Cascade delete rows from multiple tables in SQL - sql-server

I have 3 tables like this:
Table1: Id, Name
Table2: Id, Name
Table3: Id, EntityName (nvarchar), EntityId (int)
There are no foreign keys on Table3. I am inserting rows for Table1 and Table2 to Table3 like this:
Id
EntityName
EntityId
OtherColumn(s)
1
Table1
1
...
2
Table2
1
...
3
Table2
2
...
When I delete a row from Table1 or Table2, how can I cascade it from Table3?

You can create a delete trigger on each table to delete the matching rows from table3, for example:
create trigger Table1Delete on dbo.table1
for delete
as
if ##RowCount = 0 return
set nocount on
delete from t3
from deleted d
join table3 t3 on t3.EntityName='Table1' and d.Id=t3.EntityId
And a similar one for Table2

This is how you could write queries to "mimic" cascade delete:
delete from table2 t2
where exists(select 1 from table3
where t2.id = entityId and EntityName = 'Table2')
delete from table1 t1
where exists(select 1 from table3
where t1.id = entityId and EntityName = 'Table1')
If you have some condition upon which you delete from table3 you should also inlcude it in those queries.
UPDATE
To do it automatically, you need todefine foreign keys with cascade delete action. But only one foreign key can be defined on column, thus you'd need to have two columns - one for referencing table1 and second for referncing table2. Then on both you'd need define cascade delete.
With current design (one column to reference multiple tables) this isn't possible and you would need to work around (as suggested implement delete trigger on table).

Related

Select records in one table where a field in this table is included in another table

Basically I have two tables. Table1 has millions of rows. Table2 has very few rows.
Table1 has field1 which is a product ID (not unique). Table2 has field2 which is just a list of productID's that need to be included from Table1 in the select statement.
SELECT Table1.*
FROM Table1
Join Table2 ON Table2.field2 = table1.field1

With TSQL, how do I create a record in Table2 using GUID from existing record in Table1

Table1 contains Work Orders and Table2 contains Installers. I would like to insert a record into Table2 for Work Order 3906 in Table1 using unique identifier for that Work Order such that Table1GUID = Table2GUID . I'll worry about populating the new record later (all columns in Table2 can be blank for now except GUID which must be identical to corresponding GUID from Table1). Records for Table1 and Table2 are one to one.
This is NOT working: (0 row(s) affected)
INSERT INTO Table2 (Table2GUID)
SELECT Table1GUID FROM Table1
WHERE Table1.WOnumber = '3906'
This doesn't work either:
INSERT INTO Table2 (Table2GUID)
SELECT Table1GUID FROM Table1
INNER JOIN Table2 ON Table2GUID = Table1GUID
WHERE Table1.WOnumber = '3906'

How to represent OR table using JOIN

I have a query having 4 tables Table1, Table2, Table3 and Table4.
Table1 is master table having IDs
Table2 is child table with FK relationship with Table1 and has a column called Tag.
Table3 is child table with FK relationship with Table1 and has a column called Code
Table4 is child table with FK relationship with Table1 and has column called Code2
Now I want a query to represent follow logic
Select Table1.ID
From Table1 ...
WHERE Table2.Tag IN( 1,2,3,4)
AND ( Table3.Code In (456,789) OR Table4.CODE2 in (123,897) )
I know I can have join between Table1 and Table2 get the ids for which Tag value is in (1,2,3,4). But I am not sure how to join the Table3 and Table4 to achieve the requirement.
You just keep adding joins to the child table based on the condition that the Foreign Key column in each child table equals the key of Table1
You're query should look like this
Select Table1.ID
From Table1
JOIN Table2 ON Table2.FK_ID = Table1.ID
JOIN Table3 ON Table3.FK_ID = Table1.ID
JOIN Table4 ON Table4.FK_ID = Table1.ID
WHERE Table2.Tag IN( 1,2,3,4)
AND ( Table3.Code In (456,789) OR Table4.CODE2 in (123,897) )
But with FK_ID replaced with the appropriate Foreign Key field

most efficient way to quickly delete records using a join?

What is the fastest way to delete records from a SQL Server database for a large year-end purge, when the query has to join to another table? I understand cursors are slow. Do I do
DELETE FROM table1 WHERE table1_id in (SELECT table1_id FROM table2 WHERE whatever)
Seems like it might be faster to join to the table inside the query using a different technique, something like
DELETE FROM table1 WHERE table1_id = table2
A join would be the best way to go.
I assume you have a foreign key association from table2 to table1, so you're going to want to delete from the second table before the primary table.
Example:
DELETE T2
FROM table1 T1
JOIN table2 T2 ON -- JOIN CRITERIA HERE
WHERE -- FILTER CRITERIA HERE
DELETE T1
FROM table1 T1
JOIN table2 T2 ON -- JOIN CRITERIA HERE
WHERE -- FILTER CRITERIA HERE
If you attempt to delete from the primary table first, you will likely encounter a foreign key constraint violation.
Could you add a cascade delete relationship on the foreign key then get SQL server to cascade the delete for you?
Maybe something like this would be faster.
delete from (select * FROM table1 WHERE table1_id in (SELECT table1_id FROM table2 WHERE whatever))
You can try this (should be faster than IN statement, because query stops than find first value in subquery and search next value):
DELETE t1
FROM table1 t1
WHERE EXISTS (SELECT 0
FROM table2 t2
WHERE t1.table1_id = t2.table1_id
AND whatever)
Or you can do JOIN:
DELETE t1
FROM table1 t1
JOIN table2 t2 ON t1.table1_id = t2.table1_id
WHERE whatever

SQL Server many-to-many query

I have two tables, let's call them table1 and table2. They both have a column called ID1 and ID2 which are respective PK for each of two tables.
I have also another table, called table3 which contains ID1 and ID2, establishing a many to many relation between these two tables.
What I need is to get all the records from table2 that are not related with records in table1.
Ex.
Table 1 contains a record with ID = 1
Table 2 contains two records with ID 1, 2
Table 3 contains one record with values 1 - 1
I need a query that will give me as result 2.
Can anyone suggest me a way to proceed?
Thanks
SELECT t2.ID2
FROM table2 t2
WHERE NOT EXISTS(SELECT NULL
FROM table3 t3
WHERE t3.ID2 = t2.ID2);
You could also use a LEFT JOIN:
SELECT t2.ID2
FROM table2 t2
LEFT JOIN table3 t3
ON t2.ID2 = t3.ID2
WHERE t3.ID2 IS NULL;

Resources