是否可以通过在引用它的所有外键之间级联更新来更新主键列值?
# 编辑 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 的表:
这需要一些努力,但会导致为您的案例正确设置约束。
编辑 2:您需要的信息在 sys.foreign_keys 中找到。您可以从该表中进行选择以获取所需的所有信息。
约翰保罗库克的帖子可以在这里找到:
(http://social.technet.microsoft.com/wiki/contents/articles/2958.script-to-create-all-foreign-keys.aspx)
此代码将删除并在数据库中创建所有 FK 约束。您应该能够从中工作以仅在数据库中进行所需的更改。
你当然可以。
ON UPDATE CASCADE
就是你要找的。这是一个小方法: http ://sqlandme.com/2011/08/08/sql-server-how-to-cascade-updates-and-deletes-to-related-tables/
基本上,当您修改 PK 时,级联将出去并更新所有引用它的 FK。这可以在您的
CREATE
语句中完成,就像您正在执行CASCADE DELETE
执行此操作时请密切注意,因为据我了解,CASCADE 实际上在后台运行在隔离级别
SERIALIZABLE
(通常,SQL默认运行),因此请注意任何阻塞问题。READ COMMITTED
可以在本文中找到有关隔离级别的其他信息:http: //msdn.microsoft.com/en-us/library/ms173763.aspx
将所有外键定义为 CASCADE UPDATE
如果你还没有这样做,那么你将不得不
..当然是在交易中,并注意其他可能失败的约束