Ràng buộc CHECK trong SQL Server
Trong hướng dẫn này, bạn sẽ học cách sử dụng ràng buộc CHECK
trong SQL Server để giới hạn các giá trị có thể được insert hoặc update vào một hoặc nhiều cột trong bảng.
Giới thiệu về ràng buộc CHECK trong SQL Server
Ràng buộc CHECK
trong SQL Server cho phép bạn chỉ định các giá trị trong một cột phải đáp ứng một biểu thức Boolean.
Ví dụ: để yêu cầu đơn giá lớn hơn 0, bạn có thể sử dụng:
CREATE SCHEMA test;
GO
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2) CHECK(unit_price > 0)
);
Như bạn có thể thấy, CHECK
định nghĩa ràng buộc nằm sau kiểu dữ liệu. Nó bao gồm từ khóa CHECK
theo sau là một biểu thức logic trong dấu ngoặc đơn:
CHECK(unit_price > 0)
Bạn cũng có thể gán cho ràng buộc một tên riêng bằng cách sử dụng từ khóa CONSTRAINT
như sau:
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2) CONSTRAINT positive_price CHECK(unit_price > 0)
);
Chỉ định tên ràng buộc rõ ràng giúp phân loại các thông báo lỗi và cho phép bạn tham chiếu đến các ràng buộc khi bạn muốn sửa đổi chúng.
Nếu bạn không chỉ định tên ràng buộc theo cách này, SQL Server sẽ tự động tạo tên cho bạn.
Xem câu lệnh insert sau:
INSERT INTO test.products(product_name, unit_price)
VALUES ('Awesome Free Bike', 0);
SQL Server sẽ thông báo lỗi sau:
The INSERT statement conflicted with the CHECK constraint "positive_price". The conflict occurred in database "BikeStores", table "test.products", column 'unit_price'.
Lỗi xảy ra do đơn giá không lớn hơn 0 như được chỉ định trong ràng buộc CHECK
.
Câu lệnh sau hoạt động tốt vì biểu thức logic được xác định trong ràng buộc CHECK
đánh giá là TRUE
:
INSERT INTO test.products(product_name, unit_price)
VALUES ('Awesome Bike', 599);
Ràng buộc CHECK và NULL trong SQL Server
Ràng buộc CHECK
từ chối các giá trị gây ra biểu thức Boolean được đánh giá FALSE
.
Vì NULL
đánh giá thành UNKNOWN
, nó có thể được sử dụng trong biểu thức để bỏ qua một ràng buộc.
Ví dụ: bạn có thể insert một sản phẩm có đơn giá NULL
như được hiển thị trong truy vấn sau:
INSERT INTO test.products(product_name, unit_price)
VALUES ('Another Awesome Bike', NULL);
Đây là kết quả:
(1 row affected)
SQL Server đã chèn NULL
vào cột unit_price
và không trả lại lỗi.
Để khắc phục điều này, bạn cần sử dụng một ràng buộc NOT NULL
cho cột unit_price
.
Ràng buộc CHECK tham chiếu đến nhiều cột
Một ràng buộc CHECK
có thể tham chiếu đến nhiều cột. Ví dụ: bạn lưu trữ giá thông thường và giá chiết khấu trong bảng test.products
và bạn muốn đảm bảo rằng giá chiết khấu luôn thấp hơn giá thông thường:
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2) CHECK(unit_price > 0),
discounted_price DEC(10,2) CHECK(discounted_price > 0),
CHECK(discounted_price < unit_price)
);
Hai ràng buộc đầu tiên cho unit_price
và discounted_price
nên trông quen thuộc.
Ràng buộc thứ ba sử dụng một cú pháp mới không được gắn vào một cột cụ thể. Thay vào đó, nó xuất hiện dưới dạng một hàng riêng biệt trong danh sách cột được phân tách bằng dấu phẩy.
Ràng buộc hai cột đầu tiên là ràng buộc cột, trong khi ràng buộc thứ ba là ràng buộc bảng.
Lưu ý: bạn có thể viết các ràng buộc cột dưới dạng các ràng buộc bảng. Tuy nhiên, bạn không thể viết ràng buộc bảng dưới dạng ràng buộc cột. Ví dụ, bạn có thể viết lại câu lệnh trên như sau:
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2),
discounted_price DEC(10,2),
CHECK(unit_price > 0),
CHECK(discounted_price > 0),
CHECK(discounted_price > unit_price)
);
hoặc thậm chí:
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2),
discounted_price DEC(10,2),
CHECK(unit_price > 0),
CHECK(discounted_price > 0 AND discounted_price > unit_price)
);
Bạn cũng có thể gán tên cho một ràng buộc bảng theo cách giống như một ràng buộc cột:
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2),
discounted_price DEC(10,2),
CHECK(unit_price > 0),
CHECK(discounted_price > 0),
CONSTRAINT valid_prices CHECK(discounted_price > unit_price)
);
Thêm ràng buộc CHECK vào bảng hiện có
Để thêm một ràng buộc CHECK
vào một bảng hiện có, bạn sử dụng câu lệnh ALTER TABLE ADD CONSTRAINT
.
Giả sử bạn có bảng test.products
sau:
CREATE TABLE test.products(
product_id INT IDENTITY PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
unit_price DEC(10,2) NOT NULL
);
Để thêm một ràng buộc CHECK
vào bảng test.products
, bạn sử dụng câu lệnh sau:
ALTER TABLE test.products
ADD CONSTRAINT positive_price CHECK(unit_price > 0);
Để thêm một cột mới với một ràng buộc CHECK
, bạn sử dụng câu lệnh sau:
ALTER TABLE test.products
ADD discounted_price DEC(10,2)
CHECK(discounted_price > 0);
Để thêm một ràng buộc CHECK
có tên valid_price
, bạn sử dụng câu lệnh sau:
ALTER TABLE test.products
ADD CONSTRAINT valid_price
CHECK(unit_price > discounted_price);
Xóa ràng buộc CHECK trong SQL Server
Để xóa một ràng buộc CHECK
, bạn sử dụng câu lệnh ALTER TABLE DROP CONSTRAINT
:
ALTER TABLE table_name
DROP CONSTRAINT constraint_name;
Nếu bạn gán cho một ràng buộc CHECK
một tên cụ thể, bạn có thể tham chiếu tên đó trong câu lệnh.
Tuy nhiên, trong trường hợp bạn không gán cho ràng buộc CHECK
một tên cụ thể, thì bạn cần phải tìm nó bằng cách sử dụng câu lệnh sau:
EXEC sp_help 'table_name';
Ví dụ:
EXEC sp_help 'test.products';
Câu lệnh này đưa ra rất nhiều thông tin bao gồm các tên ràng buộc:
Câu lệnh sau xóa ràng buộc positive_price
:
ALTER TABLE test.products
DROP CONSTRAINT positive_price;
Tắt ràng buộc CHECK để INSERT hoặc UPDATE
Để vô hiệu hóa một ràng buộc CHECK
cho việc insert hoặc update, bạn sử dụng câu lệnh sau:
ALTER TABLE table_name
NOCHECK CONSTRAINT constraint_name;
Câu lệnh sau vô hiệu hóa ràng buộc valid_price
:
ALTER TABLE test.products
NO CHECK CONSTRAINT valid_price;
Trong hướng dẫn này, bạn đã học cách sử dụng ràng buộc CHECK
trong SQL Server để giới hạn các giá trị có thể được insert hoặc update vào một hoặc nhiều cột trong bảng.