Generate Delete Statement from Foreign Key Relationships in SQL 2008

Generate Delete Statement From Foreign Key Relationships in SQL 2008?

DELETE statements generated for use in SP with parameter, and as ON DELETE triggers:
(this variant supports single column FKs only)

SELECT 'DELETE '+detail.name+' WHERE '+dcolumn.name+' = @'+mcolumn.name AS stmt, 
'DELETE ' + detail.name + ' FROM ' + detail.name + ' INNER JOIN deleted ON ' +
detail.name + '.' + dcolumn.name + ' = deleted.' + mcolumn.name AS trg
FROM sys.columns AS mcolumn
INNER JOIN sys.foreign_key_columns ON mcolumn.object_id =
sys.foreign_key_columns.referenced_object_id
AND mcolumn.column_id = sys.foreign_key_columns.referenced_column_id
INNER JOIN sys.tables AS master ON mcolumn.object_id = master.object_id
INNER JOIN sys.columns AS dcolumn
ON sys.foreign_key_columns.parent_object_id = dcolumn.object_id
AND sys.foreign_key_columns.parent_column_id = dcolumn.column_id
INNER JOIN sys.tables AS detail ON dcolumn.object_id = detail.object_id
WHERE (master.name = N'MyTableName')

Delete from a table with many foreign keys

The delete cascade would be a good solution for a "main" table.

To avoid altering manually all your tables, you can use a script, as found here with a minor change (last line, change <yourTable> by your table Name).

select
DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema +
'].[' + ForeignKeys.ForeignTableName +
'] DROP CONSTRAINT [' + ForeignKeys.ForeignKeyName + ']; '
, CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema +
'].[' + ForeignKeys.ForeignTableName +
'] WITH CHECK ADD CONSTRAINT [' + ForeignKeys.ForeignKeyName +
'] FOREIGN KEY([' + ForeignKeys.ForeignTableColumn +
']) REFERENCES [' + schema_name(sys.objects.schema_id) + '].[' +
sys.objects.[name] + ']([' +
sys.columns.[name] + ']) ON DELETE CASCADE; '
from sys.objects
inner join sys.columns
on (sys.columns.[object_id] = sys.objects.[object_id])
inner join (
select sys.foreign_keys.[name] as ForeignKeyName
,schema_name(sys.objects.schema_id) as ForeignTableSchema
,sys.objects.[name] as ForeignTableName
,sys.columns.[name] as ForeignTableColumn
,sys.foreign_keys.referenced_object_id as referenced_object_id
,sys.foreign_key_columns.referenced_column_id as referenced_column_id
from sys.foreign_keys
inner join sys.foreign_key_columns
on (sys.foreign_key_columns.constraint_object_id
= sys.foreign_keys.[object_id])
inner join sys.objects
on (sys.objects.[object_id]
= sys.foreign_keys.parent_object_id)
inner join sys.columns
on (sys.columns.[object_id]
= sys.objects.[object_id])
and (sys.columns.column_id
= sys.foreign_key_columns.parent_column_id)
) ForeignKeys
on (ForeignKeys.referenced_object_id = sys.objects.[object_id])
and (ForeignKeys.referenced_column_id = sys.columns.column_id)
where (sys.objects.[type] = 'U')
and (sys.objects.[name] = '<yourTable>')

You copy the first column result in a Management Studio query window, execute, then do the same with the second column, and voilà, you're done.

How to remove foreign key constraint in sql server?

Try following

ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>

Refer : http://www.w3schools.com/sql/sql_foreignkey.asp

How to generate DELETE statements in PL/SQL, based on the tables FK relations?

(My first answer became too long and difficult to edit, and it got Community Wikified, which is really annoying. Here is the latest version of the script.)

This script attempts to perform a cascading delete through recursion. It should avoid infinite loops when there are circular references. But it requires that all circular referential constraints have ON DELETE SET NULL or ON DELETE CASCADE.

CREATE OR REPLACE PROCEDURE delete_cascade(
table_owner VARCHAR2,
parent_table VARCHAR2,
where_clause VARCHAR2
) IS
/* Example call: execute delete_cascade('MY_SCHEMA', 'MY_MASTER', 'where ID=1'); */

