Does designating a foreign key automatically take care of updates to the foreign table's value? - sql

I have two tables: student and faculty
I added a column to the student table that is a foreign key that references a column in faculty.
Let's say that a faculty's id changes. Based on my code below, will my student table update accordingly? Or do I need to do anything extra to ensure that it updates? For example, pretend that James's id updates from 1 to 99. Will the advisorid column of student update accordingly?
Note - I am using LINQPad and I have no way to test this because when I try to make a change to the referenced table I get an Error 547: The UPDATE statement conflicted with the REFERENCE constraint "FK__enroll__studenti__178D7CA5". The conflict occurred in database "tempdb", table "dbo.enroll", column 'studentid'.
alter table student
add advisorid int foreign key(advisorid) references faculty(facultyid);
update student set advisorid = 1 where studentid = 1;
select * from student
select * from faculty;

As you've seen, by default, updates on the key a foreign key is based of do no propagate to the dependent columns. You can get such a behavior by specifying an on update clause:
alter table student
add advisorid int foreign key(advisorid) references faculty(facultyid)
on update cascade;
EDIT:
To answer the question in the comments, the behavior could also be defined when deleting a row:
alter table student
add advisorid int foreign key(advisorid) references faculty(facultyid)
on delete cascade
on update cascade;

In Oracle ON UPDATE CASCADE does not work. Here I will demonstrate an alternative update scenario.
Instead of specifying ON UPDATE CASCADE it is possible to deferring the check of a contraint to the end of a transaction. Therefore the constraint must be DEFERRABLE. Unfortuantely the constraint could not be modified so that it must dropped and recreated.
Here is an Example:
CREATE TABLE parent_ (
pid NUMBER CONSTRAINT pk_parent PRIMARY KEY,
c1 VARCHAR2(50)
);
CREATE TABLE child_ (
cid NUMBER,
pid NUMBER CONSTRAINT fk_child_parent REFERENCES parent_(pid) ON DELETE CASCADE, --DEFERRABLE,
c1 VARCHAR2(50)
);
INSERT INTO parent_ VALUES (1, 'two');
INSERT INTO child_ VALUES (2, 1, 'two');
COMMIT;
An update of the primary key or foreign key will lead to an oracle exception
UPDATE parent_ SET pid = 2
Fehlerbericht -
SQL-Fehler: ORA-02292: integrity constraint (ME.FK_CHILD_PARENT) violated - child record found
02292. 00000 - "integrity constraint (%s.%s) violated - child record found"
*Cause: attempted to delete a parent key value that had a foreign
dependency.
*Action: delete dependencies first then parent or disable constraint.
UPDATE child_ SET pid = 2
Fehlerbericht -
SQL-Fehler: ORA-02291: integrity constraint (ME.FK_CHILD_PARENT) violated - parent key not found
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause: A foreign key value has no matching primary key value.
*Action: Delete the foreign key or add a matching primary key.
Now the foreign key will be re-created as deferrable. It will still lead to foreign key constraint violations but it can be set to deferred per session. The advantage is that all other session still behave as before.
ALTER TABLE child_ DROP CONSTRAINT fk_child_parent;
ALTER TABLE child_ ADD CONSTRAINT fk_child_parent FOREIGN KEY (pid) REFERENCES parent_(pid) ON DELETE CASCADE DEFERRABLE;
ALTER SESSION SET CONSTRAINTS = DEFERRED;
UPDATE parent_ SET pid = 2;
UPDATE child_ SET pid = 2;
COMMIT;
ALTER SESSION SET CONSTRAINTS = IMMEDIATE;
The DEFERRABLE attribute can also be set when creating a foreign key (also inline). Find more on that in the official documentation

Related

I have a problem with this query in Postgres

