Что такое ограничение CHECK CHECK?

18

У меня есть автоматически сгенерированный T-SQL, который, вероятно, действителен, но я не совсем понимаю

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

Я знаю, что такое ограничение внешнего ключа, но что это CHECK CHECK?

BanksySan
источник

Ответы:

27

Страница документации 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 KEYили CHECKограничения . Если не указано, WITH CHECKпредполагается, что для новых ограничений, и WITH NOCHECKпредполагается для повторно разрешенных ограничений.

Если вы не хотите проверять новые CHECKили FOREIGN KEYограничения на существующие данные, используйте WITH NOCHECK. Мы не рекомендуем делать это, за исключением редких случаев. Новое ограничение будет оцениваться во всех последующих обновлениях данных. Любые нарушения ограничений, которые подавляются WITH NOCHECKпри добавлении ограничения, могут привести к сбою будущих обновлений, если они обновят строки данными, которые не соответствуют ограничению.

Оптимизатор запросов не учитывает определенные ограничения WITH NOCHECK. Такие ограничения игнорируются, пока они не будут повторно включены с помощью ALTER TABLEтаблицы WITH CHECK CHECK CONSTRAINT ALL.

...

{ CHECK | NOCHECK } CONSTRAINT
Указывает, что имя_ограничения включено или отключено. Эта опция может быть использована только с FOREIGN KEYи CHECKограничения. Если NOCHECKуказано, ограничение отключено, и будущие вставки или обновления столбца не проверяются в соответствии с условиями ограничения. DEFAULT, PRIMARY KEY, И UNIQUEограничения не могут быть отключены.

Тест в 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) ;

ИДТИ

Msg 547 Уровень 16 Государство 0 Линия 1
Оператор INSERT конфликтует с ограничением FOREIGN KEY «My_FORIEGN_KEY». Конфликт произошел в базе данных "fiddle_792fce5de09f42908c3a0f91421f3522", таблица "dbo.a", столбец "помощь".
Msg 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) ;

ИДТИ

Msg 547 Уровень 16 Государство 0 Линия 1
Оператор INSERT конфликтует с ограничением FOREIGN KEY «My_FORIEGN_KEY». Конфликт произошел в базе данных "fiddle_792fce5de09f42908c3a0f91421f3522", таблица "dbo.a", столбец "помощь".
Msg 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 

ИДТИ

Msg 547 Уровень 16 Государство 0 Линия 1
Оператор ALTER TABLE конфликтовал с ограничением FOREIGN KEY «My_FORIEGN_KEY». Конфликт произошел в базе данных "fiddle_792fce5de09f42908c3a0f91421f3522", таблица "dbo.a", столбец "помощь".
ypercubeᵀᴹ
источник
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 WITH CHECK CHECK CONSTRAINT ALL '

Кроме того, рассмотрите этот поток в StackOverflow: /programming/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

Джордж К
источник