child_cons VARCHAR2(30);
parent_cons VARCHAR2(30);
child_table VARCHAR2(30);
child_cols VARCHAR(500);
parent_cols VARCHAR(500);
delete_command VARCHAR(10000);
new_where_clause VARCHAR2(10000);

/* gets the foreign key constraints on other tables which depend on columns in parent_table */
CURSOR cons_cursor IS
SELECT owner, constraint_name, r_constraint_name, table_name, delete_rule
FROM all_constraints
WHERE constraint_type = 'R'
AND delete_rule = 'NO ACTION'
AND r_constraint_name IN (SELECT constraint_name
FROM all_constraints
WHERE constraint_type IN ('P', 'U')
AND table_name = parent_table
AND owner = table_owner)
AND NOT table_name = parent_table; -- ignore self-referencing constraints


/* for the current constraint, gets the child columns and corresponding parent columns */
CURSOR columns_cursor IS
SELECT cc1.column_name AS child_col, cc2.column_name AS parent_col
FROM all_cons_columns cc1, all_cons_columns cc2
WHERE cc1.constraint_name = child_cons
AND cc1.table_name = child_table
AND cc2.constraint_name = parent_cons
AND cc1.position = cc2.position
ORDER BY cc1.position;
BEGIN
/* loops through all the constraints which refer back to parent_table */
FOR cons IN cons_cursor LOOP
child_cons := cons.constraint_name;
parent_cons := cons.r_constraint_name;
child_table := cons.table_name;
child_cols := '';
parent_cols := '';

/* loops through the child/parent column pairs, building the column lists of the DELETE statement */
FOR cols IN columns_cursor LOOP
IF child_cols IS NULL THEN
child_cols := cols.child_col;
ELSE
child_cols := child_cols || ', ' || cols.child_col;
END IF;

IF parent_cols IS NULL THEN
parent_cols := cols.parent_col;
ELSE
parent_cols := parent_cols || ', ' || cols.parent_col;
END IF;
END LOOP;

/* construct the WHERE clause of the delete statement, including a subquery to get the related parent rows */
new_where_clause :=
'where (' || child_cols || ') in (select ' || parent_cols || ' from ' || table_owner || '.' || parent_table ||
' ' || where_clause || ')';

delete_cascade(cons.owner, child_table, new_where_clause);
END LOOP;

/* construct the delete statement for the current table */
delete_command := 'delete from ' || table_owner || '.' || parent_table || ' ' || where_clause;

-- this just prints the delete command
DBMS_OUTPUT.put_line(delete_command || ';');

-- uncomment if you want to actually execute it:
--EXECUTE IMMEDIATE delete_command;

-- remember to issue a COMMIT (not included here, for safety)
END;

Delete from multiple table with foreign keys

First, you should look out for all relationships and then you could just run a DELETE statement against the referenced tables based on the Keys (IDs) from your main query. A basic idea could be:

-- how many tables and references? Just to be sure.
EXEC sp_fkeys 'Job'

-- required query for deleting relationships
DELETE FROM ForeignTable WHERE JobId IN (SELECT Id FROM Job WHERE [....])
DELETE FROM ForeignTable2 WHERE JobId IN (SELECT Id FROM Job WHERE [....])

-- main query
DELETE FROM [JOB] WHERE Id IN (SELECT Id FROM [JOB] WHERE Name=@Name AND Title=@Title AND Zip=@Zip AND Id<>@Id)

Hope it helps.

SQL DROP TABLE foreign key constraint

No, this will not drop your table if there are indeed foreign keys referencing it.

To get all foreign key relationships referencing your table, you could use this SQL (if you're on SQL Server 2005 and up):

SELECT * 
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

and if there are any, with this statement here, you could create SQL statements to actually drop those FK relations:

SELECT 
'ALTER TABLE [' + OBJECT_SCHEMA_NAME(parent_object_id) +
'].[' + OBJECT_NAME(parent_object_id) +
'] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')


Related Topics



Leave a reply



Submit