Tại sao NULL = NULL đánh giá thành sai trong máy chủ SQL


146

Trong máy chủ SQL nếu bạn có nullParam=NULLmệnh đề where, nó luôn ước lượng thành false. Điều này là phản trực giác và đã gây ra cho tôi nhiều lỗi. Tôi hiểu IS NULLIS NOT NULLtừ khóa là cách chính xác để làm điều đó. Nhưng tại sao máy chủ SQL lại hoạt động theo cách này?


166
Tôi không có em gái và bạn tôi cũng vậy. Nếu "NULL = NULL" thì chúng ta có một người chị em chung và do đó có liên quan! :)
Matt Hamilton

11
Có một cuộc tranh cãi kéo dài về SQL NULL (xem ví dụ: en.wikipedia.org/wiki/Null_%28Query%29#ContputyFirstsql.com/inulls.htmlm ). Điểm cụ thể ở đây là sự bình đẳng là một khái niệm toán học đã được thiết lập từ lâu và SQL vi phạm nó - sự bình đẳng là phản xạ: với mỗi x, x = x. Điều đó phải luôn luôn đúng, nếu không, người ta sẽ đưa ra một cách giải thích về sự bình đẳng không chuẩn và sự nhầm lẫn là kết quả rõ ràng.
MaD70

14
Nó không vi phạm toán học chút nào. Tôi đang nghĩ về hai con số. Tôi sẽ không nói cho bạn biết họ là gì mặc dù. Vì vậy, bây giờ bạn nói với tôi, họ có bằng nhau không?
Tom H

10
@Matt, tôi không đồng ý với sự tương tự của bạn. NULL = NULL không có nghĩa là bạn có một người chị em chung, điều đó có nghĩa là cả hai bạn đều thiếu em gái.
thiệu lại

5
@ manu08 Không, cách triển khai hiện tại (rằng NULL không bao giờ bằng NULL) có nghĩa là cả hai chúng tôi đều thiếu em gái, đó là quan điểm của tôi.
Matt Hamilton

Câu trả lời:


205

Hãy nghĩ về null là "không xác định" trong trường hợp đó (hoặc "không tồn tại"). Trong một trong những trường hợp đó, bạn không thể nói rằng chúng bằng nhau, vì bạn không biết giá trị của một trong hai trường hợp đó. Vì vậy, null = null đánh giá là không đúng (sai hoặc null, tùy thuộc vào hệ thống của bạn), vì bạn không biết các giá trị để nói rằng chúng bằng nhau. Hành vi này được định nghĩa trong tiêu chuẩn ANSI SQL-92.

EDIT: Điều này phụ thuộc vào cài đặt ansi_nulls của bạn . nếu bạn tắt ANSI_NULLS, điều này SILL đánh giá là đúng. Chạy mã sau đây cho một ví dụ ...

set ansi_nulls off

if null = null
    print 'true'
else
    print 'false'


set ansi_nulls ON

if null = null
    print 'true'
else
    print 'false'

11
x = x chỉ đúng khi x là giá trị đã biết . NULL là một đại diện văn bản của một giá trị không xác định . Nếu bạn có hai giá trị không xác định, bạn không thể kết luận bất cứ điều gì về sự bình đẳng của chúng. Tôi tin rằng điều đó cũng đã đúng trong một vài thế kỷ.
Dewayne Christensen

4
Kể từ tháng 12, hãy sử dụng một ví dụ theo mùa. Tôi có hai món quà dưới gốc cây. Bây giờ, bạn nói với tôi nếu tôi có hai điều tương tự hay không.
Dewayne Christensen

5
SQL NULL không có gì khác biệt so với NaN điểm trôi nổi của IEEE, nơi bạn cũng có (NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...- bởi vì, nếu không phải là một con số, bạn không thể nói nhiều về nó; đó là một cái gì đó chưa biết. Khái niệm này là âm thanh, ngay cả khi không trực quan cho những người chưa bao giờ nhìn thấy nó trước đây.
Pavel Minaev

8
Không có vi phạm tính phản xạ ở đây, vì NULL không phải là thành viên của tập hợp các giá trị (miền, theo thuật ngữ quan hệ). NULL không phải là một giá trị . Đó là một giữ chỗ cho giá trị không xác định.
Pavel Minaev

9
Nói cách khác, mọi NULLbiểu thức SQL có thể được coi là một biến toán học riêng biệt . Vì vậy, một biểu thức NULL = NULLnên được coi là x = y, ở đâu xylà các biến không liên kết. Bây giờ nếu ai đó hỏi bạn, giá trị của là x = ygì? Câu trả lời hợp lý duy nhất là "một số z". Vì vậy, chúng tôi có (x = y) = z- hoặc, phiên mã nó trở lại SQL , (NULL = NULL) = NULL.
Pavel Minaev

130

Frank bao nhiêu tuổi? Tôi không biết (null).

Shirley bao nhiêu tuổi? Tôi không biết (null).

Frank và Shirley bằng tuổi nhau phải không?

Câu trả lời đúng phải là "Tôi không biết" (không), không phải "không", vì Frank và Shirley thể bằng tuổi nhau, đơn giản là chúng ta không biết.


4
Tôi không đồng ý rằng null biểu thị "không xác định". Điều thực sự có nghĩa là "không có dữ liệu". Điều đó có thể được sử dụng để đại diện cho trường hợp không biết thông tin, nhưng thực tế nhiều khả năng nó sẽ được sử dụng để chỉ ra rằng một cái gì đó không tồn tại. Để tiếp tục ví dụ của bạn: Tên đệm của Frank là gì? Anh ta không có một (null). Tên đệm của Shirley là gì? Cô ấy không có một (null). Do Frank và Shirley có cùng tên đệm? Đúng? Không? Không biết à? Tôi có thể thấy một đối số cho "không" và tôi có thể thấy một đối số cho "không biết", nhưng không có đối số thực sự cho "có" trừ khi bạn quá hiểu chữ.
Richiban

2
@richiban Tôi không đồng ý. Việc thiếu sự tồn tại của một hàng có nghĩa là 'không có dữ liệu'
Neil McGuigan

1
@NeilMcGuigan Điều đó đúng nếu đối với dữ liệu có bảng riêng, nhưng dữ liệu được biểu thị trong một cột thì sao? Bạn sẽ không sử dụng 'null' để thể hiện thực tế là dữ liệu không tồn tại chứ? 'Không biết' là một lý do rất cụ thể cho việc dữ liệu bị vắng mặt.
Richiban

3
Nhưng null = nullsản lượng FALSE, không NULL.
slartidan

1
@slartidan Tôi đồng ý với bạn, tuy nhiên điều đó không chính xác
Neil McGuigan

28

Ở đây tôi hy vọng sẽ làm rõ vị trí của tôi.

Điều đó NULL = NULLđánh giá FALSElà sai. Hacker và Mister trả lời đúng NULL. Đây là lý do tại sao. Dewayne Christensen đã viết cho tôi, trong một bình luận cho Scott Ivey :

Kể từ tháng 12, hãy sử dụng một ví dụ theo mùa. Tôi có hai món quà dưới gốc cây. Bây giờ, bạn nói với tôi nếu tôi có hai điều tương tự hay không.

Chúng có thể khác nhau hoặc chúng có thể bằng nhau, bạn không biết cho đến khi mở cả hai món quà. Ai biết? Bạn đã mời hai người không biết nhau và cả hai đã làm cho bạn cùng một món quà - hiếm, nhưng không phải là không thể § .

Vì vậy, câu hỏi: hai UNKNOWN này có giống nhau (bằng, =) không? Câu trả lời đúng là: UNKNOWN (tức là NULL).

Ví dụ này nhằm chứng minh rằng ".. ( falsehoặc null, tùy thuộc vào hệ thống của bạn) .." là một câu trả lời đúng - không phải, chỉ NULL đúng trong 3VL (hoặc bạn có thể chấp nhận một hệ thống đưa ra câu trả lời sai không? )

Một câu trả lời đúng cho câu hỏi này phải nhấn mạnh hai điểm này:

  • logic ba giá trị (3VL) là phản trực giác (xem vô số câu hỏi khác về chủ đề này trên Stackoverflow và trong diễn đàn khác để đảm bảo);
  • Các DBMS dựa trên SQL thường không tôn trọng ngay cả 3VL, đôi khi chúng đưa ra các câu trả lời sai (như, áp phích ban đầu khẳng định, SQL Server làm trong trường hợp này).

Vì vậy, tôi nhắc lại: SQL không tốt khi buộc người ta phải giải thích thuộc tính phản xạ của đẳng thức, trong đó nêu rõ:

for any x, x = x § § (bằng tiếng Anh đơn giản: bất kể vũ trụ diễn ngôn là gì, một "thứ" luôn luôn bằng chính nó ).

.. trong 3 VL ( TRUE, FALSE, NULL). Kỳ vọng của mọi người sẽ tuân thủ 2VL ( TRUE, FALSEmà ngay cả trong SQL là hợp lệ cho tất cả các giá trị khác), tức là x = x luôn luôn đánh giá TRUE , đối với mọi giá trị có thể có của x - không có ngoại lệ.

Cũng lưu ý rằng các NULL là " phi giá trị " hợp lệ (vì người xin lỗi của họ giả vờ là họ) mà người ta có thể gán làm giá trị thuộc tính (??) như một phần của các biến quan hệ. Vì vậy, chúng là các giá trị được chấp nhận của mọi loại (miền), không chỉ của loại biểu thức logic.

điều này là quan điểm của tôi : NULLkhi giá trị, là một "con thú lạ". Không có uyển ngữ, tôi thích nói: vô nghĩa .

Tôi nghĩ rằng công thức này rõ ràng hơn và ít tranh cãi hơn - xin lỗi vì trình độ tiếng Anh kém của tôi.

Đây chỉ là một trong những vấn đề của NULL. Tốt hơn để tránh chúng hoàn toàn, khi có thể.

§ chúng tôi quan tâm đến các giá trị ở đây, vì vậy thực tế là hai món quà luôn là hai đối tượng vật lý khác nhau không phải là một sự phản đối hợp lệ; nếu bạn không tin tôi xin lỗi, đây không phải là nơi để giải thích sự khác biệt giữa ngữ nghĩa giá trị và "đối tượng" (Đại số quan hệ có ngữ nghĩa giá trị ngay từ đầu - xem nguyên tắc thông tin của Codd; Tôi nghĩ rằng một số người triển khai SQL DBMS không thậm chí không quan tâm đến một ngữ nghĩa chung).

Theo hiểu biết của tôi, đây là một tiên đề được chấp nhận (dưới hình thức này hay hình thức khác, nhưng luôn được giải thích trong 2VL) kể từ thời cổ đại và điều đó chính xác bởi vì nó rất trực quan. 3VL (là một họ logic trong thực tế) là một sự phát triển gần đây hơn nhiều (nhưng tôi không chắc chắn khi nào được phát triển lần đầu tiên).

Lưu ý bên lề: nếu ai đó sẽ giới thiệu Loại dưới cùng , Đơn vịTùy chọn là cố gắng biện minh cho các NULL SQL, tôi sẽ chỉ bị thuyết phục sau khi kiểm tra khá chi tiết sẽ cho thấy cách triển khai SQL với NULL có hệ thống loại âm thanh và cuối cùng sẽ làm rõ, những gì NULL (những "giá trị không hoàn toàn" này thực sự là).


Trong những gì tiếp theo tôi sẽ trích dẫn một số tác giả. Bất kỳ lỗi hoặc thiếu sót có lẽ là của tôi và không phải của các tác giả ban đầu.

Joe Celko trên SQL NULL

Tôi thấy Joe Celko thường được trích dẫn trên diễn đàn này. Rõ ràng ông là một tác giả rất được kính trọng ở đây. Vì vậy, tôi tự nhủ: "anh ấy đã viết gì về SQL NULL? Làm thế nào để anh ấy giải thích vô số vấn đề của NULL?". Một người bạn của tôi có phiên bản ebook về SQL của Joe Celko dành cho người thông minh: lập trình SQL nâng cao, phiên bản thứ 3 . Hãy xem nào.

Đầu tiên, mục lục. Điều làm tôi ấn tượng nhất là số lần NULL được đề cập và trong các bối cảnh đa dạng nhất:

3.4 Arithmetic and NULLs 109
3.5 Chuyển đổi giá trị đến và đi từ NULL 110
3.5.1 NULLIF () Chức năng 110
6 NULLs: Thiếu dữ liệu trong SQL 185
6.4 NULLs So sánh 190
6,5 NULLs và Logic 190
6.5.1 NULLS trong Subquery vị từ 191
6.5.2 Chuẩn Các giải pháp SQL 193
6.6 Toán học và NULL 193
6.7 Hàm và NULL 193
6.8 NULL và Ngôn ngữ máy chủ 194
6.9 Lời khuyên thiết kế cho NULL 195
6.9.1 Tránh NULL từ các chương trình máy chủ 197
6.10 Lưu ý về nhiều giá trị NULL 198
10.1 IS NULL Dự đoán 241
10.1. 1 nguồn của NULL 242
...

và như thế. Nó gọi "trường hợp đặc biệt khó chịu" với tôi.

Tôi sẽ đi vào một số trong những trường hợp này với các trích đoạn từ cuốn sách này, cố gắng giới hạn bản thân mình vì điều cần thiết, vì lý do bản quyền. Tôi nghĩ rằng những trích dẫn này nằm trong học thuyết "sử dụng hợp lý" và chúng thậm chí có thể kích thích để mua cuốn sách - vì vậy tôi hy vọng rằng sẽ không có ai phàn nàn (nếu không tôi sẽ cần phải xóa hầu hết, nếu không phải là tất cả). Hơn nữa, tôi sẽ không báo cáo đoạn mã vì lý do tương tự. Xin lỗi vì điều đó. Mua cuốn sách để đọc về lý luận dữ liệu.

Số trang giữa dấu ngoặc trong những gì sau.

KHÔNG NULL Ràng buộc (11)

Ràng buộc cột quan trọng nhất là KHÔNG NULL, cấm sử dụng NULL trong một cột. Sử dụng ràng buộc này thường xuyên và chỉ loại bỏ nó khi bạn có lý do chính đáng. Nó sẽ giúp bạn tránh các biến chứng của các giá trị NULL khi bạn thực hiện truy vấn đối với dữ liệu.

Nó không phải là một giá trị ; nó là một điểm đánh dấu giữ một nơi mà giá trị có thể đi.

Một lần nữa "giá trị nhưng không hoàn toàn là một giá trị" vô nghĩa. Phần còn lại có vẻ khá hợp lý với tôi.

(12)

Nói tóm lại, NULL gây ra rất nhiều tính năng bất thường trong SQL, mà chúng ta sẽ thảo luận sau. Đặt cược tốt nhất của bạn chỉ là ghi nhớ các tình huống và quy tắc cho NULL khi bạn không thể tránh chúng.

Cung cấp SQL, NULL và vô hạn:

(104) CHƯƠNG 3: SỐ LIỆU SỐ TRONG SQL

SQL đã không chấp nhận mô hình IEEE cho toán học vì nhiều lý do.

...

Nếu các quy tắc IEEE cho toán học được cho phép trong SQL, thì chúng ta sẽ cần các quy tắc chuyển đổi loại cho vô hạn và một cách để biểu thị một giá trị số chính xác vô hạn sau khi chuyển đổi. Mọi người có đủ rắc rối với NULL, vì vậy chúng ta đừng đến đó.

Việc triển khai SQL chưa quyết định về ý nghĩa thực sự của NULL trong các ngữ cảnh cụ thể:

3.6.2 Hàm số mũ (116)

Vấn đề là logarit không được xác định khi (x <= 0). Một số triển khai SQL trả về một thông báo lỗi, một số trả về NULL và DB2 / 400; Phiên bản 3 phát hành 1 đã trả về * NEGINF (viết tắt của âm bản vô cực âm tính).

Joe Celko trích dẫn David McGoveran và CJ Ngày:

6 NULL: Thiếu dữ liệu trong SQL (185)

Trong cuốn sách Hướng dẫn về Sybase và SQL Server của họ , David McGoveran và CJ Date đã nói: Đây là ý kiến ​​của người viết này so với NULL, ít nhất là như được định nghĩa và triển khai trong SQL, là rắc rối hơn nhiều so với giá trị và nên tránh; chúng thể hiện hành vi rất lạ và không nhất quán và có thể là một nguồn gây lỗi và nhầm lẫn phong phú. (Xin lưu ý rằng những nhận xét và phê bình này áp dụng cho bất kỳ hệ thống nào hỗ trợ NULL kiểu SQL, không chỉ riêng cho SQL Server.)

NULL như một người nghiện ma túy :

(186/187)

Trong phần còn lại của cuốn sách này, tôi sẽ thúc giục bạn không sử dụng chúng , điều này có vẻ mâu thuẫn, nhưng thực tế không phải vậy. Hãy nghĩ về một NULL như một loại thuốc; sử dụng đúng cách và nó hiệu quả với bạn, nhưng lạm dụng nó và nó có thể phá hỏng mọi thứ. Chính sách tốt nhất của bạn là tránh NULL khi bạn có thể và sử dụng chúng đúng cách khi bạn phải.

Phản đối duy nhất của tôi ở đây là "sử dụng chúng đúng cách", tương tác xấu với các hành vi thực hiện cụ thể.

6.5.1 NULLS trong Dự đoán truy vấn con (191/192)

Mọi người quên rằng một truy vấn con thường ẩn một so sánh với NULL. Hãy xem xét hai bảng này:

...

Kết quả sẽ trống rỗng. Điều này là phản trực giác , nhưng chính xác.

(dải phân cách)

6.5.2 Giải pháp SQL chuẩn (193)

SQL-92 đã giải quyết một số vấn đề 3VL (logic ba giá trị) bằng cách thêm một vị từ mới có dạng:

<điều kiện tìm kiếm> LÀ [KHÔNG] THẬT | SAU | KHÔNG XÁC ĐỊNH

Nhưng bản thân UNKNOWN là một nguồn gốc của các vấn đề, do đó, Ngày của CJ, trong cuốn sách của ông được trích dẫn dưới đây, đề xuất trong chương 4.5. Tránh Nulls trong SQL :

  • Đừng sử dụng từ khóa UNKNOWN trong bất kỳ bối cảnh nào.

Đọc "ASIDE" trên UNKNOWN, cũng được liên kết dưới đây.

6.8 NULL và ngôn ngữ máy chủ (194)

Tuy nhiên, bạn nên biết cách xử lý NULL khi chúng phải được chuyển đến chương trình máy chủ. Không có ngôn ngữ máy chủ chuẩn nào được nhúng được xác định hỗ trợ NULL, đó là một lý do chính đáng khác để tránh sử dụng chúng trong lược đồ cơ sở dữ liệu của bạn.

(dải phân cách)

6,9 Lời khuyên thiết kế cho NULL (195)

Đó là một ý tưởng tốt để khai báo tất cả các bảng cơ sở của bạn với các ràng buộc KHÔNG NULL trên tất cả các cột bất cứ khi nào có thể. Các NULL gây nhầm lẫn cho những người không biết SQL và các NULL đắt tiền.

Phản đối: Các NULL nhầm lẫn ngay cả những người biết rõ về SQL, xem bên dưới.

(195)

Nên tránh các NULL trong các khóa NGOẠI TỆ. SQL cho phép lợi ích này của mối quan hệ nghi ngờ, nhưng nó có thể gây mất thông tin trong các truy vấn có liên quan. Ví dụ: được cung cấp mã số bộ phận trong Khoảng không quảng cáo được tham chiếu dưới dạng PHÍM NGOẠI bởi bảng Đơn hàng, bạn sẽ gặp vấn đề khi nhận danh sách các bộ phận có NULL. Đây là một mối quan hệ bắt buộc; bạn không thể đặt một phần không tồn tại.

(dải phân cách)

6.9.1 Tránh các NULL từ các chương trình máy chủ (197)

Bạn có thể tránh đưa NULL vào cơ sở dữ liệu từ Chương trình máy chủ với một số nguyên tắc lập trình.

...

  1. Xác định tác động của dữ liệu bị thiếu đối với lập trình và báo cáo: Các cột số có NULL là một vấn đề, bởi vì các truy vấn sử dụng hàm tổng hợp có thể cung cấp kết quả sai lệch.

(dải phân cách)

(227)

SUM () của một tập hợp trống luôn là NULL. Một trong những lỗi lập trình phổ biến nhất được thực hiện khi sử dụng thủ thuật này là viết một truy vấn có thể trả về nhiều hơn một hàng. Nếu bạn không nghĩ về nó, bạn có thể đã viết ví dụ cuối cùng là: ...

(dải phân cách)

10.1.1 Nguồn của NULL (242)

Điều quan trọng là phải nhớ nơi NULL có thể xảy ra. Chúng không chỉ là một giá trị có thể có trong một cột . Các hàm tổng hợp trên các tập hợp trống, OUTER THAM GIA, biểu thức số học với NULL và toán tử OLAP đều trả về NULL. Các cấu trúc này thường hiển thị dưới dạng các cột trong XEM.

(dải phân cách)

(301)

Một vấn đề khác với NULL được tìm thấy khi bạn cố gắng chuyển đổi các vị từ IN thành các vị từ EXISTS.

(dải phân cách)

16.3 TẤT CẢ Chức năng Vị ngữ và Vị trí (313)

Điều đầu tiên là phản trực giác khi hai vị từ này không giống nhau trong SQL:

...

Nhưng bạn phải nhớ các quy tắc cho các hàm extrema, họ bỏ tất cả các NULL trước khi trả về các giá trị lớn hơn hoặc nhỏ nhất. Vị từ TẤT CẢ không bỏ NULL, vì vậy bạn có thể nhận được chúng trong kết quả.

(dải phân cách)

(315)

Tuy nhiên, định nghĩa trong tiêu chuẩn được diễn đạt theo cách phủ định, để NULL nhận được lợi ích của sự nghi ngờ. ...

Như bạn có thể thấy, đó là một ý tưởng tốt để tránh các NULL trong các ràng buộc KHÔNG GIỚI HẠN.

Thảo luận nhóm THEO:

Các NULL được đối xử như thể tất cả đều bằng nhau và tạo thành nhóm riêng của họ. Mỗi nhóm sau đó được giảm xuống một hàng trong bảng kết quả mới thay thế cho hàng cũ.

Điều này có nghĩa là đối với mệnh đề GROUP BY NULL = NULL không đánh giá thành NULL, như trong 3VL, nhưng nó đánh giá thành TRUE.

Tiêu chuẩn SQL khó hiểu:

ĐẶT HÀNG B BYNG và NULL (329)

Cho dù giá trị khóa sắp xếp là NULL được coi là lớn hơn hoặc nhỏ hơn giá trị không phải NULL được xác định theo thực thi, nhưng ...

... Có những sản phẩm SQL làm theo cách đó.

Vào tháng 3 năm 1999, Chris Farrar đã đưa ra một câu hỏi từ một trong những nhà phát triển của anh ta khiến anh ta kiểm tra một phần của Tiêu chuẩn SQL mà tôi nghĩ rằng tôi đã hiểu . Chris tìm thấy một số khác biệt giữa cách hiểu chung và từ ngữ thực tế của đặc tả .

Và như thế. Tôi nghĩ là đủ bởi Celko.

Ngày của CJ trên SQL NULL

Ngày của CJ là triệt để hơn về NULL: tránh NULL trong SQL, thời gian. Trên thực tế, chương 4 của SQL và Lý thuyết quan hệ của ông : Làm thế nào để viết mã SQL chính xác có tiêu đề "KHÔNG KHAI THÁC, KHÔNG NULLS", với các chương "4.4 Điều gì không đúng với Nulls?" và "4.5 Tránh Nulls trong SQL" (theo liên kết: nhờ Google Sách, bạn có thể đọc một số trang trực tuyến).

Fabian Pascal trên SQL NULL

Từ các vấn đề thực tế của nó trong quản lý cơ sở dữ liệu - Tài liệu tham khảo cho nhà thực hành tư duy (không có trích đoạn trực tuyến, xin lỗi):

10.3 Ý nghĩa cơ bản

10.3.1 SQL NULL

... SQL bị các vấn đề cố hữu trong 3VL cũng như từ nhiều vấn đề, biến chứng, phản tác dụng và lỗi hoàn toàn [10, 11]; trong số đó là:

  • Các hàm tổng hợp (ví dụ: SUM (), AVG ()) bỏ qua NULL (ngoại trừ COUNT ()).
  • Biểu thức vô hướng trên bảng không có hàng đánh giá không chính xác thành NULL, thay vì 0.
  • Biểu thức "NULL = NULL" ước tính thành NULL, nhưng thực sự không hợp lệ trong SQL; nhưng ĐẶT HÀNG B BYNG coi các NULL là như nhau (bất cứ điều gì chúng có trước hoặc theo các giá trị "thông thường" đều được để lại cho nhà cung cấp DBMS).
  • Biểu thức "x IS KHÔNG NULL" không bằng "KHÔNG (x IS NULL)", như trường hợp trong 2VL.

...

Tất cả các phương ngữ SQL được triển khai thương mại đều tuân theo cách tiếp cận 3VL này và do đó, chúng không chỉ giải quyết được các vấn đề này mà còn có các vấn đề triển khai chính xác, khác nhau giữa các sản phẩm .


4
"Và đây là quan điểm của tôi: NULL, như một giá trị, là một" con thú kỳ lạ "." - đó là vì NULLkhông phải là một giá trị.
Pavel Minaev

1
Ngoài ra, SQL Server không cung cấp (NULL = NULL) -> FALSE. Để trích dẫn tài liệu cho ANSI_NULLS: "Khi BẬT được chỉ định, tất cả các so sánh với giá trị null đánh giá với UNKNOWN . Khi TẮT được chỉ định, so sánh các giá trị không phải UNICODE với giá trị null đánh giá TRUE nếu cả hai giá trị là NULL."
Pavel Minaev

@Pavel Minaev: a) và làm thế nào TRUE tốt hơn FALSE? b) Nếu nó không phải là một giá trị tại sao được gán là một phần của các giá trị biến?
MaD70

