Nếu bạn có một ràng buộc khóa ngoại trong SQL Server hiện đã bị vô hiệu hóa, bạn có thể sử dụng mã bên dưới để kích hoạt lại nó.
Khi bạn bật ràng buộc khóa ngoại, bạn có tùy chọn để chỉ định có kiểm tra bất kỳ dữ liệu hiện có nào trong bảng hay không. Điều này cũng áp dụng khi bạn bật CHECK
ràng buộc.
Dưới đây là các ví dụ mã về cách bật ràng buộc khóa ngoại, đồng thời chỉ định từng tùy chọn khác nhau này.
Ví dụ 1 - Bật Ràng buộc bằng CÙNG KIỂM TRA
Đây là phương pháp được khuyến khích (trừ khi bạn có lý do cụ thể để không sử dụng nó).
Dưới đây là một ví dụ về cách bật ràng buộc khóa ngoại có tên là FK_Albums_Artists
:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists;
Ở đây tôi nêu rõ ràng WITH CHECK
, yêu cầu SQL Server kiểm tra dữ liệu hiện có trước khi bật ràng buộc. Nếu bất kỳ dữ liệu nào vi phạm ràng buộc, ràng buộc sẽ không được bật và bạn sẽ gặp lỗi.
Điều này là tốt, vì nó thực thi tính toàn vẹn của tham chiếu.
Khi bạn tạo một ràng buộc khóa ngoại mới, đây là cài đặt mặc định. Tuy nhiên, khi bạn bật một ràng buộc hiện có (như chúng tôi đang làm ở đây), điều đó không cài đặt mặc định.
Ví dụ 2 - Bật Ràng buộc bằng WITH NOCHECK
Trong ví dụ này, ràng buộc được bật mà không cần kiểm tra dữ liệu hiện có:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists;
Ở đây tôi nêu rõ ràng WITH NOCHECK
, thông báo cho SQL Server không kiểm tra dữ liệu hiện có. Điều này có nghĩa là ràng buộc sẽ được kích hoạt ngay cả khi bảng đã chứa dữ liệu vi phạm ràng buộc.
Đây là cài đặt mặc định khi bật một ràng buộc (nhưng không phải khi tạo một ràng buộc).
Một trong số ít lý do (có thể là lý do duy nhất) bạn sẽ sử dụng điều này là nếu bạn muốn giữ dữ liệu không hợp lệ trong cơ sở dữ liệu. Có lẽ bạn có một ngoại lệ duy nhất trong đó bạn phải nhập một hàng hoặc nhiều dữ liệu không hợp lệ, nhưng bạn yêu cầu tất cả dữ liệu trong tương lai phải tuân theo ràng buộc.
Tuy nhiên, vẫn có những rủi ro liên quan đến việc làm này. Đây là những gì Microsoft phải nói về điều này:
Chúng tôi khuyên bạn không nên làm điều này, trừ một số trường hợp hiếm hoi. Ràng buộc mới được đánh giá trong tất cả các bản cập nhật dữ liệu sau này. Bất kỳ vi phạm ràng buộc nào được ngăn chặn bởi
WITH NOCHECK
khi ràng buộc được thêm vào có thể khiến các bản cập nhật trong tương lai không thành công nếu chúng cập nhật các hàng có dữ liệu không tuân theo ràng buộc.
Vì vậy, sử dụng WITH NOCHECK
có thể gây ra sự cố sau này.
Ví dụ 3 - Bật Ràng buộc bằng Tùy chọn mặc định
Dưới đây là một ví dụ sử dụng tùy chọn mặc định:
ALTER TABLE Albums CHECK CONSTRAINT FK_Albums_Artists;
Ví dụ này tương đương với ví dụ trước. Bởi vì tôi không chỉ định có kiểm tra hay không, SQL Server giả định rằng tôi muốn WITH NOCHECK
.
Vì vậy, hãy đảm bảo chỉ định rõ ràng WITH CHECK
nếu bạn muốn tránh các vấn đề về tính toàn vẹn của tham chiếu.
Sử dụng VỚI NOCHECK làm mất đi sự tin cậy
Khi bạn bật một ràng buộc bằng (mặc định) WITH NOCHECK
, một hệ quả mà bạn nên biết là SQL Server sẽ không còn tin tưởng vào ràng buộc đó nữa. Nó gắn cờ nó là không đáng tin cậy. Trên thực tế, nó đã bị gắn cờ là không đáng tin cậy khi bạn tắt ràng buộc.
SQL Server có is_not_trusted
gắn cờ mà nó đặt thành 1
khi bạn tắt ràng buộc khóa ngoại (có nghĩa là nó không đáng tin cậy) và cách duy nhất để đặt nó thành 0
(đáng tin cậy) là chỉ định WITH CHECK
khi bật lại ràng buộc. Mặt khác, sử dụng WITH NOCHECK
chỉ bật nó mà không cần kiểm tra dữ liệu hiện có.
Bằng cách sử dụng WITH CHECK
, bạn đảm bảo rằng ràng buộc sẽ kiểm tra tất cả dữ liệu hiện có trước khi nó được kích hoạt. Cách duy nhất nó có thể được kích hoạt là nếu tất cả dữ liệu hiện có tuân theo ràng buộc. Khi nó đã kiểm tra tất cả dữ liệu hiện có, ràng buộc sau đó có thể được tin cậy.
Ví dụ 4 - Kiểm tra Trạng thái Tin cậy / Bị vô hiệu hóa
Bạn có thể kiểm tra trạng thái đáng tin cậy và bị vô hiệu hóa bằng cách truy vấn sys.foreign_keys
chế độ xem hệ thống.
Như thế này:
SELECT name AS 'Constraint', is_disabled, is_not_trusted FROM sys.foreign_keys;
Kết quả:
+-------------------+---------------+------------------+ | Constraint | is_disabled | is_not_trusted | |-------------------+---------------+------------------| | FK_Albums_Artists | 0 | 1 | | FK_Albums_Genres | 0 | 0 | +-------------------+---------------+------------------+
Điều này cho tôi biết rằng ràng buộc mà tôi đã bật trong ví dụ trước ( FK_Albums_Artists ) không được tin cậy.
Điều này là do tôi đã bật nó bằng cách sử dụng cài đặt mặc định, là WITH NOCHECK
.
Nếu tôi bật lại nó bằng cách sử dụng WITH CHECK
, đây là những gì sẽ xảy ra:
ALTER TABLE Albums WITH CHECK CHECK CONSTRAINT FK_Albums_Artists; SELECT name AS 'Constraint', is_disabled, is_not_trusted FROM sys.foreign_keys;
Kết quả:
+-------------------+---------------+------------------+ | Constraint | is_disabled | is_not_trusted | |-------------------+---------------+------------------| | FK_Albums_Artists | 0 | 0 | | FK_Albums_Genres | 0 | 0 | +-------------------+---------------+------------------+
May mắn thay trong trường hợp này, tôi không có bất kỳ dữ liệu nào vi phạm ràng buộc, vì vậy, ràng buộc đã được kích hoạt thành công và độ tin cậy của nó đã được khôi phục.
Nếu có dữ liệu vi phạm ràng buộc, một lỗi sẽ được hiển thị và tôi buộc phải sửa dữ liệu trước khi có thể khôi phục lòng tin vào ràng buộc.