Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

KHÔNG VÀO lựa chọn với giá trị NULL

Đầu tiên một chút lý thuyết:Null (SQL)

Các phần quan trọng nhất đối với chúng tôi từ liên kết trên:

So sánh với NULL và logic ba giá trị (3VL)

Vì Null không phải là thành viên của bất kỳ miền dữ liệu nào, nên nó không được coi là "giá trị", mà là một điểm đánh dấu (hoặc trình giữ chỗ) cho biết sự vắng mặt của giá trị. Do đó, các phép so sánh với Null không bao giờ có thể dẫn đến Đúng hoặc Sai, mà luôn dẫn đến kết quả logic thứ ba, Không xác định. [8] Kết quả logic của biểu thức dưới đây, so sánh giá trị 10 với Null, là Không xác định:

SELECT 10 = NULL       -- Results in Unknown

để cả hai so sánh:x = NULLx <> NULL đánh giá là NULL (không xác định).

SQL thực thi ba kết quả logic, vì vậy việc triển khai SQL phải cung cấp cho một logic ba giá trị chuyên biệt (3VL). Các quy tắc chuyển đổi logic ba giá trị của SQL được hiển thị trong bảng bên dưới (p vàq đại diện cho các trạng thái logic) "[9] Các bảng sự thật mà SQL sử dụng cho AND, OR và NOT tương ứng với một đoạn chung của logic có giá trị Kleene và Łukasiewiczthree ( khác nhau trong định nghĩa của chúng về hàm ý, tuy nhiên SQL định nghĩa không có hoạt động nào như vậy).

+---------+-------------+-------------+-------------+-----------+--------+
|    p    |        q    |     p OR q  |     p AND q |    p = q  |p != q  |
+---------+-------------+-------------+-------------+-----------+--------+
| True    |     True    |     True    |     True    |   True    | False  |
| True    |     False   |     True    |     False   |   False   | True   |
| True    |     Unknown |     True    |     Unknown |   Unknown | Unknown|
| False   |     True    |     True    |     False   |   False   | True   |
| False   |     False   |     False   |     False   |   True    | False  |
| False   |     Unknown |     Unknown |     False   |   Unknown | Unknown|
| Unknown |     True    |     True    |     Unknown |   Unknown | Unknown|
| Unknown |     False   |     Unknown |     False   |   Unknown | Unknown|
| Unknown |     Unknown |     Unknown |     Unknown |   Unknown | Unknown|
+---------+-------------+-------------+-------------+-----------+--------+

Ảnh hưởng của Không xác định trong mệnh đề WHERE

Logic ba giá trị của SQL gặp phải trong Ngôn ngữ thao tác dữ liệu (DML) trong các vị từ so sánh của các câu lệnh và truy vấn DML. Mệnh đề TheWHERE khiến câu lệnh DML chỉ hoạt động trên các hàng đó mà vị từ đánh giá là True.

Tóm lại:Mệnh đề WHERE coi NULL là FALSE

Bây giờ hãy xem xét một trường hợp đơn giản hơn:

SELECT * FROM T1;

|      X |
|--------|
|      1 |
| (null) |

và một truy vấn:

SELECT * FROM t1 WHERE x IN (1, NULL);

Truy vấn trên là một đường tắt dẫn đến truy vấn này:

SELECT * FROM t1 
WHERE x = 1
  OR  x = NULL

Đối với hàng thứ hai từ bảng t (x =NULL) điều kiện này giống như sau:

WHERE NULL = 1
   OR NULL = NULL

vì vậy điều kiện này cho hàng x = NULL đánh giá là NULL vì NULL=1 là NULL, NULL=NULL là NULL và NULL OR NULL cũng là NULL (vui lòng xem bảng 3VL ở trên).

Bây giờ hãy xem xét trường hợp tò mò hơn:

SELECT * FROM t1 WHERE x NOT IN (1, NULL);

Mệnh đề này x NOT IN (1, NULL) tương đương với NOT ( x IN (1, NULL) )
vì vậy nó cũng tương đương với:

NOT (
  x = 1
  OR
  x = NULL
)

và theo luật của De Morgan, nó tương đương với:

NOT ( x = 1 ) AND NOT ( x = NULL )

và (nếu chúng ta thay thế NOT x = y với x <> y ) nó cũng tương đương với:

 x <> 1 AND x <> NULL

Vui lòng xem kỹ điều kiện cuối cùng:

WHERE 
x <> 1 AND x <> NULL

Chúng tôi biết nhiều hơn x <> NULL luôn đánh giá là NULL. Chúng tôi cũng biết từ bảng 3VL ở trên, rằng cả true AND NULL là NULL và false AND NULL đánh giá là FALSE, do đó, toàn bộ điều kiện luôn đánh giá là FALSE hoặc NULL, nhưng nó không bao giờ đánh giá là TRUE.

Do đó, một truy vấn với điều kiện này:

SELECT .....
WHERE x NOT IN ( NULL, whatever)

luôn trả về tập kết quả trống

Và bây giờ là truy vấn của bạn, cũng rất tò mò:

SELECT * FROM t1
WHERE (id, val) NOT IN (select id, val from data2);

có thể được viết lại (sử dụng các giá trị không đổi) thành:

SELECT * FROM t1
WHERE (id, val) NOT IN (
       (1, null),
       (2, 2 )
)

Truy vấn này đang sử dụng cái gọi là biểu thức giá trị hàng

Về cơ bản là một điều kiện sử dụng giá trị hàng expressin như thế này

(a, b) = (x, y)

tương đương với cái này:

a = x AND b = y

vì vậy truy vấn trên có thể được viết lại thành sau:

SELECT * FROM t1
WHERE NOT (
   id = 1 AND val = NULL
   OR
   id = 2 AND val = 2
)

Theo luật của De Morgan, điều này giống với:

SELECT * FROM t1
WHERE 
   NOT ( id = 1 AND val = NULL )
   AND
   NOT ( id = 2 AND val = 2 )

và xa hơn nữa là:

SELECT * FROM t1
WHERE 
   ( id <> 1 OR val <> NULL )
   AND
   ( id <> 2 OR val <> 2 )

Kể từ phần đầu tiên ( id <> 1 OR val <> NULL ) của điều kiện được đánh giá là true chỉ trong trường hợp id <> 1 (vui lòng xem bảng 3VL ở trên), điều kiện này có thể được đơn giản hóa thành:

SELECT * FROM t1
WHERE 
   ( id <> 1 )
   AND
   ( id <> 2 OR val <> 2 )

và xa hơn nữa (theo luật của De Morgan) thành:

SELECT * FROM t1
WHERE 
   id <> 1 AND id <> 2
   OR
   id <> 1 AND  val <> 2

vì vậy không phải (1,1) cũng không phải (2,2) từ nguồn data1 tuân thủ các điều kiện này.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chúng ta có cần chỉ định không null cho khóa chính không? Oracle / SQL

  2. Giới thiệu về phương pháp thu thập PL / SQL trong cơ sở dữ liệu Oracle

  3. ODP.NET có yêu cầu cài đặt Oracle Client không

  4. Xóa các hàng khỏi bảng mẹ và bảng con

  5. java.sql.SQLException:Exhausted Resultset