外部キー制約が設定されたテーブルを作成しました。 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を生成しているので、両方のステートメントがあることは意味があります。
最初のステートメントはテーブルを変更して制約を追加します。 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-なぜ誰もが既存の行を検証したいが、新しい行を気にしないのは少し不思議なことですが、それで終わりです。