我正在寻找一种方法来暂时关闭所有数据库约束(例如表之间的关系)。
我需要将一个数据库中的表使用 INSERT 命令复制到另一个数据库中。 我知道可以通过按正确顺序执行命令来实现此操作(以避免破坏关系)。
但如果能够在操作完成后暂时关闭并重新启用检查约束条件,那将更加容易。
这种做法可行吗?
我正在寻找一种方法来暂时关闭所有数据库约束(例如表之间的关系)。
我需要将一个数据库中的表使用 INSERT 命令复制到另一个数据库中。 我知道可以通过按正确顺序执行命令来实现此操作(以避免破坏关系)。
但如果能够在操作完成后暂时关闭并重新启用检查约束条件,那将更加容易。
这种做法可行吗?
-- Disable the constraints on a table called tableName:
ALTER TABLE tableName NOCHECK CONSTRAINT ALL
-- Re-enable the constraints on a table called tableName:
ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL
---------------------------------------------------------
-- Disable constraints for all tables in the database:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
-- Re-enable constraints for all tables in the database:
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'
---------------------------------------------------------
您可以禁用FK和CHECK约束,但只能在SQL 2005及以上版本中实现。请查看ALTER TABLE。
ALTER TABLE foo NOCHECK CONSTRAINT ALL
或者ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column
主键和唯一约束不能被禁用,但如果我理解正确的话,这应该是可以接受的。
如果你想要验证你没有破坏你的关系并且引入了孤立节点,那么当你重新启用检查时,可以进行验证。
ALTER TABLE foo CHECK CONSTRAINT ALL
或者ALTER TABLE foo CHECK CONSTRAINT FK_something
那么您可以返回并针对任何选中的列执行更新,如下所示:
UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc
在那个时候的任何错误都是由于未能满足限制条件造成的。
您实际上可以通过一个SQL命令禁用所有数据库约束,并通过调用另一个单个命令重新启用它们。请参阅:
我目前正在使用SQL Server 2005工作,但我几乎确定这种方法也适用于SQL 2000。
禁用和启用所有外键
CREATE PROCEDURE pr_Disable_Triggers_v2
@disable BIT = 1
AS
DECLARE @sql VARCHAR(500)
, @tableName VARCHAR(128)
, @tableSchema VARCHAR(128)
-- List of all tables
DECLARE triggerCursor CURSOR FOR
SELECT t.TABLE_NAME AS TableName
, t.TABLE_SCHEMA AS TableSchema
FROM INFORMATION_SCHEMA.TABLES t
ORDER BY t.TABLE_NAME, t.TABLE_SCHEMA
OPEN triggerCursor
FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema
WHILE ( @@FETCH_STATUS = 0 )
BEGIN
SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] '
IF @disable = 1
SET @sql = @sql + ' DISABLE TRIGGER ALL'
ELSE
SET @sql = @sql + ' ENABLE TRIGGER ALL'
PRINT 'Executing Statement - ' + @sql
EXECUTE ( @sql )
FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema
END
CLOSE triggerCursor
DEALLOCATE triggerCursor
0 = 获取成功
-1 = 获取失败
-2 = 获取的行丢失
在循环内部,代码根据意图构建ALTER TABLE命令,具体取决于是禁用还是启用外键约束(使用CHECK或NOCHECK关键字)。然后,该语句作为消息打印出来,以便观察其进度,然后执行该语句。最后,在迭代完所有行之后,存储过程关闭并释放游标。
sql-server
和sql-server-2005
标签来判断的。我给出的链接是针对 SQL Server 的,但你也可以在 Oracle 中做同样的事情 - 参见这里和这里。你也可以在 PostgreSQL 中实现。 - brichins