すべてのDBの制約(テーブルの関係など)を一時的にオフにする方法を探しています。
あるDBのテーブルを別のDBに(INSERTを使用して)コピーする必要があります。コマンドを適切な順序で実行することで(関係を壊さないように)それを達成できることを私は知っています。
ただし、制約のチェックを一時的にオフにして、操作の終了後にオンに戻すことができれば、より簡単になります。
これは可能ですか?
すべてのDBの制約(テーブルの関係など)を一時的にオフにする方法を探しています。
あるDBのテーブルを別のDBに(INSERTを使用して)コピーする必要があります。コマンドを適切な順序で実行することで(関係を壊さないように)それを達成できることを私は知っています。
ただし、制約のチェックを一時的にオフにして、操作の終了後にオンに戻すことができれば、より簡単になります。
これは可能ですか?
-- 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 in the database:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
-- Re-enable constraints for all tables in the database:
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'
---------------------------------------------------------
FKおよびCHECK制約は、SQL2005以降でのみ無効にできます。ALTERTABLEを参照してください
ALTER TABLE foo NOCHECK CONSTRAINT ALL
また
ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column
主キーと一意の制約を無効にすることはできませんが、正しく理解していれば、これで問題ありません。
そして、あなたがあなたの関係を壊して孤児を紹介したことがないことを確認したいなら、あなたがあなたの小切手を再び武装させたら、すなわち
ALTER TABLE foo CHECK CONSTRAINT ALL
また
ALTER TABLE foo CHECK CONSTRAINT FK_something
次に、戻って、次のようにチェックされた列に対して更新を行うことができます。
UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc
そして、その時点でのエラーは、制約を満たしていないことが原因になります。
実際には、単一のSQLコマンドですべてのデータベース制約を無効にし、別の単一コマンドを呼び出してそれらを再度有効にすることができます。見る:
私は現在SQLServer2005を使用していますが、このアプローチはSQL2000でも機能することはほぼ間違いありません。
すべての外部キーの無効化と有効化
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キーワードを使用)に応じて、ALTERTABLEコマンドを異なる方法で作成します。次に、ステートメントがメッセージとして出力されるため、進行状況を確認して、ステートメントを実行できます。最後に、すべての行が繰り返されると、ストアドプロシージャが閉じて、カーソルの割り当てが解除されます。
MSDNMagazineの制約とトリガーの無効化を参照してください。