すべてのテーブルからすべての制約を削除するにはどうすればよいですか?


30

SQL Serverデータベース内のすべてのテーブルから、すべての既定の制約、チェック制約、一意の制約、主キー、および外部キーをすべて削除したい。からすべての制約名を取得する方法を知っていますsys.objectsが、どのようにALTER TABLE部品に入力しますか?


好奇心から、そのような要求のコンテキストは何ですか?機能的な依存関係(インデックス付きビュー、FKのカスケードイベント、IGNORE_DUP_KEY = ONのUQ)がどのように対処されるのか疑問に思っています。
ソロモンラツキー

3
@srutzky Stack Overflowで尋ねられましたが、ここでよりクリーンで標準的なバージョンを作成することにしました。とにかく、これは一般的な要求であり、多くの場合、データベースのクリーンアップ(最初からやり直す、誤ってマスターに入れられたオブジェクトのクリーンアップなど)の大きなタスクの一部です。制約を削除してもこれらの機能的な依存関係が影響を受けることはありません。実際、ほとんどの場合、大きな全体像がテーブルを切り捨てたり削除したりしていると思われます。最初に制約をドロップすると、それが可能になります。
アーロンバートランド

回答:


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)
ダニエルハットマッハー

1
@Danielの良い点は、SQL Serverが新しい制約タイプを導入するまでは、おそらくORDER BYタイプで十分です。
アーロンバートランド

6

受け入れられた答えから始め、動的SQLで完全なSQLステートメントを構築するのではなく、whileループを使用するように構造を変更しました。これにはいくつかの理由があります。

クエリは、大きな@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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.