DELETE request on row with nested foreign keys - sql

I have a Table A that is referenced to by Table B, and Table C has references to Table B.
Such that:
Table A (pk: id)
Table B (pk: id, fk: A_id)
Table C (fk: B_id)
Every foreign key has a constraint ON_DELETE:CASCADE, however if I attempted to delete Table A - it refuses to. This is happening because rows in Table B have foreign keys pointing to Table A, and Table C has rows pointing to Table B.
I'm confident that I can resolve this issue by deleting Table B first, and then deleting Table A. However, would someone explain why this DELETE isn't possible? Surely, it should be able to perform a function of going down a 'hierarchy' of foreign keys and deleting everything in order?
Thanks

In ON DELETE CASCADE operation, if a parent row is deleted, it will first delete the child row and then the parent row so as to ensure that no references are left as foreign key
As for your question, since Table B is referring to Table A 's primary key and Table C is referring to Table B's primary key, the relationship for which on delete cascade should work is just a parent child and not beyond.

Related

How to setup table A in such way, that a only one row from table B with a certain value can have foreign key relation to a row from table A?

We have table A. Table B has foreign key to A. And now, if there is already a row in table B with attribute surname="Jordan" that has foreign key relation to a particular row in A , it will be impossible to create another row in table B with the same surname that will have relation with the same row in A.
How to solve this problem.
Create a unique index on Table B's foreign key column.
Note that this suggests Table B should probably be folded into Table A.

Check constraint references to unique column in the same table

I have a table:
ID Name ParentID
== ==== ========
1 A Null
2 B 1
3 C 2
so A is parent of B, and B is parent of C.
I need to create a constraint for column(ParentID) which does not accept a number is not exist in column (ID).
How I would do that?
You need to add Foreign Key.
ALTER TABLE table1
ADD CONSTRAINT fk_parent_id
FOREIGN KEY (parent_id) REFERENCES table1(id);
You can also create a foreign key using SSMS design as shown below. Expand table and right click on Keys - New Foreign key
Now click on the browse button of relationship and specify the colum nane of primary and foreign key table as shown below.
This is one of the way and you might select the preferred way either using query or design for creating the foreign key relationships between tables in Sql Server.

Foreign Key reference not populating in intended table

I'm having a problem referencing a Foreign Key from another table that has already been created with data imported.
ALTER TABLE CSEA_BOOK
ADD CONSTRAINT FK_BOOK_CASE_ID FOREIGN KEY (CASE_ID)
REFERENCES CSEA_CASE(CASE_ID);
I can create it just fine but when you
SELECT *
FROM CSEA_CASE a, CSEA_BOOK b
WHERE a.CASE_ID = b.CASE_ID;
everything comes back NULL where I know it should contain data.
Am I doing something out of order or Sequence?

Join query to delete a record both in child class and parent class

I need to delete a record in both child table and parent table with the reference to another column.The primary key of one table is equal to foreign key of another table.eg.table A.pkid=table B.fkid
How do I use join query or cascade to delete it.
I tried couple of queries but it shows invalid syntax.
delete from
table A table B where pkid=(SELECT fk_id from table B)
where name='SEP' from table B
delete from
table A join table B ON table A.fk_id=(SELECT pk_id FROM table B)
where name='SEP' from table B
delete from
table A join table B ON A.fk_id=B.pk_id
where name='SEP' from table B
Could you please refine my query or give me a link where I can get some help on this? Thanks a lot.
It looks like all you need is something simple:
BEGIN WORK;
DELETE FROM A WHERE fk_id IN (SELECT pk_id FROM B WHERE name = 'SEP');
DELETE FROM B WHERE name = 'SEP';
COMMIT WORK;
The alternative is to define the PK-FK relationship in the schema with the ON DELETE CASCADE option, and children will be automatically deleted on deletion of the parent.

How to constraint one column with values from a column from another table?

This isn't a big deal, but my OCD is acting up with the following problem in the database I'm creating. I'm not used to working with databases, but the data has to be stored somewhere...
Problem
I have two tables A and B.
One of the datafields is common to both tables - segments. There's a finite number of segments, and I want to write queries that connect values from A to B through their segment values, very much asif the following table structure was used:
However, as you can see the table Segments is empty. There's nothing more I want to put into that table, rather than the ID to give other table as foreign keys. I want my tables to be as simple as possible, and therefore adding another one just seems wrong.
Note also that one of these tables (A, say) is actually master, in the sense that you should be able to put any value for segment into A, but B one should first check with A before inserting.
EDIT
I tried one of the answers below:
create table A(
id int primary key identity,
segment int not null
)
create table B(
id integer primary key identity,
segment int not null
)
--Andomar's suggestion
alter table B add constraint FK_B_SegmentID
foreign key (segment) references A(segment)
This produced the following error.
Maybe I was somehow unclear that segments is not-unique in A or B and can appear many times in both tables.
Msg 1776, Level 16, State 0, Line 11 There are no primary or candidate
keys in the referenced table 'A' that match the referencing column
list in the foreign key 'FK_B_SegmentID'. Msg 1750, Level 16, State 0,
Line 11 Could not create constraint. See previous errors.
You can create a foreign key relationship directly from B.SegmentID to A.SegmentID. There's no need for the extra table.
Update: If the SegmentIDs aren't unique in TableA, then you do need the extra table to store the segment IDs, and create foreign key relationships from both tables to this table. This however is not enough to enforce that all segment IDs in TableB also occur in TableA. You could instead use triggers.
You can ensure the segment exists in A with a foreign key:
alter table B add constraint FK_B_SegmentID
foreign key (SegmentID) references A(SegmentID)
To avoid rows in B without a segment at all, make B.SegmentID not nullable:
alter table B alter column SegmentID int not null
There is no need to create a Segments table unless you want to associate extra data with a SegmentID.
As Andomar and Mark Byers wrote, you don't have to create an extra table.
You can also CASCADE UPDATEs or DELETEs on the master. Be very carefull with ON DELETE CASCADE though!
For queries use a JOIN:
SELECT *
FROM A
JOIN B ON a.SegmentID = b.SegmentID
Edit:
You have to add a UNIQUE constraint on segment_id in the "master" table to avoid duplicates there, or else the foreign key is not possible. Like this:
ALTER TABLE A ADD CONSTRAINT UNQ_A_SegmentID UNIQUE (SegmentID);
If I've understood correctly, a given segment cannot be inserted into table B unless it has also been inserted into table A. In which case, table A should reference table Segments and table B should reference table A; it would be implicit that table B ultimately references table Segments (indirectly via table A) so an explicit reference is not required. This could be done using foreign keys (e.g. no triggers required).
Because table A has its own key I assume a given segment_ID can appear in table A more than once, therefore for B to be able to reference the segment_ID value in A then a superkey would need to be defined on the compound of A_ID and segment_ID. Here's a quick sketch:
CREATE TABLE Segments
(
segment_ID INTEGER NOT NULL UNIQUE
);
CREATE TABLE A
(
A_ID INTEGER NOT NULL UNIQUE,
segment_ID INTEGER NOT NULL
REFERENCES Segments (segment_ID),
A_data INTEGER NOT NULL,
UNIQUE (segment_ID, A_ID) -- superkey
);
CREATE TABLE B
(
B_ID INTEGER NOT NULL UNIQUE,
A_ID INTEGER NOT NULL,
segment_ID INTEGER NOT NULL,
FOREIGN KEY (segment_ID, A_ID)
REFERENCES A (segment_ID, A_ID),
B_data INTEGER NOT NULL
);