Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Yang Harus Anda Ketahui tentang WITH NOCHECK saat Mengaktifkan Batasan CHECK di SQL Server

Jika Anda pernah berada dalam situasi di mana Anda perlu mengaktifkan kembali CHECK kendala yang sebelumnya telah dinonaktifkan, Anda harus memastikan bahwa Anda tahu apa yang Anda lakukan.

Secara khusus, Anda harus memahami perbedaan antara WITH NOCHECK dan WITH CHECK argumen.

Argumen ini dapat digunakan pada saat Anda mengaktifkan batasan. Mereka menentukan apakah data yang ada divalidasi terhadap Anda yang diaktifkan kembali (atau baru ditambahkan) CHECK paksaan. Pada dasarnya Anda memiliki opsi untuk memeriksa semua data yang ada untuk setiap pelanggaran terhadap batasan. Jika Anda tidak menentukan apa pun, data yang ada tidak akan diperiksa. Itulah mengapa penting untuk memahami cara kerjanya.

Omong-omong, argumen ini juga berlaku untuk batasan kunci asing.

Seperti yang Anda harapkan, WITH CHECK menentukan bahwa data yang ada divalidasi dan WITH NOCHECK menentukan bahwa itu tidak. Standarnya adalah WITH NOCHECK .

Jika Anda menggunakan WITH NOCHECK , batasan akan ditandai sebagai tidak tepercaya. Sebenarnya, ini ditandai sebagai tidak tepercaya saat Anda menonaktifkan batasan. Tetapi ketika Anda mengaktifkannya kembali, itu akan tetap tidak dipercaya kecuali Anda menggunakan WITH CHECK . Dengan kata lain, jika Anda ingin menyatakan kembali "kepercayaan", Anda harus secara eksplisit menentukan ini.

Dengan kata lain:

  • Bila Anda menggunakan WITH NOCHECK , batasan akan tetap tidak dipercaya.
  • Bila Anda menggunakan WITH CHECK itu akan menjadi tepercaya, tetapi hanya jika semua data yang ada sesuai dengan batasan. Jika ada data yang melanggar batasan, batasan tidak akan diaktifkan dan Anda akan menerima pesan kesalahan.

Tentu saja, ketika saya mengatakan "semua data yang ada", saya hanya mengacu pada data yang batasannya berlaku.

Mungkin ada skenario di mana Anda dengan sengaja menonaktifkan batasan karena Anda harus memasukkan data yang melanggar batasan. Dalam kasus seperti itu, jika data yang tidak valid harus tetap berada di database, Anda harus menggunakan WITH NOCHECK jika Anda ingin mengaktifkan kembali batasan. Ini akan memungkinkan Anda untuk mengaktifkan batasan tanpa ada data yang menghalangi.

Di bawah ini adalah contoh yang menunjukkan hal ini.

Contoh 1 – Tinjau Periksa Batasan

Pertama, mari kita gunakan sys.check_constraints untuk melihat semua CHECK batasan dalam database saat ini.

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Hasil:

+-----------------+---------------+------------------+----------------------------------------+
| name            | is_disabled   | is_not_trusted   | definition                             |
|-----------------+---------------+------------------+----------------------------------------|
| chkPrice        | 0             | 0                | ([Price]>(0))                          |
| chkValidEndDate | 0             | 0                | ([EndDate]>=[StartDate])               |
| chkTeamSize     | 0             | 0                | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
| chkJobTitle     | 0             | 0                | ([JobTitle]<>'Digital Nomad')          |
+-----------------+---------------+------------------+----------------------------------------+

Kita dapat melihat bahwa semuanya diaktifkan dan dipercaya (karena semuanya memiliki nol di is_disabled dan is_not_trusted kolom).

Untuk artikel ini, saya akan menonaktifkan dan mengaktifkan kembali chkJobTitle kendala.

Contoh 2 – Nonaktifkan Batasan

Di sini, saya menonaktifkan chkJobTitle kendala:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

Selesai.

Sekarang mari kita tinjau kembali semua kendala:

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Hasil:

+-----------------+---------------+------------------+----------------------------------------+
| name            | is_disabled   | is_not_trusted   | definition                             |
|-----------------+---------------+------------------+----------------------------------------|
| chkPrice        | 0             | 0                | ([Price]>(0))                          |
| chkValidEndDate | 0             | 0                | ([EndDate]>=[StartDate])               |
| chkTeamSize     | 0             | 0                | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
| chkJobTitle     | 1             | 1                | ([JobTitle]<>'Digital Nomad')          |
+-----------------+---------------+------------------+----------------------------------------+

Kami dapat melihat bahwa itu telah dinonaktifkan (karena is_disabled kolom disetel ke 1 ).

