Sql-Server
級聯主鍵更新到所有引用外鍵
是否可以通過在引用它的所有外鍵之間級聯更新來更新主鍵列值?
# 編輯 1: 當我執行 followinq 查詢時
select * from sys.foreign_keys where referenced_object_id=OBJECT_ID('myTable')
,我看到 update_referential_action 設置為 0。因此更新我的主鍵列後不採取任何行動。如何更新外鍵以使其ON CASCADE UPDATE?
# 編輯 2:
為了編寫腳本創建或刪除架構中的所有外鍵,請執行以下腳本(取自此處)
DECLARE @schema_name sysname; DECLARE @table_name sysname; DECLARE @constraint_name sysname; DECLARE @constraint_object_id int; DECLARE @referenced_object_name sysname; DECLARE @is_disabled bit; DECLARE @is_not_for_replication bit; DECLARE @is_not_trusted bit; DECLARE @delete_referential_action tinyint; DECLARE @update_referential_action tinyint; DECLARE @tsql nvarchar(4000); DECLARE @tsql2 nvarchar(4000); DECLARE @fkCol sysname; DECLARE @pkCol sysname; DECLARE @col1 bit; DECLARE @action char(6); DECLARE @referenced_schema_name sysname; DECLARE FKcursor CURSOR FOR select OBJECT_SCHEMA_NAME(parent_object_id) , OBJECT_NAME(parent_object_id), name, OBJECT_NAME(referenced_object_id) , object_id , is_disabled, is_not_for_replication, is_not_trusted , delete_referential_action, update_referential_action, OBJECT_SCHEMA_NAME(referenced_object_id) from sys.foreign_keys order by 1,2; OPEN FKcursor; FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name , @referenced_object_name, @constraint_object_id , @is_disabled, @is_not_for_replication, @is_not_trusted , @delete_referential_action, @update_referential_action, @referenced_schema_name; WHILE @@FETCH_STATUS = 0 BEGIN IF @action <> 'CREATE' SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + ' DROP CONSTRAINT ' + QUOTENAME(@constraint_name) + ';'; ELSE BEGIN SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + CASE @is_not_trusted WHEN 0 THEN ' WITH CHECK ' ELSE ' WITH NOCHECK ' END + ' ADD CONSTRAINT ' + QUOTENAME(@constraint_name) + ' FOREIGN KEY ('; SET @tsql2 = ''; DECLARE ColumnCursor CURSOR FOR select COL_NAME(fk.parent_object_id, fkc.parent_column_id) , COL_NAME(fk.referenced_object_id, fkc.referenced_column_id) from sys.foreign_keys fk inner join sys.foreign_key_columns fkc on fk.object_id = fkc.constraint_object_id where fkc.constraint_object_id = @constraint_object_id order by fkc.constraint_column_id; OPEN ColumnCursor; SET @col1 = 1; FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol; WHILE @@FETCH_STATUS = 0 BEGIN IF (@col1 = 1) SET @col1 = 0; ELSE BEGIN SET @tsql = @tsql + ','; SET @tsql2 = @tsql2 + ','; END; SET @tsql = @tsql + QUOTENAME(@fkCol); SET @tsql2 = @tsql2 + QUOTENAME(@pkCol); FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol; END; CLOSE ColumnCursor; DEALLOCATE ColumnCursor; SET @tsql = @tsql + ' ) REFERENCES ' + QUOTENAME(@referenced_schema_name) + '.' + QUOTENAME(@referenced_object_name) + ' (' + @tsql2 + ')'; SET @tsql = @tsql + ' ON UPDATE ' + CASE @update_referential_action WHEN 0 THEN 'NO ACTION ' WHEN 1 THEN 'CASCADE ' WHEN 2 THEN 'SET NULL ' ELSE 'SET DEFAULT ' END + ' ON DELETE ' + CASE @delete_referential_action WHEN 0 THEN 'NO ACTION ' WHEN 1 THEN 'CASCADE ' WHEN 2 THEN 'SET NULL ' ELSE 'SET DEFAULT ' END + CASE @is_not_for_replication WHEN 1 THEN ' NOT FOR REPLICATION ' ELSE '' END + ';'; END; PRINT @tsql; IF @action = 'CREATE' BEGIN SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + CASE @is_disabled WHEN 0 THEN ' CHECK ' ELSE ' NOCHECK ' END + 'CONSTRAINT ' + QUOTENAME(@constraint_name) + ';'; PRINT @tsql; END; FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name , @referenced_object_name, @constraint_object_id , @is_disabled, @is_not_for_replication, @is_not_trusted , @delete_referential_action, @update_referential_action, @referenced_schema_name; END; CLOSE FKcursor; DEALLOCATE FKcursor;
要生成 DROP 外鍵腳本,請將聲明子句中的 @action 值修改為等於“DROP”:
DECLARE @action char(6) = 'DROP';
如果您已將外鍵約束定義為
ON UPDATE CASCADE
,則更改的主鍵值應向下級聯到具有該約束的所有外鍵。如果您沒有
ON UPDATE CASCADE
約束,那麼您將需要創建腳本來完成更新。編輯:由於您沒有
ON UPDATE CASCADE
約束,但是您想要進行設置,因此需要做一些工作。SQL Server 不支持將約束更改為新設置。有必要遍歷每個對 PK 表有 FK 約束的表。對於每個帶有 FK 的表:
- ALTER TABLE 刪除現有的 FK 約束。
- 再次 ALTER TABLE 為有問題的 FK 創建 ON UPDATE CASCADE 約束。
這需要一些努力,但會導致為您的案例正確設置約束。
編輯 2:您需要的資訊在 sys.foreign_keys 中找到。您可以從該表中進行選擇以獲取所需的所有資訊。
約翰保羅庫克的文章可以在這裡找到:
此程式碼將刪除並在數據庫中創建所有 FK 約束。您應該能夠從中工作以僅在數據庫中進行所需的更改。