1
>> Kể từ tháng 12, hãy sử dụng một ví dụ theo mùa. Tôi có hai món quà dưới gốc cây. Bây giờ, bạn nói với tôi nếu tôi có hai điều tương tự hay không. ..... vâng, bạn đã làm điều đó khi bạn có hai điều và theo như bạn quan tâm ngay bây giờ , ở mức độ hiểu biết hiện tại của bạn, chúng hoàn toàn giống với bạn
Brad Thomas

3
null = null nên đúng null là giá trị được xác định rõ có thể đại diện cho một giá trị không xác định , nhưng nó cũng có thể đại diện cho sự vắng mặt của một giá trị. Nhà phát triển phải quyết định null đại diện cho cái gì, nhưng bản thân null hoàn toàn là một giá trị và null là null = null. Bất kỳ triển khai nào khác đều bị ràng buộc bởi thảm họa, bởi vì bạn đang xen kẽ logic ternary vào các vị từ về cơ bản là Boolean. Tôi đã TUYỆT VỜI rằng điều này đang trở thành vĩnh viễn trong cài đặt trong máy chủ SQL. TẮT TẮT TẮT với nó.
Triynko

9

Có lẽ nó phụ thuộc, nhưng tôi nghĩ NULL=NULLđánh giá là NULLthích hầu hết các hoạt động với NULL như một toán hạng.


