Khi bạn tạo CHECK
trong SQL Server, bạn thậm chí có thể không nghĩ đó là ràng buộc cấp bảng hay ràng buộc cấp cột.
CHECK
cấp bảng ràng buộc áp dụng cho bảng, trong khi ràng buộc cấp cột áp dụng cho một cột cụ thể. Với CHECK
cấp bảng ràng buộc, đó là hàng được kiểm tra khi kiểm tra dữ liệu. Với CHECK
cấp cột ràng buộc, đó là cột cụ thể được kiểm tra.
Nói chung, bạn sẽ biết liệu ràng buộc bạn đang tạo có phải là ràng buộc cấp bảng hay cấp cột hay không theo định nghĩa mà bạn đưa ra. Nếu chỉ một cột đang được kiểm tra trong biểu thức, nó sẽ là một ràng buộc cấp cột. Nếu không, nó sẽ là một ràng buộc cấp bảng.
Nhưng làm cách nào để biết liệu các ràng buộc hiện tại của bạn là cấp cột hay cấp bảng?
Bạn có thể chạy bất kỳ ví dụ mã nào bên dưới để xác định xem các ràng buộc hiện tại của bạn là cấp cột hay cấp bảng. Những thứ này truy xuất tất cả CHECK
các ràng buộc đối với cơ sở dữ liệu hiện tại, nhưng bạn luôn có thể sử dụng WHERE
để thu hẹp nó thành một ràng buộc cụ thể.
Ví dụ 1 - Truy vấn cơ bản
Đây là một truy vấn đơn giản trả về thông tin cơ bản về tất cả CHECK
các ràng buộc trong cơ sở dữ liệu hiện tại.
Tại đây, tôi truy vấn sys.check_constraints
chế độ xem hệ thống (trả về một hàng cho mỗi đối tượng là CHECK
ràng buộc, với sys.objects.type = 'C'
). Tôi chỉ trả về bốn cột (nhưng bạn có thể trả lại bao nhiêu cột tùy thích).
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints;
Kết quả:
+-----------------+----------------+--------------------+----------------------------------------+ | Name | Table | parent_column_id | Definition | |-----------------+----------------+--------------------+----------------------------------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | | chkValidEndDate | ConstraintTest | 0 | ([EndDate]>=[StartDate]) | | chkTeamSize | ConstraintTest | 3 | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | Occupation | 3 | ([JobTitle]<>'Digital Nomad') | +-----------------+----------------+--------------------+----------------------------------------+
Cách nhanh nhất để xác định ràng buộc nào là ràng buộc cấp bảng là tìm giá trị 0 (
0
) trong
parent_column_id
cột. Bất kỳ thứ gì có số 0 đều là CHECK
cấp bảng hạn chế. Giá trị khác 0 cho biết rằng đó là CHECK
cấp cột ràng buộc được xác định trên cột với giá trị ID được chỉ định.
Vì vậy, trong ví dụ này có ba ràng buộc cấp cột và một ràng buộc cấp bảng.
Lưu ý rằng có hai ràng buộc với cùng một parent_column_id (3), tuy nhiên, hai ràng buộc này là từ các bảng khác nhau. Số 3 đề cập đến cột thứ ba trong các bảng tương ứng của chúng.
Như đã đề cập, nếu bạn chỉ muốn thông tin về một ràng buộc cụ thể, hãy sử dụng WHERE
mệnh đề:
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints WHERE name = 'chkPrice';
Kết quả:
+----------+----------------+--------------------+---------------+ | Name | Table | parent_column_id | Definition | |----------+----------------+--------------------+---------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | +----------+----------------+--------------------+---------------+
Ví dụ 2 - Cải thiện Truy vấn
Chúng ta có thể cải thiện ví dụ trước bằng cách trả về tên cột cha thay vì chỉ ID của nó. Tất nhiên, điều này sẽ trả về tên cột chỉ cho các ràng buộc cấp cột. Đối với các ràng buộc cấp bảng, NULL sẽ được trả về.
SELECT cc.name AS 'Constraint', o.name AS 'Table', ac.name AS 'Column', cc.Definition AS 'Constraint Definition' FROM sys.check_constraints cc LEFT OUTER JOIN sys.objects o ON cc.parent_object_id = o.object_id LEFT OUTER JOIN sys.all_columns ac ON cc.parent_column_id = ac.column_id AND cc.parent_object_id = ac.object_id;
Kết quả:
+-----------------+----------------+----------+----------------------------------------+ | Constraint | Table | Column | Constraint Definition | |-----------------+----------------+----------+----------------------------------------| | chkPrice | ConstraintTest | Price | ([Price]>(0)) | | chkValidEndDate | ConstraintTest | NULL | ([EndDate]>=[StartDate]) | | chkTeamSize | ConstraintTest | TeamSize | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | Occupation | JobTitle | ([JobTitle]<>'Digital Nomad') | +-----------------+----------------+----------+----------------------------------------+
Ví dụ 3 - Cải tiến Hơn nữa
Hãy điều chỉnh thêm một số truy vấn:
SELECT cc.name AS 'Constraint', cc.is_disabled AS 'Disabled?', CASE WHEN cc.parent_column_id = 0 THEN 'Table-level' ELSE 'Column-level' END AS 'Table/Column', o.name AS 'Table', ISNULL(ac.name, '(n/a)') AS 'Column', cc.Definition AS 'Constraint Definition' FROM sys.check_constraints cc LEFT OUTER JOIN sys.objects o ON cc.parent_object_id = o.object_id LEFT OUTER JOIN sys.all_columns ac ON cc.parent_column_id = ac.column_id AND cc.parent_object_id = ac.object_id;
Kết quả:
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+ | Constraint | Disabled? | Table/Column | Table | Column | Constraint Definition | |-----------------+-------------+----------------+----------------+----------+----------------------------------------| | chkPrice | 0 | Column-level | ConstraintTest | Price | ([Price]>(0)) | | chkValidEndDate | 0 | Table-level | ConstraintTest | (n/a) | ([EndDate]>=[StartDate]) | | chkTeamSize | 0 | Column-level | ConstraintTest | TeamSize | ([TeamSize]>=(5) AND [TeamSize]<=(20)) | | chkJobTitle | 0 | Column-level | Occupation | JobTitle | ([JobTitle]<>'Digital Nomad') | +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
Vì vậy, bây giờ tôi có văn bản "Cấp cột" hoặc "Cấp bảng" được trả về, tùy thuộc vào đó là văn bản nào.
Tôi cũng sử dụng ISNULL()
hàm để biến bất kỳ giá trị NULL nào thành “(n / a)”.
Và tôi cũng đã thêm is_disabled vào danh sách, đề phòng trường hợp bất kỳ ràng buộc nào đã bị vô hiệu hóa. Bạn luôn có thể cung cấp cho cột này cùng cách xử lý với parent_column_id và hiển thị “Có” hoặc “Không” hoặc “Đã bật” hoặc “Đã tắt” hoặc tương tự.