Що таке обмеження для перевірки?


18

У мене є автоматично створений T-SQL, який, ймовірно, дійсний, але я не дуже розумію.

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

Я знаю, що таке обмеження іноземного ключа, але що таке CHECK CHECK?

Відповіді:


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 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
Вказує, що ім'я 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", стовпці "довідка".

1
Спасибі. Wrt ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY]; -- enable constraint without checking, це буде означати, що обмеження не перевірятиме існуючі дані, а лише нові вхідні дані?
BanksySan

1
Саме так. Подивіться, як наступна вставка (help = 6) заборонена, але існуючі рядки (з help = 4) все ще є.
ypercubeᵀᴹ

Це прекрасно демонструє.
BanksySan

1

Розгляньте читати статтю тут: https://msdn.microsoft.com/en-us/library/ms190273.aspx

Це говорить нам: "Оптимізатор запитів не враховує обмежень, визначених NOCHECK. Такі обмеження ігноруються до тих пір, поки їх не буде включено повторно за допомогою таблиці ALTER TABLE AND CHECK CHECK CONSTRAINT ALL '

Також врахуйте цю тему на StackOverflow: /programming/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.