9

Chỉ vì bạn không biết hai thứ là gì, không có nghĩa là chúng bằng nhau. Nếu khi bạn nghĩ về NULLbạn nghĩ về NULL '(chuỗi) thì có lẽ bạn muốn có một bài kiểm tra khác về đẳng thức như IS DISTINCT FROMAND của PostgresqlIS NOT DISTINCT FROM

Từ các tài liệu PostgreSQL về "Hàm so sánh và toán tử"

biểu hiện IS DISTINCT FROM thức biểu thức

biểu hiện IS NOT DISTINCT FROM thức biểu thức

Đối với các đầu vào không null, IS DISTINCT FROMgiống như <>toán tử. Tuy nhiên, nếu cả hai đầu vào đều rỗng, nó sẽ trả về false và nếu chỉ có một đầu vào là null thì nó trả về true. Tương tự, IS NOT DISTINCT FROMgiống hệt =với các đầu vào không null, nhưng nó trả về true khi cả hai đầu vào đều null và false khi chỉ có một đầu vào là null. Do đó, các cấu trúc này hoạt động hiệu quả như thể null là một giá trị dữ liệu bình thường, thay vì "không xác định".


5

Khái niệm về NULL là đáng nghi ngờ, để nói rằng ít nhất. Codd đã giới thiệu mô hình quan hệ và khái niệm về NULL trong ngữ cảnh (và tiếp tục đề xuất nhiều hơn một loại NULL!) Tuy nhiên, lý thuyết quan hệ đã phát triển kể từ khi các tác phẩm gốc của Codd: một số đề xuất của ông đã bị loại bỏ (ví dụ: khóa chính) và những người khác không bao giờ bị bắt (ví dụ: các nhà khai thác theta). Trong lý thuyết quan hệ hiện đại (lý thuyết thực sự quan hệ, tôi nên nhấn mạnh) NULL đơn giản là không tồn tại. Xem Tuyên ngôn thứ ba. http://www.thethirdmanifesto.com/