Anda mungkin memperhatikan bahwa is_not_trusted kolom juga disetel ke 1 . Ini menunjukkan bahwa CHECK batasan belum diverifikasi oleh sistem untuk semua baris.

Seperti disebutkan, sebuah CHECK kendala hanya dapat dipercaya jika semua data telah berhasil melewati kondisi kendala. Saat kami menonaktifkan batasan, ini membuka potensi data yang tidak valid untuk masuk ke database. Oleh karena itu, kami tidak dapat 100% yakin bahwa semua data valid, sehingga batasan ditandai sebagai tidak tepercaya.

Cara untuk memastikan kendala dipercaya lagi adalah dengan mengaktifkannya kembali menggunakan WITH CHECK argumen. Ini akan menyebabkan batasan untuk memeriksa semua data sebelum diaktifkan kembali. Jika ada data yang tidak valid, itu tidak akan dapat diaktifkan kembali. Anda harus memperbarui data agar valid, atau mengaktifkan kembali batasan menggunakan WITH NOCHECK sebagai gantinya (yang akan menyebabkan kendala tetap tidak dipercaya).

Contoh 3 – Aktifkan Batasan menggunakan Pengaturan Default (DENGAN NOCHECK)

Mari aktifkan kembali batasan dan jalankan kueri lagi.

Untuk mengaktifkan batasan, saya akan malas dan menggunakan pengaturan default:

ALTER TABLE Occupation  
CHECK CONSTRAINT chkJobTitle; 

Sekarang verifikasi perubahannya:

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Hasil:

+-----------------+---------------+------------------+----------------------------------------+
| name            | is_disabled   | is_not_trusted   | definition                             |
|-----------------+---------------+------------------+----------------------------------------|
| chkPrice        | 0             | 0                | ([Price]>(0))                          |
| chkValidEndDate | 0             | 0                | ([EndDate]>=[StartDate])               |
| chkTeamSize     | 0             | 0                | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
| chkJobTitle     | 0             | 1                | ([JobTitle]<>'Digital Nomad')          |
+-----------------+---------------+------------------+----------------------------------------+

Apakah Anda melihat apa yang baru saja terjadi? Meskipun saya mengaktifkan batasan lagi, itu masih tidak dipercaya.

Ini karena saya malas (atau mungkin hanya pelupa) ketika saya mengaktifkan kendala. Ketika saya mengaktifkan batasan, saya lupa menentukan WITH CHECK . Standarnya adalah WITH NOCHECK yang berarti bahwa data yang ada tidak diperiksa saat mengaktifkan kembali batasan.

Inilah sebabnya mengapa Anda harus benar-benar tahu apa yang Anda lakukan saat mengaktifkan CHECK (dan FOREIGN KEY ) kendala. Dengan malas dan tidak secara eksplisit menentukan pengaturan yang berpotensi penting, kami memberikan izin kepada SQL Server untuk menutup mata terhadap masalah apa pun dengan data yang ada.

Namun, jika seluruh alasan Anda perlu menonaktifkan batasan adalah untuk memasukkan data yang melanggar batasan, maka default WITH NOCHECK mungkin yang Anda inginkan.

Omong-omong, untuk batasan baru, defaultnya adalah WITH CHECK .

Tetapi dalam kasus saya, saya tidak memasukkan atau memperbarui apa pun data setelah menonaktifkan kendala, jadi jika sebelumnya dapat dipercaya, sekarang harus tetap dapat dipercaya.

Jadi bagaimana saya bisa membuat batasan saya dipercaya lagi?

Contoh 4 – Aktifkan Batasan menggunakan WITH CHECK

Jika saya ingin batasan saya dipercaya lagi, saya perlu secara eksplisit menentukan WITH CHECK saat mengaktifkannya kembali.

Mari kita nonaktifkan kendala lagi:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

Jadi sekarang saya kembali ke tempat saya sebelum saya mengaktifkannya kembali.

Apa yang seharusnya saya lakukan ketika saya mengaktifkannya kembali adalah ini:

ALTER TABLE Occupation  
WITH CHECK CHECK CONSTRAINT chkJobTitle; 

Sekarang lihat lagi batasannya:

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Hasil:

+-----------------+---------------+------------------+----------------------------------------+
| name            | is_disabled   | is_not_trusted   | definition                             |
|-----------------+---------------+------------------+----------------------------------------|
| chkPrice        | 0             | 0                | ([Price]>(0))                          |
| chkValidEndDate | 0             | 0                | ([EndDate]>=[StartDate])               |
| chkTeamSize     | 0             | 0                | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
| chkJobTitle     | 0             | 0                | ([JobTitle]<>'Digital Nomad')          |
+-----------------+---------------+------------------+----------------------------------------+

Fiuh! Batasan saya dapat dipercaya sekali lagi.

