Context: I want to update a table called "Projects" and change the project number from 10 to 45 where the project name is "Website". This Project table has a PK (pnumber attribute) and its related to another table called "WorksOn" that has a FK (attribute pno) related to the primary key pnumber of Project table.
The diagram would be something like this:
I was trying something like:
BEGIN TRANSACTION;
ALTER TABLE Workson DROP CONSTRAINT fk_workson_projects;
ALTER TABLE Projects DROP CONSTRAINT pk_projects;
UPDATE Projects
SET pnumber = 45
WHERE pname = 'Website';
ALTER TABLE Workson ADD CONSTRAINT fk_workson_projects FOREIGN KEY (pno) REFERENCES projects(pnumber);
ALTER TABLE Projects ADD CONSTRAINT pk_projects PRIMARY KEY (pnumber);
COMMIT;
Essentially dropping the constraints, updating the table and adding the same constraints again but I keep getting this error:
ERROR: current transaction is aborted, commands ignored until end of transaction block
SQL state: 25P02
How could I update the information by dropping the constraints and adding them back again inside a transaction?
Thank you in advance
You need to create the primary key before you can create a foreign key that references it. Looking at the error messages would have told you that.
Related
I'm trying to truncate a set of tables, but it keeps complaining about a foreign key.
but that foreign key is set to on delete Set null
to reproduce:
create table test_players (id SERIAL PRIMARY KEY, name VARCHAR(255));
create table test_items (id SERIAL PRIMARY KEY, name VARCHAR(255), player_id INTEGER FOREIGN KEY (player_id) REFERENCES test_players(id) ON DELETE SET NULL);
now if you truncate the test_players it will complain:
ERROR: cannot truncate a table referenced in a foreign key constraint
DETAIL: Table "test_items" references "test_players".
HINT: Truncate table "test_items" at the same time, or use TRUNCATE ... CASCADE.
SQL state: 0A000
what must I do to make me be able to delete test_players without deleting the test_items?
You cannot do what you are attempting. You will have to do this in 3 steps.
Update test_items and for each player_id. Well technically you don't need this, but if you don't give yourself data integrity issues.
Drop the test_items to test_players FK.
Then truncate test_players
The reason is that truncate basically just zaps the table, it does NOT process individual rows. Therefore it would not process the FK set null, it throws the error you got instead. In fact even if the child table is empty, or for that matter even if the parent is empty. See fiddle here. The fiddle also contains a function to do it, and a test for it.
The of course you could just Delete from test_players and let the triggers take care of updating test_items. Takes longer, esp if larger table, but you keep your FK. Of course there's
Recreate your FK.
I have a table named base_types that contains this constraint:
ALTER TABLE public.base_types
ADD CONSTRAINT base_type_gas_type_fk FOREIGN KEY (gas_type)
REFERENCES public.gas_types (gas_type) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED;
And I have a table named alarm_history that contains five constraints, including this one:
ALTER TABLE public.alarm_history
ADD CONSTRAINT alarm_history_device_fk FOREIGN KEY (device)
REFERENCES public.bases (alarm_device) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
DEFERRABLE INITIALLY DEFERRED;
I am trying to convert a database from one that didn't bother with anything weird and useless like constraints into one that uses them. I am beginning with this script:
delete from gas_types;
select conversion.convert_base_types();
alter table base_types validate constraint base_type_gas_type_fk;
select conversion.convert_alarm_history();
alter table alarm_history validate constraint alarm_history_base_fk;
alter table alarm_history validate constraint alarm_history_charge_fk;
alter table alarm_history validate constraint alarm_history_cooler_fk;
alter table alarm_history validate constraint alarm_history_device_fk;
alter table alarm_history validate constraint alarm_history_furnace_fk;
I duly get an error message telling me that the gas_type field in my new base_types record doesn't match anything in the gas_types table, since the gas_types table is empty. But if I comment out the base_types commands, I get 18,000 nice, shiny new records in the alarm_history table, despite the fact that every single one of them violates at least one of that table's five foreign key constraints, since all of the tables those keys are referring to are empty. I need to ensure that my converted data is consistent, and therefore I need to validate my constraints, but that's obviously not happening. Why not?
Since the constraints above are created as DEFERRABLE INITIALLY DEFERRED, they are not checked until the DML statements (your delete statement) are committed or in your case you until you explicitly validate the constraint.
This is the normal and expected operation of an initially deferred deferrable constraint.
To change this functionality within your current transaction you can issue a SET CONSTRAINTS command to alter this:
SET CONSTRAINTS alarm_history_device_fk IMMEDIATE;
delete from gas_types;
Which should raise a foreign key violation alerting you earlier that you have data dependent on the records you are tying to delete.
I have a table with a foreign key reference and I had added a on_delete_cascade condition with that foreign key.
I don't need the rows to be deleted even if the foreign key object gets deleted.
How can I change the drop condition without have to drop the column?
Just drop the conatraint and then add it back without the ON DELETE CASCADE clause:
ALTER TABLE some_table DROP CONSTRAINT some_key,
ADD CONSTRAINT some_key FOREIGN KEY (id) REFERENCES tab(a_id);
Check what the real experts wrote by reading here:
https://www.postgresql.org/message-id/CABvLTWHdT0tTygV0-O_ZgLRRAGZAg0W4zvghfF2PshAzvkAaGg%40mail.gmail.com
I want to understand what does before update in trigger means.
I have a table called DEPT_MST where DEPT_ID is the primary key. It has 2 rows with DEPT_ID 1 and 2.
Another table EMP has columns EMP_ID as primary key and EMP_DEPT_ID which is a foreign key referencing DEPT_ID of DEPT table.
Now if I add before update trigger on EMP tables EMP_DEPT_ID column which will check if new value for EMP_DEPT_ID is present in master table DEPT if now then will insert new row with new DEPT_ID to DEPT table.
Now if I update EMP_DEPT_ID to 3 where EMP_DEPT_ID is 2 in EMP table it is giving integrity constraint violation error parent not found.
So,
Does this mean that Oracle checks for integrity constraints first and then calls the "before update" trigger?
Then how can we bypass this check and call before update trigger?
What exactly does "before update" mean here?
How can I achieve above result by using triggers and not by using explicit PL SQL block?
Thank you
Non-deferred foreign key constraints are evaluated before triggers are called, yes.
If you can declare the foreign key constraint to be deferrable (which would require dropping and re-creating it if the existing constraint is not deferrable)
ALTER TABLE emp
ADD CONSTRAINT fk_emp_dept (emp_dept_id) REFERENCES dept( dept_id )
INITIALLY DEFERRED DEFERRABLE;
In your application, you can then set the constraint to be deferrable, run your INSERT statement causing the trigger to fire and insert the parent row. Your foreign key constraint will be validated when the transaction commits.
An alternative to defining the constraint to be deferrable would be to rename the emp table to, say, emp_base, create a view named emp and then create an instead of insert trigger on emp that implements the logic of first inserting into dept and then inserting into emp_base.
So the problem I have is in my task provided to us by the Professor we are to
create tables
insert records to each table.
update and delete (minimum of 1 record) from each table
using a DB2 Script that is following the old standard where COLLECTIONS are created instead of SCHEMAS
steps 1 and 2 are done. the updates are done. my deletes are giving me a hard time. an example would be this.
CREATE TABLE UMALIK8.CAMPUS (
CAMPUS_ID VARCHAR (10) NOT NULL,
CAMPUS_NAME VARCHAR (30) NOT NULL,
MANAGER_NUM VARCHAR (10) NOT NULL,
CONSTRAINT UMALIK8.CAMPUS_PK PRIMARY KEY (CAMPUS_ID),
CONSTRAINT UMALIK8.CAMPUS_FK FOREIGN KEY (MANAGER_NUM)
REFERENCES UMALIK8.MANAGER(MANAGER_NUM)
ON DELETE CASCADE);
INSERT INTO UMALIK8.CAMPUS (CAMPUS_ID, CAMPUS_NAME, MANAGER_NUM)
VALUES ('King', 'King Campus', 'M021386');
DELETE FROM UMALIK8.CAMPUS
WHERE CAMPUS_ID = 'King';
so when I try to delete it, it says delete prevented by referential constraint "roomassign_fk" which doesn't make sense to me because the roomassign table is like 3 or 4 tables AFTER the campus table, the campus is the parent table, and the manager number is from the manager table and the parent table for manager table is Employee table....all throughout the delete script im getting referential errors and I don't know why. Even in my adult table but my adult table has no foreign keys, its only got a primary key on its own, and its got a bunch of child tables....
Now the order of my script is
Tables,
Inserts,
Updates,
Deletes
all separated from each other in one long script
any idea how to fix this? what am i doing wrong?
your help is greatly appreciated, thanks!
As discussed on the comments with the OP turns out that the issue is about a trigger on the table CAMPUS. As the OP asked I'm putting this as an answer.
Is it possible to exist on this table UMALIK8.CAMPUS a trigger which is inserting registries in a table that has an FK to it?
What I mean with a trigger is that if your table has an after insert trigger that would mean something like this: you run the insert command on CAMPUS, after the insert happens the DB2 will call the trigger and insert in a ROOM (i think that is the name of other table given the FK name) one registry which will be linked (by FK) to the one you just inserted on CAMPUS, then if you try to delete the registry on CAMPUS the referential constraint "roomassign_fk" will happen because you have a child registry that is linked to the one in CAMPUS