暂时关闭约束 (MS SQL)
-
09-09-2019 - |
题
我正在寻找一种方法来暂时关闭所有数据库的约束(例如表关系)。
我需要将一个数据库的表复制(使用 INSERT)到另一个数据库。我知道我可以通过按正确的顺序执行命令(不破坏关系)来实现这一点。
但如果我可以暂时关闭检查约束并在操作完成后将其重新打开,那就更容易了。
这可能吗?
解决方案
您可以禁用FK和CHECK约束<击>仅在SQL 2005 + 行使>。请参阅 ALTER TABLE
ALTER TABLE foo NOCHECK CONSTRAINT ALL
或
ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column
主键和唯一约束不能被禁止的,但如果我理解正确的话,你这个应该没问题。
其他提示
-- 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:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
-- Re-enable constraints for all tables:
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'
---------------------------------------------------------
而且,如果你想验证你没有破坏你的关系,并介绍了孤儿,一旦你重新武装你的支票,即。
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
首先,将光标foreignKeyCursor被声明为SELECT语句 它收集外键和他们的表名的列表。接下来, 打开游标并执行语句初始提取。这个 FETCH语句将读取第一行的数据到本地 变量@foreignKeyName和@tablename。当通过循环 光标,您可以通过检查@@ FETCH_STATUS为0值,这 指示获取成功。这意味着循环将 继续往前走,因此可以得到每个连续的外键 从行集。 @@ FETCH_STATUS可对所有游标 连接。所以,如果你是通过多个游标循环,这是 重要的是检查在声明FETCH_STATUS的@@值 紧随其后的FETCH语句。 @@ FETCH_STATUS反映 对于最近的读取状态的连接操作。 对于@@ FETCH_STATUS有效值是:
0 = FETCH成功结果 -1 = FETCH是不成功的结果 -2 =,这是取出的行缺少
在循环内部,代码建立ALTER TABLE命令不同 根据意向是否禁用或启用外国 键约束(使用CHECK或NOCHECK关键字)。该声明是 然后打印为消息,以便它的进展,可以观察,然后将 语句执行。最后,当所有行的迭代 通过,所存储的过程关闭并释放光标。