Ngôn ngữ SQL chịu sự cố tương thích ngược. NULL tìm thấy đường vào SQL và chúng tôi bị mắc kẹt với nó. Có thể cho rằng, việc triển khai NULLtrong SQL là thiếu sót (việc triển khai SQL Server khiến mọi thứ trở nên phức tạp hơn do ANSI_NULLStùy chọn của nó ).

Tôi khuyên bạn nên tránh sử dụng các cột NULLable trong các bảng cơ sở.


Mặc dù có lẽ tôi không nên bị cám dỗ, tôi chỉ muốn khẳng định một sự điều chỉnh của riêng tôi về cách NULLhoạt động trong SQL:

NULL= NULLđánh giá để UNKNOWN.

UNKNOWN là một giá trị logic.

NULL là một giá trị dữ liệu.

Điều này dễ chứng minh, vd

SELECT NULL = NULL

tạo đúng một lỗi trong SQL Server. Nếu kết quả là một giá trị dữ liệu thì chúng tôi sẽ thấy NULL, vì một số câu trả lời ở đây (sai) cho thấy chúng tôi sẽ làm.

Giá trị logic UNKNOWN được xử lý khác nhau trong SQL DML và SQL DDL tương ứng.

Trong SQL DML, UNKNOWN khiến các hàng bị xóa khỏi tập kết quả.

