SSMS 約束腳本:第二條 alter table 語句的用途?
SSMS 將外鍵約束腳本編寫為兩個語句:
ALTER TABLE {table} WITH CHECK ADD CONSTRAINT {constraintname} {constraint spec} GO ALTER TABLE {table} CHECK CONSTRAINT {constraintname} GO
第二個聲明的目的是什麼?
第二行是多餘的,但我同意過度使用
CHECK
該語法會令人困惑。根據ALTER TABLE 文件
WITH CHECK ADD
,如果使用該選項並且啟用了新添加的約束,則無論如何都會檢查現有數據。帶支票 | WITH NOCHECK
指定表中的數據是否針對新添加或重新啟用的 FOREIGN KEY 或 CHECK 約束進行驗證。如果未指定,則假定 WITH CHECK 用於新約束,而 WITH NOCHECK 假定用於重新啟用的約束。
第二行再次從文件中啟用約束,但該約束已經啟用。
{檢查| NOCHECK } CONSTRAINT 指定啟用或禁用約束名稱。此選項只能與 FOREIGN KEY 和 CHECK 約束一起使用。當指定 NOCHECK 時,約束被禁用,並且將來對列的插入或更新不會根據約束條件進行驗證。不能禁用 DEFAULT、PRIMARY KEY 和 UNIQUE 約束。
但是,約束已經啟用,從這段程式碼可以看出:
CREATE TABLE [dbo].[constraintdemo]( [constraintfield] [int] NULL ) ON [PRIMARY] GO ALTER TABLE [dbo].[constraintdemo] WITH CHECK ADD CONSTRAINT [CK_constraintdemo] CHECK (([constraintfield]>(0))) GO INSERT INTO constraintdemo (constraintfield) VALUES (-1)
結果是:
消息 547,級別 16,狀態 0,第 12 行 INSERT 語句與 CHECK 約束“CK_constraintdemo”衝突。衝突發生在數據庫“PlayGround”、表“dbo.constraintdemo”、列“constraintfield”中。該語句已終止。
請參閱此dbfiddle,您可以在其中執行上述程式碼
如果您想證明現有數據已被有效驗證,
WITH CHECK
您可以執行以下程式碼:CREATE TABLE [dbo].[constraintdemo]( [constraintfield] [int] NULL ) ON [PRIMARY] GO INSERT INTO constraintdemo (constraintfield) values (-1),(-2) GO ALTER TABLE [dbo].[constraintdemo] WITH CHECK ADD CONSTRAINT [CK_constraintdemo] CHECK (([constraintfield]>(0))) GO
返回:
(2 行受影響)消息 547,級別 16,狀態 0,第 21 行 ALTER TABLE 語句與 CHECK 約束“CK_constraintdemo”衝突。衝突發生在數據庫“PlayGround”、表“dbo.constraintdemo”、列“constraintfield”中。
再次:dbfiddle
在這個例子中,它是檢查約束還是外鍵約束並不重要,正如這個稍微複雜的例子所證明的那樣(注意我註釋掉了第二行):
CREATE TABLE [dbo].[keytable]( [key] [nchar](10) NOT NULL, CONSTRAINT [PK_keytable] PRIMARY KEY CLUSTERED ( [key] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO CREATE TABLE [dbo].[valuetable]( [key] [nchar](10) NULL, [value] [nchar](10) NULL ) ON [PRIMARY] GO ALTER TABLE [dbo].[valuetable] WITH CHECK ADD CONSTRAINT [FK_valuetable_keytable] FOREIGN KEY([key]) REFERENCES [dbo].[keytable] ([key]) GO --ALTER TABLE [dbo].[valuetable] CHECK CONSTRAINT [FK_valuetable_keytable] GO INSERT INTO keytable ([key]) VALUES (1),(2); GO INSERT INTO valuetable ([key],[value]) VALUES (3,'test'); GO
這仍然會導致顯示外鍵已啟用的錯誤:
消息 547 級別 16 狀態 0 第 1 行 INSERT 語句與 FOREIGN KEY 約束“FK_valuetable_keytable”衝突。衝突發生在數據庫“fiddle_7378e515ee284b358b4e2edbc07d1329”、表“dbo.keytable”、“key”列中。Msg 3621 Level 0 State 0 Line 1
語句已終止。
再一次,我們可以扭轉局面,證明它使用以下程式碼檢查創建時的現有數據:
CREATE TABLE [dbo].[keytable]( [key] [nchar](10) NOT NULL, CONSTRAINT [PK_keytable] PRIMARY KEY CLUSTERED ( [key] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO CREATE TABLE [dbo].[valuetable]( [key] [nchar](10) NULL, [value] [nchar](10) NULL ) ON [PRIMARY] GO INSERT INTO keytable ([key]) VALUES (1),(2); GO INSERT INTO valuetable ([key],[value]) VALUES (3,'test'); GO ALTER TABLE [dbo].[valuetable] WITH CHECK ADD CONSTRAINT [FK_valuetable_keytable] FOREIGN KEY([key]) REFERENCES [dbo].[keytable] ([key]) GO
返回:
消息 547 級別 16 狀態 0 第 1 行 ALTER TABLE 語句與 FOREIGN KEY 約束“FK_valuetable_keytable”衝突。衝突發生在數據庫“fiddle_59761b4587c14f2b96b8029a10de6229”、表“dbo.keytable”、列“key”中。