什么是 WITH CHECK CHECK 约束?

Ban*_*San 31 sql-server constraint t-sql

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

ALTER TABLE [dbo].[MyTable]
WITH CHECK
CHECK CONSTRAINT [My_FORIEGN_KEY];
Run Code Online (Sandbox Code Playgroud)

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

ype*_*eᵀᴹ 42

MSDN 文档页面 aboutALTER TABLE解释了这些:

  • ALTER TABLE:修改表的结构
    (一些可能的操作/修改是):
    • CHECK CONSTRAINT ..: 启用约束
    • NOCHECK CONSTRAINT ..:禁用约束
      在创建/启用/禁用约束时,还有一些额外的可选步骤要做:
      • WITH CHECK: 也检查约束
      • WITH NOCHECK: 不检查约束

用他们的话来说:

| [ WITH { CHECK | NOCHECK } ] { CHECK | NOCHECK } CONSTRAINT   
    { ALL | constraint_name [ ,...n ] }
Run Code Online (Sandbox Code Playgroud)

...

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);
Run Code Online (Sandbox Code Playgroud)

?
INSERT INTO a (aid)
VALUES (1), (2), (3) ;
Run Code Online (Sandbox Code Playgroud)

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

?
INSERT INTO b (aid, bid)
VALUES
  (1, 11),
  (1, 12),
  (2, 21), 
  (3, 31) ;
Run Code Online (Sandbox Code Playgroud)

4 行受影响
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;
Run Code Online (Sandbox Code Playgroud)

消息 547 级别 16 状态 0 行 1
INSERT 语句与 FOREIGN KEY 约束“My_FORIGN_KEY”冲突。冲突发生在数据库“fiddle_792fce5de09f42908c3a0f91421f3522”、表“dbo.a”、“aid”列中。
消息 3621 级别 0 状态 0 行 1
该语句已终止。
SELECT * FROM b ;
Run Code Online (Sandbox Code Playgroud)

援助| 出价
--: | ——:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
ALTER TABLE b NOCHECK CONSTRAINT [My_FORIEGN_KEY];   --disable
Run Code Online (Sandbox Code Playgroud)

?
INSERT INTO b (aid, bid)
VALUES
  (4, 41),
  (4, 42) ;
Run Code Online (Sandbox Code Playgroud)

2 行受影响
SELECT * FROM b ;
Run Code Online (Sandbox Code Playgroud)

援助| 出价
--: | ——:
  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
Run Code Online (Sandbox Code Playgroud)

?
SELECT * FROM b ;
Run Code Online (Sandbox Code Playgroud)

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

消息 547 级别 16 状态 0 行 1
INSERT 语句与 FOREIGN KEY 约束“My_FORIGN_KEY”冲突。冲突发生在数据库“fiddle_792fce5de09f42908c3a0f91421f3522”、表“dbo.a”、“aid”列中。
消息 3621 级别 0 状态 0 行 1
该语句已终止。
SELECT * FROM b ;
Run Code Online (Sandbox Code Playgroud)

援助| 出价
--: | ——:
  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 
Run Code Online (Sandbox Code Playgroud)

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