web-dev-qa-db-ja.com

ALTER TABLE CHECK CONSTRAINTは冗長ですか?

外部キー制約が設定されたテーブルを作成しました。 SSMSでテーブル作成スクリプトを生成すると、次のコードが作成されます。

ALTER TABLE [dbo].[MainTable]  WITH CHECK ADD  CONSTRAINT [FK_MainTable_ForeignKeyTable] FOREIGN KEY([FK_Field])
REFERENCES [dbo].[ForeignKeyTable] ([PK_Field])
GO

ALTER TABLE [dbo].[MainTable] CHECK CONSTRAINT [FK_MainTable_ForeignKeyTable]
GO

最初のステートメントはWITH CHECK制約を作成するので、これにより2番目のステートメントが冗長になりますか?そうでない場合、WITH CHECKが行わないことを達成するCHECK CONSTRAINTは何ですか?

私は ALTER TABLE CHECK CONSTRAINT を見ましたが、その場合、SSMSは最初のステートメントWITH NOCHECKを生成しているので、両方のステートメントがあることは意味があります。

5
mathewb

最初のステートメントはテーブルを変更して制約を追加します。 2番目のステートメント有効または無効今後の挿入または更新のための制約。

したがって、ALTER TABLE ... CHECK CONSTRAINT ...は、将来の挿入/更新の制約を有効にします。 ALTER TABLE ... NOCHECK CONSTRAINT ...を指定すると、そのdisables制約により、外部キーによって参照されるテーブルの列に一致する値が含まれていない場合でも、将来の挿入と更新が成功します。この例を通して、両方のステートメントが存在することの有用性を確認できます。

USE tempdb;

IF OBJECT_ID(N'dbo.b', N'U') IS NOT NULL
DROP TABLE dbo.b;
IF OBJECT_ID(N'dbo.a', N'U') IS NOT NULL
DROP TABLE dbo.a;

CREATE TABLE dbo.a
(
    a_ID int NOT NULL
        CONSTRAINT a_primary_key
        PRIMARY KEY
        CLUSTERED
    , SomeData varchar(10) NOT NULL
) ON [PRIMARY];

INSERT INTO dbo.a (a_ID, SomeData)
VALUES (1, 'aaaa')
    , (2, 'bbbb')
    , (3, 'cccc');

CREATE TABLE dbo.b
(
    b_ID int NOT NULL
        CONSTRAINT b_primary_key
        PRIMARY KEY
        CLUSTERED
    , SomeData varchar(10) NOT NULL
    , a_ID int NOT NULL
) ON [PRIMARY];

INSERT INTO dbo.b (b_ID, SomeData, a_ID)
VALUES (49, 'dddd', 1)
    , (50, 'eeee', 2)
    , (51, 'ffff', 3);

そこで、関係が定義されていない2つのテーブルを作成しました。その後、関係をデザインインすることを決定するため、dbo.bの主キー列を参照する外部キーをdbo.aに追加します。既存の行の有効性をチェックしたいが、将来追加される可能性のある新しい行は気にしない1

ALTER TABLE dbo.b 
WITH CHECK
ADD CONSTRAINT b_a_foreign_key
FOREIGN KEY (a_ID)
REFERENCES a(a_ID);

ALTER TABLE dbo.b 
NOCHECK CONSTRAINT b_a_foreign_key;

すべて良い。既存の行が検証され、新しい行されないが外部キーに対して検証されます。

INSERT INTO dbo.b (b_ID, SomeData, a_ID)
VALUES (52, 'gggg', 4);

テーブルの内容:

SELECT *
FROM dbo.b
    LEFT JOIN dbo.a ON b.a_ID = a.a_ID

結果:

╔══════╦══════════╦══════╦══════╦══════════╗
║ b_ID║SomeData║a_ID║a_ID║SomeData║
╠══════╬══════════╬══════╬══════╬══ ════════╣
║49║dddd║1║1║aaaa║
║50║eeee║2║2║bbbb║
║51║ffff ║3║3║cccc║
║52║gggg║4║NULL║NULL║<-クレイジーなもの
╚══════╩═════════ ═╩══════╩══════╩══════════╝

そのため、SSMSでテーブルをスクリプト化するコードはすべての不測の事態をカバーする必要があるため、必要のない場合でもALTER TABLE ... CHECK CONSTRAINT ...を吐き出し、ほとんどの場合は確かに必要ありません。


1-なぜ誰もが既存の行を検証したいが、新しい行を気にしないのは少し不思議なことですが、それで終わりです。

4
Max Vernon