一時的に制約をオフにする(MS SQL)


208

すべてのDBの制約(テーブルの関係など)を一時的にオフにする方法を探しています。

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

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

これは可能ですか?


3
これは完全なコピーではありません。選択したテーブルをコピーしたいだけです
Maciej

これを行うことに対する私の懸念は、これがあなただけでなくすべての人に対する制約をオフにすることです。これを行う必要がある場合は、最初にデータベースをシングルユーザーモードにします。そうしないと、データ整合性の問題が発生する可能性があります。
HLGEM 2009

13
The Futureの皆さん、データベースのすべての制約を一度に無効にして再度有効にすることができます。stackoverflow.com/a/161410を
brichins

1
完了したら、制約を有効にすることを忘れないでください!
マイククリスチャン

1
@NicolasBarbulescoは十分に公正です。sql-serversql-server-2005タグを外していました。私が挙げたリンクはSQL Server用ですが、Oracleでも同じことができますここここを参照くださいPostgreSQLでも実行できます
brichins 2013年

回答:


214

FKおよびCHECK制約は、SQL 2005+でのみ無効にできますALTER TABLEを参照してください

ALTER TABLE foo NOCHECK CONSTRAINT ALL

または

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

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


10
しかし、これは一時的なものではありません。
Nicolas Barbulesco 2013年

@NicolasBarbulesco:状況によって異なります。はい、そうです
。DROP

この答えは、ソリューションの前半にすぎません。一時的に制約をオフにする簡単な方法を探していましたが、Oracleには存在しないという結論に達しました。
Nicolas Barbulesco 2013年

PKと一意制約を無効にできないことは事実ではありません。少なくとも最近のバージョンのSQL Serverでは機能します。例:techonthenet.com/sql_server/primary_keys.php
Dejan

1
オラクルの@NicolasBarbulesco?ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; //制約に違反することを行うALTER TABLE some_table ENABLE CONSTRAINT some_table_fk1;
スティーブスウィンズバーグ2015

237
-- 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'
---------------------------------------------------------

1
@kevincいいえ。あなたが一貫している限り、それは問題ではありません。
Po-ta-toe

2
引用符で囲まれた識別子を使用することは、ANSI標準設定であると私は信じています。つまり、文字列には使用しないでください。一貫性とは何の関係もありません。stackoverflow.com/questions/1992314/…を
kevinc

1
手順をありがとう!ところで、正しい大文字小文字の区別は "sp_MSforeachtable"(MS大文字)です。ありがとう!
Sielu

3
これは質問に完全に答えるので、正しい答えとしてマークされているはずです。それだけでなく、@ Donalにはワイルドカードバージョンが含まれていて、私にとって非常に役立ちました。
マットジャクソン

2
再度有効にしていただきありがとうございます。特にcheck check多くの人が忘れているダブル!
アレックス、

57

そして、あなたがチェックを再武装した後、あなたがあなたの関係を破り、孤児を導入していないことを確認したいなら、すなわち

ALTER TABLE foo CHECK CONSTRAINT ALL

または

ALTER TABLE foo CHECK CONSTRAINT FK_something

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

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

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


11
より良い方法は、ALTER TABLE FOO WITH CHECK CHECK CONSTRAINT FK_something
Cody Konior '27 / 03/27

1
ALTER TABLE foo CHECK CONSTRAINT ALLまたはALTER TABLE foo CHECK CONSTRAINT FK_somethingは制約を有効にしますが、データをチェックしません。これは、制約が信頼されないことを意味します(is_no_trusted = 1、is_disabled = 0)。
Bogdan Sahlean 2017


0

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

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 Magazineの制約とトリガーの無効化」を参照してください

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