I have a problem with this table in Postgres, it give me this error:
ERROR: cannot use subquery in check constraint
LINE 66: check(Artista in(Select ID_Artista
create table DirigeF(
Artista int references Artista(ID_Artista) on delete cascade,
Film int references Film(ID_Contenuto) on delete cascade,
check(Artista in(Select ID_Artista
from Artista
where tipologia='REGISTA'or'AR')),
constraint DirigeF_PK primary key(Artista, Film)
);
I want to check that Artista in table DirigeF has tipologia='REGISTA' from another table.
As the error suggests, you cannot do this with a check constraint. One option is a trigger. Another is a foreign key constraint -- but that needs to be carefully arranged.
First you need a column that indicates whether the type in Artista is "REGISTA" or "AR". That would be:
alter table artista add is_regista_ar bool generated always as
(tipologia in ('REGISTA', 'AR'));
Then create a unique constraint or index:
alter table artista add unq_artista_tipologia_id
unique (is_regista_ar, id_artista)
Note: This requires Postgres 12+. But something similar can be done in earlier versions.
Then, add a boolean column to your table that is always true:
create table DirigeF (
Artista int references Artista(ID_Artista) on delete cascade,
Film int references Film(ID_Contenuto) on delete cascade,
is_regista_ar bool generated always as true,
constraint fk_artista_tipo_artista foreign key (is_regista_ar, Artista) references Artista(is_regista_ar, ID_Artista),
constraint DirigeF_PK primary key (Artista, Film)
);

How to alter the table to add foreign key constraint referencing primary key of same table

When I try to alter the table to add the foreign constraint, it is throwing the below error
Msg 547, Level 16, State 0, Line 1
The ALTER TABLE statement conflicted with the FOREIGN KEY SAME TABLE constraint "FK_ManagerId". The conflict occurred in database "MX_STAG", table "dbo.Sales_US_User", column 'ID'.
I tried the below queries,none of them have worked.
ALTER TABLE SALES_US_USER
ADD CONSTRAINT FK_ManagerId
FOREIGN KEY (ManagerID) REFERENCES SALES_US_USER(id);
ALTER TABLE SALES_US_USER
ADD FOREIGN KEY (ManagerID) REFERENCES SALES_US_USER(id);
Please help
You've got the DDL right. That error is telling you that you have a row with a ManagerId that does not map to an Id. EG
use tempdb
go
drop table if exists sales_us_manager
go
create table sales_us_user(Id int primary key, ManagerId int)
insert into sales_us_user(id,managerId) values (1,2)
ALTER TABLE SALES_US_USER
ADD CONSTRAINT FK_ManagerId
FOREIGN KEY (ManagerID) REFERENCES SALES_US_USER(id);
--Msg 547, Level 16, State 0, Line 12
--The ALTER TABLE statement conflicted with the FOREIGN KEY SAME TABLE constraint "FK_ManagerId". The conflict occurred in database "tempdb", table "dbo.sales_us_user", column 'Id'.
select *
from SALES_US_USER
where ManagerId not in
(select id from SALES_US_USER )
You need to delete both table data before updated database with your new migration. One of the common mistakes that you add a FK (foreign key) from table to another while any on these table contains data. The constraint happens because the FK can't be null and while you are adding the new migration the database find that the new column that will be created will be null so, delete the data in both tables first.
The issue got resolved after finding and updating the rows with an an invalid ManagerId, and then created the constraint.

Do foreign keys gets inserted when primary key is inserted?

A very basic question I'm confused about, similar to UPDATE and DELETE CASCADE, do foreign keys gets inserted automatically when a referenced table's primary key is inserted?
Or are they simply a constraint that tells to check the primray key that is being reference and if present add, else error.
As a example, I'm asking about something like this:
...
CONSTRAINT idFK
FOREIGN KEY(id)
REFERENCES Users(id)
ON DELETE CASCADE
ON UPDATE CASCADE
...
Here, will id in this table automatically get inserted when an id is inserted in Users table?
when you insert a record in "Users" table , nothing inserted in any other tables.
when you insert a record in a table with foreign key, the value of foreign key field just will check with the primary key value in parent(Here "Users") table.

SQL Update error. FK Conflict

I am trying to change the name of a group from ASSY to Manufacturing but am running into some dificulties. It is on a sql server database. I ran the query below.
Update groups
set group_code= 'Manufacturing'
where site_code = 'TMMBC' and group_code = 'ASSY' and group_description = 'Manufacturing'
But it returned with this error - "The UPDATE statement conflicted with the REFERENCE constraint "user_groups_FK_2". The conflict occurred in database "eci", table "dbo.user_groups"."
Is there a way I can update both tables at the same time to bypass this error?
Is there a way I can update both tables at the same time to bypass
this error?
Yes. You can define the foreign key to cascade on update.
I would consider restructuring it so that groups has an integer surrogate key though and have the textual description as a separate column.
This avoids having to repeat the relatively long string Manufacturing possibly many times in the child table.
Assuming your definition for table user_groups looks something like:
create table dbo.user_groups (
group_code varchar(100),
-- other fields
constraint user_groups_fk_2 foreign key (group_code) references dbo.groups (group_code)
);
You would change the table definition to have the foreign key cascade, like:
create table dbo.user_groups (
group_code varchar(100),
-- other fields
constraint user_groups_fk_2 foreign key (group_code) references dbo.groups (group_code) on delete cascade on update cascade
);
Or through ALTER TABLE statements:
alter table dbo.user_groups drop constraint user_groups_fk_2;
alter table dbo.user_groups add constraint user_groups_fk_2 foreign key (group_code) references dbo.groups (group_code) on delete cascade on update cascade;

Oracle parents key not found

Im trying to add a constraint to a reservation table, the reservation can either be for a flight or accommodation or both.
First 4 records booked inward flight, outward flight and accommodation
Next 4 records booked a flight only and have acc_id set to NULL
Following 2 records booked only accommodation, hence in flight, out flight and seats are set to null.
Here are my constraints for this table
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT HOLIDAY_PK PRIMARY KEY (RESV_ID);
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT CUSTOMER_FK FOREIGN KEY (BOOKING_CUS_ID) REFERENCES CUSTOMER (CUS_ID);
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT STAFF_FK3 FOREIGN KEY (EMP_ID) REFERENCES STAFF (EMP_ID);
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT FLIGHT_FK FOREIGN KEY (IN_FLIGHT_ID) REFERENCES FLIGHT (FLI_ID);
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT FLIGHT_FK1 FOREIGN KEY (OUT_FLIGHT_ID) REFERENCES FLIGHT (FLI_ID);
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT ACC_FK FOREIGN KEY (ACC_ID) REFERENCES ACCOMMODATION (ACC_ID);
and the only constraint that is yielding an error is;
ALTER TABLE HOLIDAY_RESERVATION ADD CONSTRAINT FLIGHT_FK1 FOREIGN KEY (OUT_FLIGHT_ID) REFERENCES FLIGHT (FLI_ID);
I get
ERROR at line 1:
ORA-02298: cannot validate (U1146815.FLIGHT_FK1) - parent keys not found
What seems to be the problem? i understand that it has to do with orphan childs, but i am setting nulls so i dont understand, please advise
The error indicates that the FLIGHT table does not have an entry for at least one of the FLI_ID values between 11 and 18. You'd need to insert a row in the FLIGHT table for whatever flights are missing or update your table to have a different OUT_FLIGHT_ID.
Delete all the rows from the child table which is being used to alter the column for having the references.
ALTER TABLE sales ADD CONSTRAINT sales_time_fk
FOREIGN KEY (time_id) REFERENCES times (time_id)
RELY DISABLE NOVALIDATE;