ALTER TABLE CHECK CONSTRAINT 是多余的吗?

mat*_*ewb 5 sql-server constraint ssms sql-server-2014 check-constraints

我创建了一个带有外键约束的表。当我通过 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
Run Code Online (Sandbox Code Playgroud)

由于第一个语句创建了 WITH CHECK 约束,这是否会使第二个语句变得多余?如果不是,那么 CHECK CONSTRAINT 完成了 WITH CHECK 没有完成的任务是什么?

我看到了ALTER TABLE CHECK CONSTRAINT,但在这种情况下,SSMS 正在生成第一个语句 WITH NOCHECK,所以有两个语句是有意义的。

Han*_*non 5

第一个语句更改表以添加约束。第二条语句启用或禁用将来插入或更新的约束。

\n\n

因此,ALTER TABLE ... CHECK CONSTRAINT ...启用对未来插入/更新的约束。如果指定ALTER TABLE ... NOCHECK CONSTRAINT ...,则会禁用约束,从而即使外键引用的表中的列不包含匹配值,也允许将来的插入和更新成功。您可以通过此示例了解同时存在这两个语句的实用性:

\n\n
USE tempdb;\n\nIF OBJECT_ID(N'dbo.b', N'U') IS NOT NULL\nDROP TABLE dbo.b;\nIF OBJECT_ID(N'dbo.a', N'U') IS NOT NULL\nDROP TABLE dbo.a;\n\nCREATE TABLE dbo.a\n(\n    a_ID int NOT NULL\n        CONSTRAINT a_primary_key\n        PRIMARY KEY\n        CLUSTERED\n    , SomeData varchar(10) NOT NULL\n) ON [PRIMARY];\n\nINSERT INTO dbo.a (a_ID, SomeData)\nVALUES (1, 'aaaa')\n    , (2, 'bbbb')\n    , (3, 'cccc');\n\nCREATE TABLE dbo.b\n(\n    b_ID int NOT NULL\n        CONSTRAINT b_primary_key\n        PRIMARY KEY\n        CLUSTERED\n    , SomeData varchar(10) NOT NULL\n    , a_ID int NOT NULL\n) ON [PRIMARY];\n\nINSERT INTO dbo.b (b_ID, SomeData, a_ID)\nVALUES (49, 'dddd', 1)\n    , (50, 'eeee', 2)\n    , (51, 'ffff', 3);\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,我们创建了两个没有定义关系的表。后来,我们决定要设计关系,因此我们在 中添加一个外键来dbo.b引用 中的主键列dbo.a。我们希望检查现有行的有效性,但不关心将来可能添加的新行1

\n\n
ALTER TABLE dbo.b \nWITH CHECK\nADD CONSTRAINT b_a_foreign_key\nFOREIGN KEY (a_ID)\nREFERENCES a(a_ID);\n\nALTER TABLE dbo.b \nNOCHECK CONSTRAINT b_a_foreign_key;\n
Run Code Online (Sandbox Code Playgroud)\n\n

都好。已验证现有行,并且不会根据外键验证新行:

\n\n
INSERT INTO dbo.b (b_ID, SomeData, a_ID)\nVALUES (52, 'gggg', 4);\n
Run Code Online (Sandbox Code Playgroud)\n\n

表内容:

\n\n
SELECT *\nFROM dbo.b\n    LEFT JOIN dbo.a ON b.a_ID = a.a_ID\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果:

\n\n
\xe2\x95\x94\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\x90\xe2\x95\x97\n\xe2\x95\x91 b_ID \xe2\x95\x91 SomeData \xe2\x95\x91 a_ID \xe2\x95\x91 a_ID \xe2\x95\x91一些数据\xe2\x95\x91\n\xe2\x95\xa0\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\ x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\ xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\ x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\ x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\ xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa3\n\xe2\x95\x91 49 \xe2\x95\x91 dddd \xe2\x95\x91 1 \xe2\x95 \x91 1 \xe2\x95\x91 aaaa \xe2\x95\x91\n\xe2\x95\x91 50 \xe2\x95\x91 eeee \xe2\x95\x91 2 \xe2\x95\x91 2 \xe2\x95 \x91 bbbb \xe2\x95\x91\n\xe2\x95\x91 51 \xe2\x95\x91 ffff \xe2\x95\x91 3 \xe2\x95\x91 3 \xe2\x95\x91 cccc \xe2\x95 \x91\n\xe2\x95\x91 52 \xe2\x95\x91 gggg \xe2\x95\x91 4 \xe2\x95\x91 NULL \xe2\x95\x91 NULL \xe2\x95\x91 <-- 疯狂的东西\n\xe2\x95\x9a\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa9 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\xa9\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\xa9\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa9 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x9d\n
\n\n

因此,由于 SSMS 中编写表脚本的代码必须涵盖所有可能发生的情况,因此ALTER TABLE ... CHECK CONSTRAINT ...即使不需要,它也会输出 a,并且在绝大多数情况下肯定不需要。

\n\n
\n\n

1 - 为什么有人希望验证现有行,但不关心新行,这有点神秘,但你明白了。

\n

  • 相关q:https://dba.stackexchange.com/questions/167861/what-is-a-with-check-check-constraint/167866#167866 (2认同)