Sql-Server

ALTER TABLE CHECK CONSTRAINT 是多餘的嗎?

  • September 12, 2018

我創建了一個帶有外鍵約束的表。當我通過 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 約束,這是否會使第二條語句變得多餘?如果不是,那麼 CHECK CONSTRAINT 完成了什麼,而 WITH CHECK 沒有完成?

我看到了ALTER TABLE CHECK CONSTRAINT,但在這種情況下,SSMS 正在生成第一個帶有 NOCHECK 的語句,因此同時擁有這兩個語句是有意義的。

第一條語句更改表以添加約束。第二條語句啟用或禁用將來插入或更新的約束。

因此,ALTER TABLE ... CHECK CONSTRAINT ...為將來的插入/更新啟用約束。如果指定ALTER TABLE ... NOCHECK CONSTRAINT ...,則禁用約束,從而允許將來的插入和更新成功,即使外鍵引用的表中的列不包含匹配值。通過此範例,您可以看到同時存在這兩個語句的實用性:

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);

因此,我們創建了兩個沒有定義關係的表。後來,我們決定要設計關係,所以我們添加一個外鍵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 ...即使不需要,它也會輸出 a,並且在絕大多數情況下肯定不需要。


1 - 為什麼有人希望驗證現有行,但不關心新行有點神秘,但你去吧。

引用自:https://dba.stackexchange.com/questions/185883