什么是WITH CHECK CHECK约束?


18

我有一些自动生成的T-SQL,这可能是有效的,但我不太了解。

ALTER TABLE [dbo].[MyTable]
WITH CHECK
CHECK CONSTRAINT [My_FORIEGN_KEY];

我知道什么是外键约束,但这是什么CHECK CHECK

Answers:


28

有关的MSDN文档页面ALTER TABLE解释了以下内容:

  • ALTER TABLE:修改表的结构
    (以及一些可能的操作/修改是):
    • CHECK CONSTRAINT ..:启用约束
    • NOCHECK CONSTRAINT ..:禁用约束
      在创建/启用/禁用约束时,还需要执行其他可选步骤:
      • WITH CHECK:同时检查约束
      • WITH NOCHECK:不检查约束

用他们的话说:

| [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT   
    { ALL | constraint_name [ ,...n ] }

...

WITH CHECK | WITH NOCHECK 指定是否针对新添加或重新启用约束验证表中的数据。如果未指定,则假定为新约束,并且假定为重新启用约束。FOREIGN KEYCHECKWITH CHECKWITH NOCHECK

如果您不想验证新数据CHECKFOREIGN KEY对现有数据的约束,请使用WITH NOCHECK。除了极少数情况,我们不建议您这样做。新的约束将在以后的所有数据更新中进行评估。WITH NOCHECK如果在添加约束时抑制的任何约束违规行为,如果它们使用不符合约束的数据更新行,则可能导致将来的更新失败。

查询优化器不考虑已定义的约束WITH NOCHECK。在使用ALTER TABLEtable 重新启用这些约束之前,将忽略这些约束WITH CHECK CHECK CONSTRAINT ALL

...

{ CHECK | NOCHECK } CONSTRAINT
指定启用或禁用constraint_name。此选项只能与FOREIGN KEYCHECK约束一起使用。当NOCHECK被指定,限制被禁止和未来的插入或更新列没有对约束条件进行验证。DEFAULTPRIMARY KEYUNIQUE不能禁用约束。

dbfiddle中测试:

CREATE TABLE a (aid INT PRIMARY KEY);

INSERT INTO a (aid)
VALUES (1), (2), (3) ;

3行受影响
CREATE TABLE b 
( aid INT,
  bid INT PRIMARY KEY,
  CONSTRAINT [My_FORIEGN_KEY]
    FOREIGN KEY (aid) REFERENCES a (aid)
) ;

INSERT INTO b (aid, bid)
VALUES
  (1, 11),
  (1, 12),
  (2, 21), 
  (3, 31) ;

受影响的4行
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

消息547级别16状态0线路1
INSERT语句与FOREIGN KEY约束“ My_FORIEGN_KEY”冲突。在数据库“ fiddle_792fce5de09f42908c3a0f91421f3522”的表“ dbo.a”的“ aid”列中发生了冲突。
消息3621级别0状态0线路1
该语句已终止。
SELECT * FROM b ;

援助| 出价
-:| -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
ALTER TABLE b NOCHECK CONSTRAINT [My_FORIEGN_KEY];   --disable

INSERT INTO b (aid, bid)
VALUES
  (4, 41),
  (4, 42) ;

2行受影响
SELECT * FROM b ;

援助| 出价
-:| -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
  4 | 41
  4 | 42
ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- enable constraint without checking existing data

SELECT * FROM b ;

援助| 出价
-:| -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
  4 | 41
  4 | 42
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

消息547级别16状态0线路1
INSERT语句与FOREIGN KEY约束“ My_FORIEGN_KEY”冲突。在数据库“ fiddle_792fce5de09f42908c3a0f91421f3522”的表“ dbo.a”的“ aid”列中发生了冲突。
消息3621级别0状态0线路1
该语句已终止。
SELECT * FROM b ;

援助| 出价
-:| -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
  4 | 41
  4 | 42
ALTER TABLE b WITH CHECK CHECK CONSTRAINT [My_FORIEGN_KEY];  
-- check existing data and enable constraint 

消息547级别16状态0线路1
ALTER TABLE语句与FOREIGN KEY约束“ My_FORIEGN_KEY”冲突。在数据库“ fiddle_792fce5de09f42908c3a0f91421f3522”的表“ dbo.a”的“ aid”列中发生了冲突。

1
谢谢。Wrt ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY]; -- enable constraint without checking,这是否意味着约束将不检查现有数据,仅检查新的传入数据?
BanksySan

1
究竟。了解如何不允许下一个插入(aid = 6),但现有行(具有aid = 4)仍然存在。
ypercubeᵀᴹ

那完美地展示了它。
BanksySan

1

考虑在这里阅读文章:https : //msdn.microsoft.com/en-us/library/ms190273.aspx

它告诉我们:“查询优化器不考虑使用NOCHECK定义的约束。在使用ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL'重新启用它们之前,将忽略这些约束。

另外,考虑一下StackOverflow上的线程:https ://stackoverflow.com/questions/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.