Contoh 5 – Aktifkan Batasan CHECK dengan Data Tidak Valid

Tentu saja kendala saya hanya dipercaya lagi karena saya tidak memasukkan data yang tidak valid saat dinonaktifkan. Jika saya melakukan ini, saya tidak akan dapat mengaktifkannya menggunakan WITH CHECK , seperti yang ditunjukkan di bawah ini.

Jika saya menonaktifkannya lagi:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

Sekarang masukkan data yang tidak valid (dan kembalikan hasilnya):

INSERT INTO Occupation
VALUES ( 7, 'Digital Nomad' );

SELECT 
  OccupationId,
  JobTitle
FROM Occupation;

Hasil:

+----------------+-----------------+
| OccupationId   | JobTitle        |
|----------------+-----------------|
| 1              | Engineer        |
| 2              | Accountant      |
| 3              | Cleaner         |
| 4              | Attorney        |
| 5              | Sales Executive |
| 6              | Uber Driver     |
| 7              | Digital Nomad   |
+----------------+-----------------+

Jadi kami berhasil memasukkan data yang tidak valid (baris terakhir).

Ini tidak valid karena definisi batasan berjalan sebagai berikut:([JobTitle]<>'Digital Nomad')

Artinya JobTitle kolom tidak boleh berisi teks Digital Nomad .

Sekarang mari kita coba aktifkan kembali CHECK kendala menggunakan WITH CHECK dan lihat apa yang terjadi.

ALTER TABLE Occupation  
WITH CHECK CHECK CONSTRAINT chkJobTitle; 

Hasil:

Msg 547, Level 16, State 0, Line 1
The ALTER TABLE statement conflicted with the CHECK constraint "chkJobTitle". The conflict occurred in database "Test", table "dbo.Occupation", column 'JobTitle'.

Jadi kami tidak dapat mengaktifkan kembali batasan menggunakan WITH CHECK sementara kita punya data di tabel yang melanggar CHECK paksaan. Entah kita perlu memperbarui data atau kita perlu menggunakan WITH NOCHECK (atau cukup hilangkan sama sekali).

Mari kita coba lagi menggunakan WITH NOCHECK .

ALTER TABLE Occupation  
WITH NOCHECK CHECK CONSTRAINT chkJobTitle; 

Hasil:

Commands completed successfully.
Total execution time: 00:00:00.015

Jadi kita bisa berhasil mengaktifkan kendala jika kita tidak memeriksa data yang ada.

Tentu saja, dalam hal ini CHECK kendala masih belum dipercaya. Jika kita ingin batasan dipercaya, kita perlu memperbarui data agar tidak melanggar batasan.

Contoh:

UPDATE Occupation
SET JobTitle = 'Unemployed'
WHERE OccupationId = 7;

SELECT 
  OccupationId,
  JobTitle
FROM Occupation;

Hasil:

+----------------+-----------------+
| OccupationId   | JobTitle        |
|----------------+-----------------|
| 1              | Engineer        |
| 2              | Accountant      |
| 3              | Cleaner         |
| 4              | Attorney        |
| 5              | Sales Executive |
| 6              | Uber Driver     |
| 7              | Unemployed      |
+----------------+-----------------+

Sekarang kita dapat mengubah CHECK kendala untuk dipercaya kembali.

Mari kita lakukan ketiganya bersama-sama:

ALTER TABLE Occupation  
NOCHECK CONSTRAINT chkJobTitle; 

ALTER TABLE Occupation  
WITH CHECK CHECK CONSTRAINT chkJobTitle; 

SELECT 
  name,
  is_disabled,
  is_not_trusted,
  definition
FROM sys.check_constraints;

Hasil:

+-----------------+---------------+------------------+----------------------------------------+
| name            | is_disabled   | is_not_trusted   | definition                             |
|-----------------+---------------+------------------+----------------------------------------|
| chkPrice        | 0             | 0                | ([Price]>(0))                          |
| chkValidEndDate | 0             | 0                | ([EndDate]>=[StartDate])               |
| chkTeamSize     | 0             | 0                | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
| chkJobTitle     | 0             | 0                | ([JobTitle]<>'Digital Nomad')          |
+-----------------+---------------+------------------+----------------------------------------+

Jadi sekarang batasan kami diaktifkan dan dipercaya sekali lagi, dan database kami bebas dari digital nomad!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara menggunakan SEMUA Operator Logika di SQL Server - Tutorial SQL Server / TSQL Bagian 126

  2. Tambahkan Langkah Pekerjaan ke Pekerjaan Agen Server SQL yang Ada (T-SQL)

  3. Fungsi String SQL Server (Daftar Lengkap)

  4. T-SQL Lewati Ambil Prosedur Tersimpan

  5. Bagaimana saya bisa membuat permintaan HTTP dari server SQL?