Ví dụ:

CREATE TABLE MyTable
(
 key_col INTEGER NOT NULL UNIQUE, 
 data_col INTEGER
 CHECK (data_col = 55)
);

INSERT INTO MyTable (key_col, data_col)
   VALUES (1, NULL);

Các INSERTthành công cho hàng này, mặc dù CHECKđiều kiện giải quyết NULL = NULL. Điều này là do định nghĩa trong Tiêu chuẩn SQL-92 ("ANSI"):

Định nghĩa ràng buộc bảng 11.6

3)

Nếu ràng buộc bảng là một định nghĩa ràng buộc kiểm tra, thì hãy đặt SC là điều kiện tìm kiếm ngay trong định nghĩa ràng buộc kiểm tra và đặt T là tên bảng được bao gồm trong mô tả ràng buộc bảng tương ứng; ràng buộc bảng không được thỏa mãn khi và chỉ khi

EXISTS (CHỌN * TỪ T WHERE KHÔNG (SC))

là đúng.

Đọc lại một cách cẩn thận, theo logic.

Nói một cách dễ hiểu, hàng mới của chúng tôi ở trên được trao "lợi ích của sự nghi ngờ" về việc được UNKNOWNvà được phép vượt qua.

Trong SQL DML, quy tắc cho WHEREmệnh đề dễ theo dõi hơn nhiều:

Điều kiện tìm kiếm được áp dụng cho từng hàng của T. Kết quả của mệnh đề where là một bảng gồm các hàng T mà kết quả của điều kiện tìm kiếm là đúng.

Trong tiếng Anh đơn giản, các hàng đánh giá UNKNOWNsẽ bị xóa khỏi tập kết quả.


5

Tại Technet có một lời giải thích tốt về cách các giá trị null hoạt động.

Null có nghĩa là không biết.

Do đó biểu thức Boolean

giá trị = không

không đánh giá thành false, nó ước tính thành null, nhưng nếu đó là kết quả cuối cùng của mệnh đề where thì không có gì được trả về. Đó là một cách thực tế để làm điều đó, vì trả về null sẽ khó thụ thai.

Nó rất thú vị và rất quan trọng để hiểu những điều sau đây:

Nếu trong một truy vấn, chúng tôi có

where (value=@param Or @param is null) And id=@anotherParam

  • giá trị = 1
  • @param là null
  • id = 123
  • @ otherParam = 123

sau đó

"value = @ param" ước tính thành null
"@param là null" ước tính là true
"id = @ AnotherParam" ước tính là đúng

Vì vậy, biểu thức được đánh giá trở thành

(null Hoặc đúng) Và đúng

Chúng tôi có thể bị cám dỗ để nghĩ rằng ở đây "null Hoặc đúng" sẽ được ước tính thành null và do đó toàn bộ biểu thức trở thành null và hàng sẽ không được trả về.

Đây không phải là như vậy. Tại sao?

Bởi vì "null Hoặc true" đánh giá là đúng, điều này rất logic, vì nếu một toán hạng là đúng với toán tử Or, thì bất kể giá trị của toán hạng khác, hoạt động sẽ trả về đúng. Do đó, không có vấn đề gì khi toán hạng khác không xác định (null).

Vì vậy, cuối cùng chúng ta có true = true và do đó hàng sẽ được trả về.

