web-dev-qa-db-ja.com

WITH CHECK CHECK CONSTRAINTとは何ですか?

自動生成されたT-SQLがいくつかありますが、これはおそらく有効ですが、よくわかりません。

ALTER TABLE [dbo].[MyTable]
WITH CHECK
CHECK CONSTRAINT [My_FORIEGN_KEY];

外部キー制約とは何か知っていますが、CHECK CHECKとは何ですか?

21
BanksySan

ALTER TABLE に関するMSDNドキュメントのページで、これらについて説明しています。

  • ALTER TABLE:テーブルの構造を変更します
    (および可能なアクション/変更の一部は次のとおりです):
    • CHECK CONSTRAINT ..:制約を有効にします
    • NOCHECK CONSTRAINT ..:制約を無効にします
      制約の作成/有効化/無効化中に実行する追加のオプションの手順もあります:
      • WITH CHECK:制約も確認してください
      • WITH NOCHECK:制約を確認しません

彼らの言葉で:

| [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT   
    { ALL | constraint_name [ ,...n ] }

...

WITH CHECK | WITH NOCHECKテーブルのデータが検証されるかどうか新しく追加または再有効化されたFOREIGN KEYまたはCHECK制約]に対して指定されます。指定しない場合、新しい制約にはWITH CHECKが想定され、再度有効にされた制約にはWITH NOCHECKが想定されます。

既存のデータに対して新しいCHECKまたはFOREIGN KEY制約を検証しない場合は、WITH NOCHECKを使用します。まれな場合を除いて、これを行うことはお勧めしません。新しい制約は、その後のすべてのデータ更新で評価されます。制約が追加されたときにWITH NOCHECKによって抑制された制約違反は、制約に準拠しないデータで行を更新する場合、将来の更新が失敗する可能性があります。

クエリオプティマイザーは、WITH NOCHECKで定義されている制約を考慮しません。このような制約は、ALTER TABLEテーブルWITH CHECK CHECK CONSTRAINT ALLを使用して再度有効にするまで無視されます。

...

{ CHECK | NOCHECK } CONSTRAINT
constraint_nameが有効または無効であることを指定します。このオプションは、FOREIGN KEYおよびCHECK制約でのみ使用できます。 NOCHECKが指定されている場合、制約は無効になり、以降の列への挿入または更新は制約条件に対して検証されません。 DEFAULTPRIMARY KEY、およびUNIQUE制約は無効にできません。

dbfiddle でテスト:

CREATE TABLE a (aid INT PRIMARY KEY);

行く

INSERT INTO a (aid)
VALUES (1), (2), (3) ;

行く

 3行が影響を受けました
CREATE TABLE b 
( aid INT,
  bid INT PRIMARY KEY,
  CONSTRAINT [My_FORIEGN_KEY]
    FOREIGN KEY (aid) REFERENCES a (aid)
) ;

行く

INSERT INTO b (aid, bid)
VALUES
  (1, 11),
  (1, 12),
  (2, 21), 
  (3, 31) ;

行く

 4行が影響を受けました
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

行く

メッセージ547レベル16状態0行1 
 INSERTステートメントがFOREIGN KEY制約「My_FORIEGN_KEY」と競合しました。データベース "fiddle_792fce5de09f42908c3a0f91421f3522"、テーブル "dbo.a"、列 'aid'で競合が発生しました。
 Msg 3621レベル0状態0行1 
ステートメントが終了しました。
SELECT * FROM b ;

行く

援助|入札
-:| -:
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
ALTER TABLE b NOCHECK CONSTRAINT [My_FORIEGN_KEY];   --disable

行く

INSERT INTO b (aid, bid)
VALUES
  (4, 41),
  (4, 42) ;

行く

 2行が影響を受けました
SELECT * FROM b ;

行く

援助|入札
-:| -:
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
 4 | 41 
 4 | 42 
ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- enable constraint without checking existing data

行く

SELECT * FROM b ;

行く

援助|入札
-:| -:
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
 4 | 41 
 4 | 42 
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

行く

メッセージ547レベル16状態0行1 
 INSERTステートメントがFOREIGN KEY制約「My_FORIEGN_KEY」と競合しました。データベース "fiddle_792fce5de09f42908c3a0f91421f3522"、テーブル "dbo.a"、列 'aid'で競合が発生しました。
 Msg 3621レベル0状態0行1 
ステートメントが終了しました。
SELECT * FROM b ;

行く

援助|入札
-:| -:
 1 | 11 
 1 | 12 
 2 | 21 
 3 | 31 
 4 | 41 
 4 | 42 
ALTER TABLE b WITH CHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- check existing data and enable constraint 

行く

メッセージ547レベル16状態0行1 
 ALTER TABLEステートメントがFOREIGN KEY制約「My_FORIEGN_KEY」と競合しました。データベース "fiddle_792fce5de09f42908c3a0f91421f3522"、テーブル "dbo.a"、列 'aid'で競合が発生しました。
31
ypercubeᵀᴹ

こちらの記事をお読みください。 https://msdn.Microsoft.com/en-us/library/ms190273.aspx

「クエリオプティマイザは、WITH NOCHECKで定義された制約を考慮しません。このような制約は、ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL 'を使用して再度有効にするまで無視されます。

また、StackOverflowのスレッドを検討してください: https://stackoverflow.com/questions/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

1
George K