web-dev-qa-db-ja.com

制約を一時的に無効にする(MS SQL)

私は一時的にすべてのDBの制約(例えばテーブルの関係)を無効にする方法を探しています。

あるDBのテーブルを別のDBに(INSERTを使って)コピーする必要があります。 (関係を壊さないように)適切な順序でコマンドを実行することでこれを達成できることを私は知っています。

しかし、チェック制約を一時的にオフにして、操作の終了後にそれをオンに戻すことができれば、もっと簡単になるでしょう。

これは可能ですか?

193
Maciej

FKとCHECKの制約を無効にすることができます sQL 2005以降のみALTER TABLE を参照してください。

ALTER TABLE foo NOCHECK CONSTRAINT ALL

または

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

主キーと一意の制約を無効にすることはできませんが、正しく理解していれば問題ありません。

205
gbn
-- 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'
---------------------------------------------------------
192
Donal

そして、あなたがあなたのチェックを再武装したならば、あなたがあなたの関係を壊して孤児を紹介したことがないことを確かめたいならば。

ALTER TABLE foo CHECK CONSTRAINT ALL

または

ALTER TABLE foo CHECK CONSTRAINT FK_something

その後、戻って実行して、チェックされた列に対して更新を行うことができます。

UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc

その時点でエラーが発生した場合は、制約を満たしていないことが原因です。

57

実際には、単一のSQLコマンドですべてのデータベース制約を無効にし、別の単一コマンドを呼び出してそれらを再び有効にすることができます。見る:

私は現在SQL Server 2005で作業していますが、このアプローチがSQL 2000でも機能することはほぼ確実です。

16
kristof

すべての外部キーの無効化と有効化

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文が実行されます。このFETCHステートメントは、最初の行のデータをローカル変数@foreignKeyNameと@tableNameに読み込みます。カーソルをループしているときは、@@ FETCH_STATUSの値0を確認できます。これは、フェッチが成功したことを示します。これは、行セットから連続した各外部キーを取得できるように、ループは前進し続けることを意味します。 @@ FETCH_STATUSは、接続上のすべてのカーソルに使用できます。したがって、複数のカーソルをループしている場合は、FETCHステートメントの直後のステートメントで@@ FETCH_STATUSの値を確認することが重要です。 @@ FETCH_STATUSは、接続における最新のFETCH操作のステータスを反映します。 @@ FETCH_STATUSの有効値は次のとおりです。

0 = FETCHは成功しました
- 1 = FETCHは失敗しました
- 2 =フェッチされた行がありません

ループ内では、(CHECKまたはNOCHECKキーワードを使用して)外部キー制約を無効にするか有効にするかによって、ALTER TABLEコマンドの作成方法が異なります。そのステートメントはメッセージとして出力されるので、進行状況を確認してからステートメントを実行します。最後に、すべての行が反復処理されると、ストアドプロシージャはカーソルを閉じて割り当てを解除します。

参照してください MSDNマガジンから制約とトリガを無効にする

2
0x49D1