Ràng buộc toàn vẹn trong SQL là các quy tắc áp dụng trên bảng cơ sở dữ liệu để duy trì tính chính xác, nhất quán và hợp lệ của dữ liệu, như đảm bảo khóa chính là duy nhất và mối quan hệ khóa ngoại hợp lệ.
Hãy hình dung một cơ sở dữ liệu bệnh viện nơi thông tin dị ứng của bệnh nhân không được để trống, hoặc một hệ thống tài chính nơi số tiền giao dịch phải là số dương. Trong những tình huống này và vô số tình huống khác, chúng ta dựa vào các ràng buộc toàn vẹn để đảm bảo dữ liệu luôn chính xác, nhất quán và đáng tin cậy.
Trong SQL, ràng buộc toàn vẹn là các quy tắc chúng ta áp dụng lên các bảng cơ sở dữ liệu để duy trì chất lượng dữ liệu. Chúng giúp ngăn lỗi, thực thi các quy tắc nghiệp vụ và đảm bảo dữ liệu phản ánh đúng các thực thể và mối quan hệ ngoài đời thực mà nó biểu diễn.
Trong bài viết này, chúng ta sẽ đi sâu vào các loại ràng buộc toàn vẹn thiết yếu trong SQL, kèm giải thích rõ ràng và ví dụ thực tiễn minh họa cách dùng trong cơ sở dữ liệu PostgreSQL. Dù sử dụng cú pháp PostgreSQL, các khái niệm này có thể áp dụng dễ dàng cho các biến thể SQL khác.
Nếu bạn muốn học thêm về SQL, hãy xem danh sách các khóa học SQL này.
Ràng Buộc Toàn Vẹn trong SQL là gì?
Hãy xét một tình huống có bảng lưu thông tin người dùng cho một ứng dụng web. Một số dữ liệu như tuổi người dùng có thể là tùy chọn vì không ảnh hưởng đến việc truy cập ứng dụng. Tuy nhiên, mật khẩu cho mỗi người dùng là bắt buộc để đăng nhập. Để xử lý điều này, chúng ta sẽ áp dụng một ràng buộc toàn vẹn lên cột mật khẩu trong bảng người dùng để đảm bảo mọi bản ghi trong bảng đều có mật khẩu.
Về bản chất, ràng buộc toàn vẹn rất quan trọng để:
Ngăn dữ liệu bị thiếu.
Đảm bảo mọi dữ liệu tuân theo kiểu và phạm vi giá trị kỳ vọng.
Duy trì các liên kết đúng đắn giữa dữ liệu ở các bảng khác nhau.
Trong bài này, chúng ta sẽ khám phá các ràng buộc toàn vẹn thiết yếu sau trong SQL:
PRIMARY KEY: Nhận diện duy nhất mỗi bản ghi trong một bảng.
NOT NULL: Đảm bảo một cột không thể chứa giá trị NULL.
UNIQUE: Đảm bảo tất cả giá trị trong một cột hoặc nhóm cột là duy nhất.
DEFAULT: Cung cấp giá trị mặc định cho một cột khi không được chỉ định.
CHECK: Đảm bảo mọi giá trị trong một cột thỏa mãn một điều kiện cụ thể.
FOREIGN KEY: Thiết lập quan hệ giữa các bảng bằng cách tham chiếu đến khóa chính ở bảng khác.
Bài Toán Nghiên Cứu: Cơ Sở Dữ Liệu Trường Đại Học
Hãy xét một cơ sở dữ liệu quan hệ cho một trường đại học. Cơ sở dữ liệu này có ba bảng: students, courses và enrollments.
Bảng Students
Bảng students lưu thông tin về tất cả sinh viên của trường.
student_id: Định danh của sinh viên
first_name: Tên của sinh viên.
last_name: Họ của sinh viên.
email: Địa chỉ email của sinh viên.
major: Chuyên ngành của sinh viên.
enrollment_year: Năm sinh viên nhập học.
Bảng Courses
Bảng courses lưu thông tin về các học phần có tại trường.
course_id: Định danh học phần.
course_name: Tên học phần.
department: Khoa/phòng ban phụ trách học phần.
Bảng Enrollments
Bảng enrollments lưu thông tin về sinh viên nào đăng ký học phần nào.
student_id: Định danh của sinh viên đăng ký học phần.
course_id: Định danh của học phần.
year: Năm đăng ký.
grade: Điểm của sinh viên ở học phần này.
is_passing_grade: Boolean cho biết điểm có đạt yêu cầu hay không.
Xuyên suốt bài viết, chúng ta sẽ dùng cơ sở dữ liệu ví dụ này và trình bày nhiều cách để đảm bảo toàn vẹn dữ liệu. Chúng ta sử dụng cú pháp PostgreSQL trong truy vấn, tuy nhiên các khái niệm rất dễ chuyển sang những biến thể SQL khác.
Ràng Buộc PRIMARY KEY
Trường đại học muốn nhận diện duy nhất từng sinh viên. Sử dụng tên và họ cho mục đích này không phù hợp do có thể trùng tên giữa các sinh viên. Tương tự, dựa vào địa chỉ email cũng không lý tưởng vì sinh viên có thể thay đổi email.
Giải pháp phổ biến để đảm bảo nhận diện duy nhất là gán cho mỗi sinh viên một mã định danh duy nhất, lưu trong cột student_id. Chúng ta có thể áp dụng ràng buộc PRIMARY KEY lên cột student_id để bảo đảm mỗi sinh viên có một định danh duy nhất.
Ràng buộc này được định nghĩa trong lệnh CREATE TABLE, ngay sau phần khai báo kiểu dữ liệu của cột:
CREATETABLE students (
student_id INTPRIMARYKEY,
first_name TEXT,
last_name TEXT,
email TEXT,
major TEXT,
enrollment_year INT);Được hỗ trợ bởi
Truy vấn trên tạo bảng sinh viên với sáu cột như đã nêu.
Ràng buộc PRIMARY KEY đảm bảo rằng:
Mỗi sinh viên có một student_id.
Mỗi student_id là duy nhất.
Ràng buộc PRIMARY KEY trên nhiều cột
Trong một số tình huống, chúng ta cần sử dụng nhiều cột để nhận diện duy nhất mỗi hàng. Chẳng hạn bảng enrollments. Một sinh viên có thể đăng ký nhiều học phần, dẫn đến nhiều hàng có cùng student_id. Tương tự, một học phần có thể có nhiều sinh viên, dẫn đến nhiều hàng có cùng course_id.
Vì không có trường đơn lẻ nào nhận diện duy nhất một hàng, mỗi bản ghi đăng ký được xác định bằng kết hợp student_id, course_id và year.
Khi có nhiều cột, ràng buộc PRIMARY KEY được chỉ định ở cuối lệnh CREATE TABLE.
Có hai cách để thêm ràng buộc toàn vẹn. Chúng ta vừa học cách làm khi tạo bảng.
Giả sử bảng đã tồn tại nhưng bạn quên chỉ định ràng buộc PRIMARY KEY. Bạn cũng có thể định nghĩa sau khi tạo bảng bằng lệnh ALTER TABLE như sau:
ALTERTABLE enrollments
ADDCONSTRAINT enroll_pk
PRIMARYKEY(student_id, course_id,year);Được hỗ trợ bởi
Trong truy vấn ALTER TABLE, chúng ta đặt tên ràng buộc là enroll_pk (viết tắt của primary key của bảng enrollments). Tên này có thể là bất kỳ định danh nào bạn chọn, nhưng nên chọn tên truyền tải ngắn gọn mục đích của ràng buộc.
Việc đặt tên cho ràng buộc toàn vẹn là thực hành tốt vì mang lại vài lợi ích:
Giúp tham chiếu dễ dàng hơn, đặc biệt khi bạn cần sửa hoặc xóa ràng buộc sau này.
Hỗ trợ quản lý và tổ chức ràng buộc, nhất là trong các cơ sở dữ liệu có số lượng ràng buộc lớn.
Ràng Buộc NOT NULL
Trường đại học muốn đảm bảo tên và email của mọi sinh viên đều được ghi nhận trong cơ sở dữ liệu. Họ không muốn nhân viên vô tình quên nhập bất kỳ trường nào trong số đó.
Để xử lý, chúng ta có thể dùng các ràng buộc NOT NULL trên ba cột này khi tạo bảng:
CREATETABLE students (
student_id INT,
first_name TEXTNOTNULL,
last_name TEXTNOTNULL,
email TEXTNOTNULL,
major TEXT,
enrollment_year INT);Được hỗ trợ bởi
Truy vấn trên sử dụng ràng buộc NOT NULL để đảm bảo các cột first_name, last_name và email không thể có giá trị NULL (không xác định).
Thêm ràng buộc NOT NULL vào một bảng hiện có có thể thực hiện bằng lệnh ALTER TABLE. Cú pháp để thêm ràng buộc NOT NULL như sau:
ALTERTABLE students
ALTERCOLUMN first_name SETNOTNULL,ALTERCOLUMN last_name SETNOTNULL,ALTERCOLUMN email SETNOTNULL;Được hỗ trợ bởi
Ràng Buộc UNIQUE
Địa chỉ email vốn dĩ là duy nhất với mỗi cá nhân. Trong những tình huống chúng ta chắc chắn một trường không bao giờ được lặp giá trị, việc thực thi điều này ở cấp cơ sở dữ liệu là thực hành tốt. Điều này giúp ngăn sai sót và đảm bảo toàn vẹn dữ liệu.
Việc thêm ràng buộc này thực hiện tương tự như các ràng buộc khác.
CREATETABLE students (...
email TEXTUNIQUE,...);Được hỗ trợ bởi
Tuy nhiên, trong trường hợp của chúng ta, ta cũng muốn áp dụng ràng buộc NOT NULL. Ta có thể áp dụng nhiều ràng buộc trên một cột bằng cách đặt cách nhau bằng khoảng trắng:
CREATETABLE students (...
email TEXTUNIQUENOTNULL,...);Được hỗ trợ bởi
Lưu ý thứ tự không quan trọng, ta cũng có thể dùng NOT NULL UNIQUE.
Thêm ràng buộc UNIQUE vào một bảng hiện có được thực hiện như sau:
ALTERTABLE students
ADDCONSTRAINT unique_emails UNIQUE(email);Được hỗ trợ bởi
Ràng buộc UNIQUE trên nhiều cột
Giả sử chúng ta muốn đảm bảo tên học phần của mỗi khoa là duy nhất trong bảng courses. Khi đó, hai cột course_name và department kết hợp với nhau phải là duy nhất.
Khi có nhiều cột, ràng buộc được thêm ở cuối lệnh CREATE TABLE:
CREATETABLE courses (
course_id INT,
course_name TEXT,
department TEXT,UNIQUE(course_name, department));Được hỗ trợ bởi
Ngoài ra, chúng ta có thể thêm ràng buộc bằng cách sửa bảng hiện có. Khi đó, ta cung cấp một bộ gồm tên các cột:
ALTERTABLE courses
ADDCONSTRAINT unique_course_name_department
UNIQUE(course_name, department);Được hỗ trợ bởi
So sánh NOT NULL UNIQUE và PRIMARY KEY
Chúng ta đã biết ràng buộc PRIMARY KEY vừa đảm bảo tính duy nhất vừa không có giá trị thiếu. Vậy khác biệt giữa:
Sự khác nhau giữa NOT NULL UNIQUE và PRIMARY KEY trên một bảng nằm ở mục đích và cách sử dụng.
Dù cả hai đều thực thi tính duy nhất và không rỗng trên cột (hoặc các cột), một bảng chỉ có duy nhất một PRIMARY KEY, dùng để nhận diện duy nhất mỗi bản ghi trong bảng.
Mặt khác, tổ hợp ràng buộc NOT NULL UNIQUE có thể áp dụng cho các cột bổ sung để đảm bảo giá trị duy nhất trên mỗi hàng và không có giá trị rỗng, phục vụ việc duy trì toàn vẹn dữ liệu theo các quy tắc nghiệp vụ cụ thể. Một bảng có thể có bất kỳ số lượng ràng buộc NOT NULL UNIQUE nào.
Sự tồn tại của cả hai loại mang lại tính linh hoạt cao hơn trong thiết kế cơ sở dữ liệu, cho phép nhiều cách để thực thi tính duy nhất và toàn vẹn dữ liệu, đồng thời phân biệt giữa định danh chính của bản ghi và các thuộc tính quan trọng, duy nhất khác trong bảng.
Ràng Buộc DEFAULT
Sinh viên có thể cần một thời gian sau khi đăng ký nhập học để chọn chuyên ngành. Trường muốn giá trị của cột chuyên ngành là chuỗi ’Undeclared’ cho các sinh viên chưa chọn chuyên ngành.
Để làm vậy, chúng ta có thể đặt giá trị mặc định cho cột này bằng ràng buộc DEFAULT. Ta có thể sửa bảng students như sau:
ALTERTABLE students
ALTERCOLUMN major SETDEFAULT'Undeclared';Được hỗ trợ bởi
Nếu muốn đặt ràng buộc DEFAULT ngay khi tạo bảng, ta có thể khai báo sau kiểu dữ liệu của cột:
CREATETABLE students (...
major TEXTDEFAULT'Undeclared',...);Được hỗ trợ bởi
Ràng Buộc CHECK
Tại trường đại học này, thang điểm từ 0 đến 100. Nếu không có ràng buộc nào, cột grade của bảng enrollment sẽ chấp nhận mọi số nguyên. Chúng ta có thể khắc phục bằng ràng buộc CHECK để buộc giá trị nằm trong khoảng 0 đến 100.
ALTERTABLE enrollments
ADDCONSTRAINT grade_range CHECK(grade BETWEEN0AND100);Được hỗ trợ bởi
Nói chung, ràng buộc CHECK cho phép chúng ta xác thực các điều kiện cụ thể mà dữ liệu cần thỏa. Đây là những ràng buộc quan trọng để đảm bảo tính nhất quán và toàn vẹn dữ liệu.
Một ràng buộc CHECK có thể liên quan đến nhiều hơn một cột. Hãy dùng nó để đảm bảo grade và is_passing_grade có giá trị nhất quán. Giả sử một điểm được coi là đạt nếu có giá trị ít nhất 60. Khi đó, chúng ta có thể đảm bảo is_passing_grade là TRUE khi và chỉ khi điểm từ 60 trở lên. Hãy thực hiện ngay trong lúc tạo bảng để minh họa cách khai báo ràng buộc CHECK trong lệnh CREATE TABLE:
Có một vấn đề với ràng buộc trên. Khi sinh viên đăng ký một học phần, họ chưa có điểm. Vì vậy, chúng ta nên cho phép giá trị NULL ở cột điểm. Khi làm vậy, ta cũng cần cập nhật ràng buộc điểm đạt để là NULL khi điểm chưa được xác định. Dưới đây là cách cập nhật ràng buộc để tính đến các trường hợp này:
Ràng buộc khóa ngoại được dùng để liên kết các cột của hai bảng với nhau, đảm bảo tính toàn vẹn tham chiếu của dữ liệu. Về bản chất, một khóa ngoại trong bảng này trỏ đến một khóa chính ở bảng khác, cho biết các hàng ở hai bảng này có liên quan. Điều này đảm bảo bạn không thể có một hàng trong bảng với khóa ngoại mà không khớp với bất kỳ hàng nào ở bảng được liên kết có khóa chính.
Trong ví dụ của chúng ta, mỗi bản ghi trong bảng enrollments tham chiếu đến một sinh viên và một học phần thông qua các cột student_id và course_id tương ứng. Nếu không có ràng buộc nào, sẽ không có gì đảm bảo rằng các giá trị định danh này trong bảng enrollments khớp với các bản ghi hiện có trong bảng students và courses.
Đây là cách chúng ta đảm bảo điều đó khi tạo bảng enrollments:
Xuyên suốt bài viết, chúng ta đã trình bày nhiều ràng buộc toàn vẹn và cách dùng để cải thiện cơ sở dữ liệu của một trường đại học. Dưới đây là phiên bản cuối cùng của lệnh CREATE TABLE, kết hợp mọi thứ chúng ta đã học.
Trước hết, chúng ta sẽ định nghĩa bảng students:
CREATETABLE students (
student_id INTPRIMARYKEY,
first_name TEXTNOTNULL,
last_name TEXTNOTNULL,
email TEXTUNIQUENOTNULL,
major TEXTDEFAULT'Undeclared',
enrollment_year INT,CONSTRAINT year_check CHECK(enrollment_year >=1900),CHECK(major IN('Undeclared','Computer Science','Mathematics','Biology','Physics','Chemistry','Biochemistry')));Được hỗ trợ bởi
Tiếp theo, hãy định nghĩa bảng courses:
CREATETABLE courses (
course_id INTPRIMARYKEY,
course_name TEXTNOTNULL,
department TEXTNOTNULL,UNIQUE(course_name, department),CHECK(department IN('Physics & Mathematics','Sciences')));Được hỗ trợ bởi
Cuối cùng, chúng ta sẽ định nghĩa bảng enrollments, thiết lập các mối quan hệ giữa sinh viên và học phần:
Chúng ta đã thêm một vài ràng buộc trong ví dụ cuối cùng này. Một trường đại học có tập hợp khoa và chuyên ngành đã biết trước. Do đó, tập giá trị mà các cột major và department có thể nhận là hữu hạn và biết trước. Trong những tình huống như vậy, nên dùng ràng buộc CHECK để đảm bảo các cột chỉ nhận giá trị từ tập đã biết đó.
Kết Luận
Trong bài viết này, chúng ta đã khám phá các loại ràng buộc toàn vẹn khác nhau trong SQL và cách triển khai chúng bằng PostgreSQL. Chúng ta đã đề cập đến khóa chính, ràng buộc NOT NULL, ràng buộc UNIQUE, ràng buộc DEFAULT, ràng buộc CHECK và ràng buộc FOREIGN KEY, kèm ví dụ thực tiễn cho từng loại.
Bằng cách hiểu các khái niệm này, chúng ta có thể đảm bảo tính chính xác, nhất quán và độ tin cậy của dữ liệu.
Nếu bạn muốn học thêm về cách tổ chức dữ liệu hiệu quả, hãy xem khóa học về Thiết kế Cơ sở Dữ liệu này.
Kỹ sư full-stack & nhà sáng lập tại CheapGPT. Giảng dạy luôn là niềm đam mê của tôi. Từ những ngày còn là sinh viên, tôi đã háo hức tìm kiếm cơ hội kèm cặp và hỗ trợ các bạn học khác. Niềm đam mê đó đã thôi thúc tôi theo học tiến sĩ, nơi tôi cũng đảm nhiệm vai trò trợ giảng để hỗ trợ con đường học thuật của mình. Trong những năm ấy, tôi tìm thấy sự mãn nguyện lớn lao trong môi trường lớp học truyền thống, xây dựng kết nối và thúc đẩy việc học tập. Tuy nhiên, với sự ra đời của các nền tảng học trực tuyến, tôi nhận ra tiềm năng thay đổi của giáo dục số. Thực tế, tôi đã trực tiếp tham gia phát triển một nền tảng như vậy tại trường đại học của chúng tôi. Tôi tận tâm kết hợp các nguyên tắc giảng dạy truyền thống với những phương pháp số đổi mới. Đam mê của tôi là tạo ra các khóa học không chỉ hấp dẫn và giàu thông tin mà còn dễ tiếp cận với người học trong thời đại số này.
Đi kèm với các truy vấn luyện tập thực hành ở mọi bước, khóa học này dạy bạn mọi điều cần biết để phân tích dữ liệu bằng chính mã SQL của bạn ngay hôm nay!
Hãy hình dung một cơ sở dữ liệu bệnh viện nơi thông tin dị ứng của bệnh nhân không được để trống, hoặc một hệ thống tài chính nơi số tiền giao dịch phải là số dương. Trong những tình huống này và vô số tình huống khác, chúng ta dựa vào các ràng buộc toàn vẹn để đảm bảo dữ liệu luôn chính xác, nhất quán và đáng tin cậy.
Trong SQL, ràng buộc toàn vẹn là các quy tắc chúng ta áp dụng lên các bảng cơ sở dữ liệu để duy trì chất lượng dữ liệu. Chúng giúp ngăn lỗi, thực thi các quy tắc nghiệp vụ và đảm bảo dữ liệu phản ánh đúng các thực thể và mối quan hệ ngoài đời thực mà nó biểu diễn.
Trong bài viết này, chúng ta sẽ đi sâu vào các loại ràng buộc toàn vẹn thiết yếu trong SQL, kèm giải thích rõ ràng và ví dụ thực tiễn minh họa cách dùng trong cơ sở dữ liệu PostgreSQL. Dù sử dụng cú pháp PostgreSQL, các khái niệm này có thể áp dụng dễ dàng cho các biến thể SQL khác.
Nếu bạn muốn học thêm về SQL, hãy xem danh sách các khóa học SQL này.
Ràng Buộc Toàn Vẹn trong SQL là gì?
Hãy xét một tình huống có bảng lưu thông tin người dùng cho một ứng dụng web. Một số dữ liệu như tuổi người dùng có thể là tùy chọn vì không ảnh hưởng đến việc truy cập ứng dụng. Tuy nhiên, mật khẩu cho mỗi người dùng là bắt buộc để đăng nhập. Để xử lý điều này, chúng ta sẽ áp dụng một ràng buộc toàn vẹn lên cột mật khẩu trong bảng người dùng để đảm bảo mọi bản ghi trong bảng đều có mật khẩu.
Về bản chất, ràng buộc toàn vẹn rất quan trọng để:
Trong bài này, chúng ta sẽ khám phá các ràng buộc toàn vẹn thiết yếu sau trong SQL:
PRIMARY KEY: Nhận diện duy nhất mỗi bản ghi trong một bảng.NOT NULL: Đảm bảo một cột không thể chứa giá trị NULL.UNIQUE: Đảm bảo tất cả giá trị trong một cột hoặc nhóm cột là duy nhất.DEFAULT: Cung cấp giá trị mặc định cho một cột khi không được chỉ định.CHECK: Đảm bảo mọi giá trị trong một cột thỏa mãn một điều kiện cụ thể.FOREIGN KEY: Thiết lập quan hệ giữa các bảng bằng cách tham chiếu đến khóa chính ở bảng khác.Bài Toán Nghiên Cứu: Cơ Sở Dữ Liệu Trường Đại Học
Hãy xét một cơ sở dữ liệu quan hệ cho một trường đại học. Cơ sở dữ liệu này có ba bảng:
students,coursesvàenrollments.Bảng Students
Bảng
studentslưu thông tin về tất cả sinh viên của trường.student_id: Định danh của sinh viênfirst_name: Tên của sinh viên.last_name: Họ của sinh viên.email: Địa chỉ email của sinh viên.major: Chuyên ngành của sinh viên.enrollment_year: Năm sinh viên nhập học.Bảng Courses
Bảng
courseslưu thông tin về các học phần có tại trường.course_id: Định danh học phần.course_name: Tên học phần.department: Khoa/phòng ban phụ trách học phần.Bảng Enrollments
Bảng
enrollmentslưu thông tin về sinh viên nào đăng ký học phần nào.student_id: Định danh của sinh viên đăng ký học phần.course_id: Định danh của học phần.year: Năm đăng ký.grade: Điểm của sinh viên ở học phần này.is_passing_grade: Boolean cho biết điểm có đạt yêu cầu hay không.Xuyên suốt bài viết, chúng ta sẽ dùng cơ sở dữ liệu ví dụ này và trình bày nhiều cách để đảm bảo toàn vẹn dữ liệu. Chúng ta sử dụng cú pháp PostgreSQL trong truy vấn, tuy nhiên các khái niệm rất dễ chuyển sang những biến thể SQL khác.
Ràng Buộc PRIMARY KEY
Trường đại học muốn nhận diện duy nhất từng sinh viên. Sử dụng tên và họ cho mục đích này không phù hợp do có thể trùng tên giữa các sinh viên. Tương tự, dựa vào địa chỉ email cũng không lý tưởng vì sinh viên có thể thay đổi email.
Giải pháp phổ biến để đảm bảo nhận diện duy nhất là gán cho mỗi sinh viên một mã định danh duy nhất, lưu trong cột
student_id. Chúng ta có thể áp dụng ràng buộcPRIMARY KEYlên cộtstudent_idđể bảo đảm mỗi sinh viên có một định danh duy nhất.Ràng buộc này được định nghĩa trong lệnh
CREATE TABLE, ngay sau phần khai báo kiểu dữ liệu của cột:Truy vấn trên tạo bảng sinh viên với sáu cột như đã nêu.
Ràng buộc
PRIMARY KEYđảm bảo rằng:student_id.student_idlà duy nhất.Ràng buộc PRIMARY KEY trên nhiều cột
Trong một số tình huống, chúng ta cần sử dụng nhiều cột để nhận diện duy nhất mỗi hàng. Chẳng hạn bảng
enrollments. Một sinh viên có thể đăng ký nhiều học phần, dẫn đến nhiều hàng có cùngstudent_id. Tương tự, một học phần có thể có nhiều sinh viên, dẫn đến nhiều hàng có cùngcourse_id.Vì không có trường đơn lẻ nào nhận diện duy nhất một hàng, mỗi bản ghi đăng ký được xác định bằng kết hợp
student_id,course_idvàyear.Khi có nhiều cột, ràng buộc
PRIMARY KEYđược chỉ định ở cuối lệnhCREATE TABLE.Ràng buộc toàn vẹn sau khi tạo bảng
Có hai cách để thêm ràng buộc toàn vẹn. Chúng ta vừa học cách làm khi tạo bảng.
Giả sử bảng đã tồn tại nhưng bạn quên chỉ định ràng buộc
PRIMARY KEY. Bạn cũng có thể định nghĩa sau khi tạo bảng bằng lệnhALTER TABLEnhư sau:Trong truy vấn
ALTER TABLE, chúng ta đặt tên ràng buộc làenroll_pk(viết tắt của primary key của bảng enrollments). Tên này có thể là bất kỳ định danh nào bạn chọn, nhưng nên chọn tên truyền tải ngắn gọn mục đích của ràng buộc.Việc đặt tên cho ràng buộc toàn vẹn là thực hành tốt vì mang lại vài lợi ích:
Ràng Buộc NOT NULL
Trường đại học muốn đảm bảo tên và email của mọi sinh viên đều được ghi nhận trong cơ sở dữ liệu. Họ không muốn nhân viên vô tình quên nhập bất kỳ trường nào trong số đó.
Để xử lý, chúng ta có thể dùng các ràng buộc
NOT NULLtrên ba cột này khi tạo bảng:Truy vấn trên sử dụng ràng buộc
NOT NULLđể đảm bảo các cộtfirst_name,last_namevàemailkhông thể có giá trịNULL(không xác định).Thêm ràng buộc
NOT NULLvào một bảng hiện có có thể thực hiện bằng lệnhALTER TABLE. Cú pháp để thêm ràng buộcNOT NULLnhư sau:Ràng Buộc UNIQUE
Địa chỉ email vốn dĩ là duy nhất với mỗi cá nhân. Trong những tình huống chúng ta chắc chắn một trường không bao giờ được lặp giá trị, việc thực thi điều này ở cấp cơ sở dữ liệu là thực hành tốt. Điều này giúp ngăn sai sót và đảm bảo toàn vẹn dữ liệu.
Việc thêm ràng buộc này thực hiện tương tự như các ràng buộc khác.
Tuy nhiên, trong trường hợp của chúng ta, ta cũng muốn áp dụng ràng buộc
NOT NULL. Ta có thể áp dụng nhiều ràng buộc trên một cột bằng cách đặt cách nhau bằng khoảng trắng:Lưu ý thứ tự không quan trọng, ta cũng có thể dùng
NOT NULL UNIQUE.Thêm ràng buộc
UNIQUEvào một bảng hiện có được thực hiện như sau:Ràng buộc UNIQUE trên nhiều cột
Giả sử chúng ta muốn đảm bảo tên học phần của mỗi khoa là duy nhất trong bảng
courses. Khi đó, hai cộtcourse_namevàdepartmentkết hợp với nhau phải là duy nhất.Khi có nhiều cột, ràng buộc được thêm ở cuối lệnh
CREATE TABLE:Ngoài ra, chúng ta có thể thêm ràng buộc bằng cách sửa bảng hiện có. Khi đó, ta cung cấp một bộ gồm tên các cột:
So sánh NOT NULL UNIQUE và PRIMARY KEY
Chúng ta đã biết ràng buộc
PRIMARY KEYvừa đảm bảo tính duy nhất vừa không có giá trị thiếu. Vậy khác biệt giữa:Sự khác nhau giữa
NOT NULL UNIQUEvàPRIMARY KEYtrên một bảng nằm ở mục đích và cách sử dụng.Dù cả hai đều thực thi tính duy nhất và không rỗng trên cột (hoặc các cột), một bảng chỉ có duy nhất một
PRIMARY KEY, dùng để nhận diện duy nhất mỗi bản ghi trong bảng.Mặt khác, tổ hợp ràng buộc
NOT NULL UNIQUEcó thể áp dụng cho các cột bổ sung để đảm bảo giá trị duy nhất trên mỗi hàng và không có giá trị rỗng, phục vụ việc duy trì toàn vẹn dữ liệu theo các quy tắc nghiệp vụ cụ thể. Một bảng có thể có bất kỳ số lượng ràng buộcNOT NULL UNIQUEnào.Sự tồn tại của cả hai loại mang lại tính linh hoạt cao hơn trong thiết kế cơ sở dữ liệu, cho phép nhiều cách để thực thi tính duy nhất và toàn vẹn dữ liệu, đồng thời phân biệt giữa định danh chính của bản ghi và các thuộc tính quan trọng, duy nhất khác trong bảng.
Ràng Buộc DEFAULT
Sinh viên có thể cần một thời gian sau khi đăng ký nhập học để chọn chuyên ngành. Trường muốn giá trị của cột chuyên ngành là chuỗi ’Undeclared’ cho các sinh viên chưa chọn chuyên ngành.
Để làm vậy, chúng ta có thể đặt giá trị mặc định cho cột này bằng ràng buộc
DEFAULT. Ta có thể sửa bảng students như sau:Nếu muốn đặt ràng buộc
DEFAULTngay khi tạo bảng, ta có thể khai báo sau kiểu dữ liệu của cột:Ràng Buộc CHECK
Tại trường đại học này, thang điểm từ 0 đến 100. Nếu không có ràng buộc nào, cột
gradecủa bảngenrollmentsẽ chấp nhận mọi số nguyên. Chúng ta có thể khắc phục bằng ràng buộcCHECKđể buộc giá trị nằm trong khoảng 0 đến 100.Nói chung, ràng buộc
CHECKcho phép chúng ta xác thực các điều kiện cụ thể mà dữ liệu cần thỏa. Đây là những ràng buộc quan trọng để đảm bảo tính nhất quán và toàn vẹn dữ liệu.Một ràng buộc
CHECKcó thể liên quan đến nhiều hơn một cột. Hãy dùng nó để đảm bảogradevàis_passing_gradecó giá trị nhất quán. Giả sử một điểm được coi là đạt nếu có giá trị ít nhất 60. Khi đó, chúng ta có thể đảm bảois_passing_gradelàTRUEkhi và chỉ khi điểm từ 60 trở lên. Hãy thực hiện ngay trong lúc tạo bảng để minh họa cách khai báo ràng buộcCHECKtrong lệnhCREATE TABLE:Có một vấn đề với ràng buộc trên. Khi sinh viên đăng ký một học phần, họ chưa có điểm. Vì vậy, chúng ta nên cho phép giá trị
NULLở cột điểm. Khi làm vậy, ta cũng cần cập nhật ràng buộc điểm đạt để làNULLkhi điểm chưa được xác định. Dưới đây là cách cập nhật ràng buộc để tính đến các trường hợp này:Lưu ý rằng ở cả hai cột
gradevàis_passing_gradechúng ta thêmNULLvào kiểu dữ liệu và làm giá trị mặc định. Mục đích chỉ để tăng tính dễ đọc.Giờ hãy xem các điều kiện nào có thể áp dụng bằng ràng buộc
CHECK.Điều kiện khoảng
Chúng ta có thể đảm bảo các giá trị trong một cột nằm trong một khoảng cụ thể.
Điều kiện danh sách
Chúng ta có thể xác thực rằng giá trị của một cột khớp với một trong các giá trị trong danh sách chỉ định.
Điều kiện so sánh
Chúng ta có thể so sánh các giá trị trong một cột để đảm bảo chúng thỏa điều kiện nhất định (lớn hơn, nhỏ hơn, v.v.).
Điều kiện khớp mẫu
Chúng ta có thể dùng khớp mẫu (ví dụ với
LIKEhoặcSIMILAR TO) để xác thực dữ liệu văn bản.Điều kiện logic
Chúng ta có thể cho phép nhiều điều kiện bằng các toán tử logic (
AND,OR,NOT).Điều kiện tổng hợp
Áp dụng một điều kiện trên nhiều cột.
Ràng Buộc FOREIGN KEY
Ràng buộc khóa ngoại được dùng để liên kết các cột của hai bảng với nhau, đảm bảo tính toàn vẹn tham chiếu của dữ liệu. Về bản chất, một khóa ngoại trong bảng này trỏ đến một khóa chính ở bảng khác, cho biết các hàng ở hai bảng này có liên quan. Điều này đảm bảo bạn không thể có một hàng trong bảng với khóa ngoại mà không khớp với bất kỳ hàng nào ở bảng được liên kết có khóa chính.
Trong ví dụ của chúng ta, mỗi bản ghi trong bảng enrollments tham chiếu đến một sinh viên và một học phần thông qua các cột
student_idvàcourse_idtương ứng. Nếu không có ràng buộc nào, sẽ không có gì đảm bảo rằng các giá trị định danh này trong bảng enrollments khớp với các bản ghi hiện có trong bảng students và courses.Đây là cách chúng ta đảm bảo điều đó khi tạo bảng
enrollments:Lưu ý để chúng là khóa ngoại, chúng phải là khóa chính trong các bảng
studentsvàcoursestương ứng.Tương tự các ràng buộc khác, chúng ta cũng có thể khai báo sau khi tạo bảng bằng lệnh
ALTER TABLE:Tổng Hợp
Xuyên suốt bài viết, chúng ta đã trình bày nhiều ràng buộc toàn vẹn và cách dùng để cải thiện cơ sở dữ liệu của một trường đại học. Dưới đây là phiên bản cuối cùng của lệnh
CREATE TABLE, kết hợp mọi thứ chúng ta đã học.Trước hết, chúng ta sẽ định nghĩa bảng
students:Tiếp theo, hãy định nghĩa bảng
courses:Cuối cùng, chúng ta sẽ định nghĩa bảng
enrollments, thiết lập các mối quan hệ giữa sinh viên và học phần:Chúng ta đã thêm một vài ràng buộc trong ví dụ cuối cùng này. Một trường đại học có tập hợp khoa và chuyên ngành đã biết trước. Do đó, tập giá trị mà các cột
majorvàdepartmentcó thể nhận là hữu hạn và biết trước. Trong những tình huống như vậy, nên dùng ràng buộcCHECKđể đảm bảo các cột chỉ nhận giá trị từ tập đã biết đó.Kết Luận
Trong bài viết này, chúng ta đã khám phá các loại ràng buộc toàn vẹn khác nhau trong SQL và cách triển khai chúng bằng PostgreSQL. Chúng ta đã đề cập đến khóa chính, ràng buộc
NOT NULL, ràng buộcUNIQUE, ràng buộcDEFAULT, ràng buộcCHECKvà ràng buộcFOREIGN KEY, kèm ví dụ thực tiễn cho từng loại.Bằng cách hiểu các khái niệm này, chúng ta có thể đảm bảo tính chính xác, nhất quán và độ tin cậy của dữ liệu.
Nếu bạn muốn học thêm về cách tổ chức dữ liệu hiệu quả, hãy xem khóa học về Thiết kế Cơ sở Dữ liệu này.