如何从所有表中删除所有约束?


30

我想从SQL Server数据库的所有表中删除所有默认约束,检查约束,唯一约束,主键和外键。我知道如何从中获取所有约束名称sys.objects,但是如何填充ALTER TABLE零件?


出于好奇,这种请求的背景是什么?我想知道如何解决功能依赖性(即索引视图,FK上的级联事件以及具有IGNORE_DUP_KEY = ON的UQ)。
所罗门·鲁兹基

3
@srutzky 有人问到Stack Overflow,但我决定在此处创建一个更干净,规范的版本。无论如何,这是一个常见的请求,通常是清理数据库(重新开始,清理错误地放入主数据库的对象等)较大任务的一部分。我看不到这些功能依赖项会因删除约束而受到影响-实际上,我怀疑在大多数情况下,较大的图片也会被截断或删除表。首先删除约束可以做到这一点。
亚伦·伯特兰

Answers:


36

您可以通过加入sys.tables.object_id = sys.objects.parent_object_id这些对象类型来轻松获得此信息。

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'
  ALTER TABLE ' + QUOTENAME(s.name) + N'.'
  + QUOTENAME(t.name) + N' DROP CONSTRAINT '
  + QUOTENAME(c.name) + ';'
FROM sys.objects AS c
INNER JOIN sys.tables AS t
ON c.parent_object_id = t.[object_id]
INNER JOIN sys.schemas AS s 
ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN ('D','C','F','PK','UQ')
ORDER BY c.[type];

PRINT @sql;
--EXEC sys.sp_executesql @sql;

PRINT只是为了吸引眼球-如果您有很多限制,由于限制为8K,它可能无法显示整个脚本。在这种情况下,请参阅本技巧以获取在运行之前验证脚本的其他方法。

对输出满意后,请取消注释EXEC


3
您可能还需要确保在主键之前删除外键约束。ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Daniel Hutmacher

1
@Daniel的好处是,在SQL Server引入新的约束类型之前,ORDER BY类型可能就足够了。
亚伦·伯特兰

6

我从公认的答案开始,并修改了结构以使用while循环,而不是在动态sql中构建完整的sql语句。我更喜欢这样做有几个原因。

该查询未存储在大@sql变量中。此实现允许为输出中记录的每个约束删除“打印”。在我的单元测试中,执行似乎要快一些。

Set NoCount ON

Declare @schemaName varchar(200)
set @schemaName=''
Declare @constraintName varchar(200)
set @constraintName=''
Declare @tableName varchar(200)
set @tableName=''

While exists
(   
    SELECT c.name
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.[type] IN ('D','C','F','PK','UQ')
    and t.[name] NOT IN ('__RefactorLog', 'sysdiagrams')
    and c.name > @constraintName
)

Begin   
    -- First get the Constraint
    SELECT 
        @constraintName=min(c.name)
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.[type] IN ('D','C','F','PK','UQ')
    and t.[name] NOT IN ('__RefactorLog', 'sysdiagrams')
    and c.name > @constraintName

    -- Then select the Table and Schema associated to the current constraint
    SELECT 
        @tableName = t.name,
        @schemaName = s.name
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.name = @constraintName

    -- Then Print to the output and drop the constraint
    Print 'Dropping constraint ' + @constraintName + '...'
    Exec('ALTER TABLE [' + @schemaName + N'].[' + @tableName + N'] DROP CONSTRAINT [' + @constraintName + ']')
End

Set NoCount OFF
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.