Apa itu CONSTRAINT CHECK CHECK?

18

Saya memiliki beberapa T-SQL yang dibuat secara otomatis, yang mungkin valid, tetapi saya tidak begitu mengerti.

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

Saya tahu apa batasan kunci asing, tapi apa masalahnya CHECK CHECK?

BanksySan
sumber

Jawaban:

27

Halaman dokumentasi MSDN tentang ALTER TABLEmenjelaskan ini:

  • ALTER TABLE: memodifikasi struktur tabel
    (dan beberapa tindakan / modifikasi yang mungkin dilakukan):
    • CHECK CONSTRAINT ..: aktifkan kendala
    • NOCHECK CONSTRAINT ..: disable the constraint
      Ada juga langkah-langkah opsional tambahan yang harus dilakukan saat membuat / mengaktifkan / menonaktifkan kendala:
      • WITH CHECK: periksa kendala juga
      • WITH NOCHECK: jangan periksa kendala

Dalam kata-kata mereka:

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

...

WITH CHECK | WITH NOCHECK Menentukan apakah data dalam tabel adalah atau tidak divalidasi terhadap yang baru ditambahkan atau diaktifkan kembali FOREIGN KEYatau CHECKkendala . Jika tidak ditentukan, WITH CHECKdiasumsikan untuk kendala baru, dan WITH NOCHECKdiasumsikan untuk kendala yang diaktifkan kembali.

Jika Anda tidak ingin memverifikasi baru CHECKatau FOREIGN KEYkendala terhadap data yang ada, gunakan WITH NOCHECK. Kami tidak menyarankan melakukan ini, kecuali dalam kasus yang jarang terjadi. Kendala baru akan dievaluasi di semua pembaruan data nanti. Pelanggaran kendala apa pun yang ditekan oleh WITH NOCHECKketika kendala ditambahkan dapat menyebabkan pembaruan di masa mendatang gagal jika mereka memperbarui baris dengan data yang tidak mematuhi kendala.

Pengoptimal kueri tidak mempertimbangkan kendala yang ditentukan WITH NOCHECK. Kendala seperti itu diabaikan sampai mereka diaktifkan kembali dengan menggunakan ALTER TABLEtabel WITH CHECK CHECK CONSTRAINT ALL.

...

{ CHECK | NOCHECK } CONSTRAINT
Menentukan bahwa constraint_name diaktifkan atau dinonaktifkan. Opsi ini hanya dapat digunakan dengan FOREIGN KEYdan CHECKkendala. Ketika NOCHECKditentukan, kendala dinonaktifkan dan memasukkan atau memperbarui kolom ke masa depan tidak divalidasi terhadap kondisi kendala. DEFAULT,, PRIMARY KEYdan UNIQUEbatasan tidak dapat dinonaktifkan.

Tes di dbfiddle :

CREATE TABLE a (aid INT PRIMARY KEY);

PERGILAH

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

PERGILAH

3 baris terpengaruh
CREATE TABLE b 
( aid INT,
  bid INT PRIMARY KEY,
  CONSTRAINT [My_FORIEGN_KEY]
    FOREIGN KEY (aid) REFERENCES a (aid)
) ;

PERGILAH

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

PERGILAH

4 baris terpengaruh
INSERT INTO b (aid, bid)
VALUES
  (6, 61),
  (6, 62) ;

PERGILAH

Msg 547 Level 16 Status 0 Baris 1
Pernyataan INSERT bertentangan dengan batasan FOREIGN KEY "My_FORIEGN_KEY". Konflik terjadi di basis data "fiddle_792fce5de09f42908c3a0f91421f3522", tabel "dbo.a", kolom 'bantuan'.
Msg 3621 Level 0 Status 0 Baris 1
Pernyataan itu telah dihentikan.
SELECT * FROM b ;

PERGILAH

bantuan | tawaran
-: | -:
  1 | 11
  1 | 12
  2 | 21
  3 | 31
ALTER TABLE b NOCHECK CONSTRAINT [My_FORIEGN_KEY];   --disable

PERGILAH

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

PERGILAH

2 baris terpengaruh
SELECT * FROM b ;

PERGILAH

bantuan | tawaran
-: | -:
  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

PERGILAH

SELECT * FROM b ;

PERGILAH

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

PERGILAH

Msg 547 Level 16 Status 0 Baris 1
Pernyataan INSERT bertentangan dengan batasan FOREIGN KEY "My_FORIEGN_KEY". Konflik terjadi di basis data "fiddle_792fce5de09f42908c3a0f91421f3522", tabel "dbo.a", kolom 'bantuan'.
Msg 3621 Level 0 Status 0 Baris 1
Pernyataan itu telah dihentikan.
SELECT * FROM b ;

PERGILAH

bantuan | tawaran
-: | -:
  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 

PERGILAH

Msg 547 Level 16 Status 0 Baris 1
Pernyataan ALTER TABLE bertentangan dengan batasan KUNCI ASING "My_FORIEGN_KEY". Konflik terjadi di basis data "fiddle_792fce5de09f42908c3a0f91421f3522", tabel "dbo.a", kolom 'bantuan'.
ypercubeᵀᴹ
sumber
1
Terima kasih. Wrt ALTER TABLE b WITH NOCHECK CHECK CONSTRAINT [My_FORIEGN_KEY]; -- enable constraint without checking, apakah ini berarti bahwa kendala tidak akan memeriksa data yang ada, hanya data yang masuk baru?
BanksySan
1
Persis. Lihat bagaimana sisipan berikutnya (bantuan = 6) tidak diizinkan tetapi baris yang ada (dengan bantuan = 4) masih ada.
ypercubeᵀᴹ
Itu menunjukkan dengan sempurna.
BanksySan
1

Pertimbangkan membaca artikel di sini: https://msdn.microsoft.com/en-us/library/ms190273.aspx

Ini memberi tahu kita: 'Pengoptimal kueri tidak mempertimbangkan kendala yang ditentukan DENGAN NOCHECK. Kendala seperti itu diabaikan sampai diaktifkan kembali dengan menggunakan tabel ALTER TABLE WITH CHECK CHECK CONSTRAINT ALL '

Juga, pertimbangkan utas ini di StackOverflow: /programming/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

George K.
sumber