Lưu ý: với cùng logic rõ ràng mà "null Hoặc đúng" đánh giá là đúng, "null và đúng" ước tính thành null.

Cập nhật:
Ok, chỉ để làm cho nó hoàn chỉnh, tôi cũng muốn thêm phần còn lại ở đây, điều này khá thú vị liên quan đến những điều trên.

"null Hoặc false" ước tính thành null, "null và false" ước tính thành false. :)

Logic tất nhiên vẫn là hiển nhiên như trước đây.


4

Bởi vì NULLcó nghĩa là 'giá trị không xác định' và hai giá trị không xác định không thể bằng nhau.

Vì vậy, nếu logic của chúng tôi NULLN ° 1 bằng NULLN ° 2, thì chúng tôi phải nói rằng bằng cách nào đó:

SELECT 1
WHERE ISNULL(nullParam1, -1) = ISNULL(nullParam2, -1)

trong đó giá trị đã biết -1N ° 1 bằng với -1N ° 2


nullParam1 = -1nullParam2 =NULLtai nạn máy bay .... nên làISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin

4

Các câu trả lời ở đây dường như đều xuất phát từ góc độ CS, vì vậy tôi muốn thêm một câu từ góc độ nhà phát triển.

Đối với một nhà phát triển NULL là rất hữu ích. Các câu trả lời ở đây nói rằng NULL có nghĩa là không xác định, và có thể trong lý thuyết CS đó là sự thật, đừng nhớ, đã lâu rồi. Trong phát triển thực tế, ít nhất là theo kinh nghiệm của tôi, điều đó xảy ra khoảng 1% thời gian. 99% khác, nó được sử dụng cho các trường hợp giá trị không phải là UNKNOWN nhưng nó được BIẾT ĐẾN.

Ví dụ:

  • Client.LastPurchase, cho một khách hàng mới. Không rõ, anh ta chưa mua hàng.

  • Khi sử dụng ORM với ánh xạ phân cấp bảng trên mỗi lớp , một số giá trị không được ánh xạ cho các lớp nhất định.

  • Khi ánh xạ cấu trúc cây, một gốc thường sẽ cóParent = NULL

  • Và nhiều thứ khác nữa...

Tôi chắc chắn rằng hầu hết các nhà phát triển tại một số điểm đã viết WHERE value = NULL, không nhận được bất kỳ kết quả nào và đó là cách họ tìm hiểu vềIS NULL cú pháp. Chỉ cần xem có bao nhiêu phiếu bầu câu hỏi này và những người liên kết có.

Cơ sở dữ liệu SQL là một công cụ và chúng nên được thiết kế theo cách dễ hiểu nhất cho người dùng của họ.


1
Mọi người dường như hét lên thì NULL không biết là gì và sau đó biện minh cho hành vi đó. Có, nếu đó là tiền đề thì 3VL có thể là câu trả lời. Nhưng trong hầu hết tất cả các DB tôi làm việc, NULL có nghĩa là vắng mặt. Xin lỗi, giọng nói của bạn bị lạc trong vùng hoang dã @AlexDev
John Rees

3

NULL không bằng bất cứ thứ gì, thậm chí không phải chính nó. Giải pháp cá nhân của tôi để hiểu hành vi của NULL là tránh sử dụng nó càng nhiều càng tốt :).


1
cũng có thể bằng tất cả mọi thứ, như trong trường hợp tham gia trái / phải / bên ngoài ...
Miguel Ventura

5
Thật là một câu trả lời ngớ ngẩn không hiệu quả. Điều tương tự cũng có thể nói với những đứa trẻ tiểu học về đại số, nhưng không thực sự thừa nhận những gì đang cố gắng giải quyết nó sẽ trở nên ngớ ngẩn, điều mà nó đã làm.
Evan Carroll

2
@Evan: Thật ra, tránh NULL là một giải pháp đúng đắn. Logic 3 giá trị không phải là điều không phải bàn cãi và nhiều người cảm thấy rằng SQL sẽ tốt hơn nếu không có NULL và tất cả sự phức tạp (cần thiết) mà nó đòi hỏi.
sleske

3
"Nhiều người" là một từ chồn và "không gây tranh cãi" là một cách để che giấu "tranh cãi" đơn giản hơn trong đó 3VL không phải là.
Evan Carroll

"NULL không bằng bất cứ thứ gì, thậm chí không phải chính nó." theo logic đó, <somevalue>! = NULL sẽ trả về đúng. Tuy nhiên, trong vũ trụ kỳ lạ của SQL, nó sai.
Tom Lint

3

Câu hỏi:
Có ai biết bằng một người khác không biết?
(NULL = NULL)
Câu hỏi đó là điều mà không ai có thể trả lời nên nó mặc định là đúng hay sai tùy thuộc vào cài đặt ansi_nulls của bạn.

Tuy nhiên, câu hỏi:
Là biến số chưa biết này chưa biết?
Câu hỏi này khá khác nhau và có thể được trả lời đúng.

nullVariable = null đang so sánh các giá trị
nullVariable là null đang so sánh trạng thái của biến


3

Sự nhầm lẫn phát sinh từ mức độ gián tiếp (trừu tượng) xuất phát từ việc sử dụng NULL .

Quay trở lại sự tương tự "những gì dưới gốc cây Giáng sinh", "Unknown" mô tả trạng thái kiến ​​thức về những gì trong Hộp A.

Vì vậy, nếu bạn không biết những gì trong Hộp A, bạn nói đó là "Không xác định", nhưng điều đó không có nghĩa là "Không biết" nằm trong hộp . Một cái gì đó không xác định là trong hộp, có thể là một loại đối tượng, hoặc có thể không có gì trong hộp.

Tương tự, nếu bạn không biết những gì trong Hộp B, bạn có thể gắn nhãn trạng thái kiến ​​thức của mình về nội dung là "Không xác định".

