Về cơ bản, không có gì sai với NULL trong khóa chính nhiều cột. Nhưng có một ý nghĩa mà nhà thiết kế có thể không có ý định, đó là lý do tại sao nhiều hệ thống gặp lỗi khi bạn thử điều này.
Hãy xem xét trường hợp của các phiên bản mô-đun / gói được lưu trữ dưới dạng một loạt các trường:
CREATE TABLE module
(name varchar(20) PRIMARY KEY,
description text DEFAULT '' NOT NULL);
CREATE TABLE version
(module varchar(20) REFERENCES module,
major integer NOT NULL,
minor integer DEFAULT 0 NOT NULL,
patch integer DEFAULT 0 NOT NULL,
release integer DEFAULT 1 NOT NULL,
ext varchar(20),
notes text DEFAULT '' NOT NULL,
PRIMARY KEY (module, major, minor, patch, release, ext));
5 phần tử đầu tiên của khóa chính là các phần được xác định thường xuyên của phiên bản phát hành, nhưng một số gói có phần mở rộng tùy chỉnh thường không phải là số nguyên (như "rc-foo" hoặc "vanilla" hoặc "beta" hoặc bất cứ ai khác cho người mà bốn lĩnh vực là không đủ có thể mơ ước). Nếu một gói không có phần mở rộng, thì đó là NULL trong mô hình trên và sẽ không có hại gì khi để mọi thứ theo cách đó.
Nhưng những gì là một NULL? Nó được cho là đại diện cho việc thiếu thông tin, một ẩn số. Điều đó nói rằng, có lẽ điều này có ý nghĩa hơn:
CREATE TABLE version
(module varchar(20) REFERENCES module,
major integer NOT NULL,
minor integer DEFAULT 0 NOT NULL,
patch integer DEFAULT 0 NOT NULL,
release integer DEFAULT 1 NOT NULL,
ext varchar(20) DEFAULT '' NOT NULL,
notes text DEFAULT '' NOT NULL,
PRIMARY KEY (module, major, minor, patch, release, ext));
Trong phiên bản này, phần "mở rộng" của bộ dữ liệu KHÔNG phải là NULL mà mặc định là một chuỗi trống - có nghĩa là về mặt ngữ nghĩa (và thực tế) khác với NULL. Một NULL là một ẩn số, trong khi một chuỗi trống là một bản ghi có chủ ý của "một cái gì đó không có mặt". Nói cách khác, "trống rỗng" và "null" là những thứ khác nhau. Đó là sự khác biệt giữa "Tôi không có giá trị ở đây" và "Tôi không biết giá trị ở đây là gì".
Khi bạn đăng ký gói thiếu phần mở rộng phiên bản, bạn biết rằng nó thiếu phần mở rộng, vì vậy một chuỗi trống thực sự là giá trị chính xác. Một NULL sẽ chỉ đúng nếu bạn không biết liệu nó có phần mở rộng hay không, hoặc bạn biết rằng nó đã làm nhưng không biết nó là gì. Tình huống này dễ xử lý hơn trong các hệ thống trong đó các giá trị chuỗi là chuẩn, bởi vì không có cách nào để biểu diễn một "số nguyên trống" ngoài việc chèn 0 hoặc 1, sẽ cuộn lên trong bất kỳ phép so sánh nào được thực hiện sau này (có ý nghĩa riêng của nó) *.
Ngẫu nhiên, cả hai cách đều hợp lệ trong Postgres (vì chúng ta đang thảo luận về RDMBS "doanh nghiệp"), nhưng kết quả so sánh có thể thay đổi khá nhiều khi bạn ném NULL vào hỗn hợp - vì NULL == "không biết" nên tất cả kết quả so sánh liên quan đến NULL sẽ trở thành NULL vì bạn không thể biết điều gì đó chưa biết. NGUY HIỂM! Hãy suy nghĩ cẩn thận về điều đó: điều này có nghĩa là kết quả so sánh NULL lan truyền thông qua một loạt các so sánh. Đây có thể là một nguồn lỗi tinh tế khi sắp xếp, so sánh, v.v.
Postgres cho rằng bạn là người lớn và có thể tự đưa ra quyết định này. Oracle và DB2 cho rằng bạn đã không nhận ra mình đang làm điều gì đó ngớ ngẩn và gây ra lỗi. Đây thường là điều đúng, nhưng không phải lúc nào cũng vậy - bạn thực sự có thể không biết và có NULL trong một số trường hợp và do đó để lại một hàng với một yếu tố không xác định mà không thể so sánh có ý nghĩa là hành vi đúng.
Trong mọi trường hợp, bạn nên cố gắng loại bỏ số lượng trường NULL mà bạn cho phép trên toàn bộ lược đồ và gấp đôi khi nói đến các trường là một phần của khóa chính. Trong phần lớn các trường hợp, sự hiện diện của các cột NULL là một dấu hiệu của thiết kế lược đồ không được chuẩn hóa (trái ngược với cố tình không chuẩn hóa) và nên được suy nghĩ rất kỹ trước khi được chấp nhận.
[* LƯU Ý: Có thể tạo một loại tùy chỉnh là liên kết các số nguyên và loại "dưới cùng" về mặt ngữ nghĩa có nghĩa là "trống rỗng" thay vì "không xác định". Thật không may, điều này giới thiệu một chút phức tạp trong các hoạt động so sánh và thường thực sự đúng loại không đáng để nỗ lực trong thực tế vì bạn không nên cho phép nhiều NULL
giá trị ở vị trí đầu tiên. Điều đó nói rằng, thật tuyệt vời nếu các RDBMS sẽ bao gồm một BOTTOM
loại mặc định bên cạnh NULL
việc ngăn chặn thói quen kết hợp các ngữ nghĩa của "không có giá trị" với "giá trị không xác định". ]