Vì vậy, đây là kicker: bạn tình trạng kiến thức về Box A là tương đương với trạng thái của bạn kiến thức về Box B . (Trạng thái kiến ​​thức của bạn trong cả hai trường hợp là "Không xác định" hoặc "Tôi không biết những gì trong Hộp".) Nhưng nội dung của các hộp có thể hoặc không thể bằng nhau.

Quay trở lại SQL, lý tưởng nhất là bạn chỉ có thể so sánh các giá trị khi bạn biết chúng là gì. Thật không may, nhãn mô tả sự thiếu kiến ​​thức được lưu trữ trong chính tế bào , vì vậy chúng tôi rất muốn sử dụng nó làm giá trị. Nhưng chúng ta không nên sử dụng nó như một giá trị, vì nó sẽ dẫn đến "nội dung của Hộp A bằng với nội dung của Hộp B khi chúng ta không biết những gì trong Hộp A và / hoặc chúng ta không biết những gì trong Hộp B. (Về mặt logic, hàm ý "nếu tôi không biết những gì trong Hộp A và nếu tôi không biết những gì trong Hộp B, thì những gì trong Hộp A = Cái gì trong Hộp B" là sai.)

Yay, Ngựa chết.


3

MSDN có một bài viết mô tả hay về null và logic ba trạng thái mà chúng tạo ra.

Nói tóm lại, đặc tả SQL92 định nghĩa NULL là không xác định và NULL được sử dụng trong các toán tử sau gây ra kết quả không mong muốn cho người không quen thuộc:

= operator NULL   true   false 
NULL       NULL   NULL   NULL
true       NULL   true   false
false      NULL   false  true

and op     NULL   true   false 
NULL       NULL   NULL   false
true       NULL   true   false
false      false  false  false

or op      NULL   true   false 
NULL       NULL   true   NULL
true       true   true   true
false      NULL   true   false

Nhưng câu hỏi không phải là về 3VL (logic ba giá trị) là về tính chất phản xạ của đẳng thức.
MaD70

Nói chính xác hơn, như cuối cùng tôi đã nêu chi tiết trong câu trả lời của mình, các vấn đề nảy sinh khi sự bình đẳng được diễn giải trong 3VL để tính chất phản xạ của đẳng thức không phải lúc nào cũng được đánh giá là đúng.
MaD70

1

null là không xác định trong sql vì vậy chúng tôi không thể mong đợi hai ẩn số là như nhau.

Tuy nhiên, bạn có thể thực hiện hành vi đó bằng cách đặt ANSI_NULLS thành Tắt (Bật theo mặc định) Bạn sẽ có thể sử dụng toán tử = cho null

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2

2
Đây là tất cả các loại không . Thế giới có một định nghĩa null, học cách hiểu nó hoặc chỉ thay đổi bảng để có kiểu int và cập nhật các cột.
Evan Carroll

3
Tôi thực sự không khuyến nghị tắt AN AN_NULLS. Tôi đã tìm hiểu về ANSI_NULLS một cách khó khăn. Nhưng thật tốt khi biết tất cả các tùy chọn có sẵn đặc biệt khi bạn bắt gặp một dòng có nội dung Where someId = null Bạn sẽ hiểu ý nghĩa của dòng đó như thế nào mà không biết về ANSI_NULLS. Cách tôi nhìn nó, bài viết của tôi rất hữu ích .. :)
ps.

1

Bạn làm việc cho chính phủ đăng ký thông tin về công dân. Điều này bao gồm ID quốc gia cho mọi người trong cả nước. Một đứa trẻ bị bỏ lại trước cửa nhà thờ khoảng 40 năm trước, không ai biết cha mẹ chúng là ai. ID cha của người này là NULL. Hai người như vậy tồn tại. Đếm những người có chung ID cha với ít nhất một người khác (những người là anh chị em ruột). Bạn có đếm cả hai không?

Câu trả lời là không, bạn không biết, vì chúng tôi không biết họ có phải là anh em ruột hay không.

Giả sử bạn không có NULLtùy chọn và thay vào đó, hãy sử dụng một số giá trị được xác định trước để đại diện cho những người không rõ, có lẽ là một chuỗi trống hoặc số 0 hoặc ký tự *, v.v. Sau đó, bạn sẽ có trong các truy vấn của mình rằng * = * , 0 = 0, và ăn vụng = ứng dụng, v.v. Đây không phải là điều bạn muốn (theo ví dụ ở trên) và như bạn thường quên về những trường hợp này (ví dụ ở trên là một trường hợp rõ ràng bên ngoài suy nghĩ thông thường hàng ngày ), sau đó bạn cần ngôn ngữ để nhớ cho bạn đó NULL = NULLlà không đúng sự thật.

Cần thiết là mẹ của sáng chế.


0

Chỉ là một bổ sung cho câu trả lời tuyệt vời khác:

AND: The result of true and unknown is unknown, false and unknown is false,
while unknown and unknown is unknown.

OR: The result of true or unknown is true, false or unknown is unknown, while unknown or unknown is unknown.

NOT: The result of not unknown is unknown

0

Nếu bạn đang tìm kiếm một biểu thức trả về true cho hai NULL, bạn có thể sử dụng:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

Nó rất hữu ích nếu bạn muốn sao chép dữ liệu từ bảng này sang bảng khác.


0

Kiểm tra đẳng thức, ví dụ, trong một câu lệnh case khi mệnh đề, có thể được thay đổi từ

XYZ = NULL 

đến

XYZ IS NULL

Nếu tôi muốn coi các khoảng trống và chuỗi rỗng bằng với NULL, tôi cũng thường sử dụng một bài kiểm tra đẳng thức như:

(NULLIF(ltrim( XYZ ),'') IS NULL)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.