Mệnh đề IN với NULL hoặc IS NULL


83

Postgres là cơ sở dữ liệu

Tôi có thể sử dụng giá trị NULL cho mệnh đề IN không? thí dụ:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)

Tôi muốn giới hạn ở bốn giá trị này.

Tôi đã thử câu lệnh trên và nó không hoạt động, nó thực thi nhưng không thêm các bản ghi với NULL id_fields.

Tôi cũng đã cố gắng thêm điều kiện HOẶC nhưng điều này chỉ làm cho truy vấn chạy và chạy mà không có kết thúc trong tầm nhìn.

SELECT *
FROM tbl_name
WHERE other_condition = bar
AND another_condition = foo
AND id_field IN ('value1', 'value2', 'value3')
OR id_field IS NULL

Bất kỳ đề xuất?


10
Một incâu lệnh sẽ được phân tích cú pháp giống hệt nhau field=val1 or field=val2 or field=val3. Đặt một null vào đó sẽ sôi xuống field=nullmà sẽ không hoạt động.
Marc B

1
truy vấn thứ 2 phải đúng. những thứ khác trong wheremệnh đề của bạn là gì?
Daniel A. White

@Daniel A. White, được cập nhật để phản ánh truy vấn với nhiều điều kiện hơn
Phill Pafford

Câu trả lời:


122

Một incâu lệnh sẽ được phân tích cú pháp giống hệt nhau field=val1 or field=val2 or field=val3. Đặt một null vào đó sẽ sôi xuống field=nullmà sẽ không hoạt động.

( Bình luận của Marc B )

Tôi sẽ làm điều này vì sự đòi hỏi

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

Ahh đã làm được, cảm ơn! Vì vậy, gói các trường thêm cả hai điều kiện vào mệnh đề WHERE? Chỉ để làm rõ
Phill Pafford

1
@Phill - đó là một vấn đề về thứ tự hoạt động.
Daniel A. White

20

Truy vấn của bạn không thành công do sự ưu tiên của toán tử . ANDràng buộc trước đây OR!
Bạn cần một cặp dấu ngoặc đơn, đó không phải là vấn đề "rõ ràng", mà là sự cần thiết thuần túy về logic .

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   (id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

Các dấu ngoặc đơn được thêm vào ngăn chặn sự ANDràng buộc trước đó OR. Nếu không có WHEREđiều kiện nào khác (không AND), bạn sẽ không cần dấu ngoặc đơn. Câu trả lời được chấp nhận là một chút sai lầm trong khía cạnh này.


15
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

Vì vậy, bạn loại bỏ null khỏi séc. Đưa ra giá trị null trong id_field, hàm liên kết sẽ thay vì trả về null 'unik_null_value' và bằng cách thêm 'unik_null_value vào danh sách IN, truy vấn sẽ trả về các bài đăng trong đó id_field là giá trị1-3 hoặc null.


2
Một chút giải thích sẽ hữu ích cho độc giả trong tương lai. Mã của bạn giúp giải quyết vấn đề như thế nào?
showdev

9

Câu hỏi được trả lời bởi Daniel là hoàn toàn ổn. Tôi muốn để lại một ghi chú về NULLS. Chúng ta nên cẩn thận về việc sử dụng toán tử NOT IN khi một cột chứa giá trị NULL. Bạn sẽ không nhận được bất kỳ đầu ra nào nếu cột của bạn chứa các giá trị NULL và bạn đang sử dụng toán tử NOT IN. Đây là cách nó được giải thích ở đây http://www.oraclebin.com/2013/01/beware-of-nulls.html , một bài báo rất hay mà tôi đã xem qua và nghĩ sẽ chia sẻ nó.


Không chắc có bao nhiêu người sử dụng đã gặp sự cố này, nhưng tôi đã gặp sự cố chính xác này khi trộn toán tử null và NOT IN và đã lăn tăn về nó trong hai giờ qua. ĐÂY là perp ...
Govind Rai

1
Liên kết đã chết.
Dag Høidahl

1
Giống như đang sống bây giờ.
luôn-một-người học

3

Lưu ý: Vì ai đó tuyên bố rằng liên kết bên ngoài đã chết trong câu trả lời của Sushant Butta, tôi đã đăng nội dung ở đây như một câu trả lời riêng biệt.

Hãy coi chừng NULLS .

Hôm nay tôi đã gặp một hành vi truy vấn rất lạ khi sử dụng IN và các NOT INtoán tử. Trên thực tế, tôi muốn so sánh hai bảng và tìm xem liệu một giá trị từ table bcó tồn tại trong table ahay không và tìm hiểu hành vi của nó nếu cột chứanull giá trị. Vì vậy, tôi chỉ tạo một môi trường để kiểm tra hành vi này.

Chúng tôi sẽ tạo bảng table_a.

SQL> create table table_a ( a number);
Table created.

Chúng tôi sẽ tạo bảng table_b.

SQL> create table table_b ( b number);
Table created.

Chèn một số giá trị vào table_a.

SQL> insert into table_a values (1);
1 row created.

SQL> insert into table_a values (2);
1 row created.

SQL> insert into table_a values (3);
1 row created.

Chèn một số giá trị vào table_b.

SQL> insert into table_b values(4);
1 row created.

SQL> insert into table_b values(3);
1 row created.

Bây giờ chúng ta sẽ thực hiện một truy vấn để kiểm tra sự tồn tại của một giá trị trong table_abằng cách kiểm tra giá trị của nó từ table_bviệc sử dụng INtoán tử.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

Thực hiện truy vấn dưới đây để kiểm tra sự không tồn tại.

SQL> select * from table_a where a not in (select * from table_b);
         A
----------
         1
         2

Sản lượng đã đến như mong đợi. Bây giờ chúng ta sẽ chèn một nullgiá trị vào bảng table_bvà xem hai truy vấn trên hoạt động như thế nào.

SQL> insert into table_b values(null);
1 row created.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

SQL> select * from table_a where a not in (select * from table_b);

no rows selected

Truy vấn đầu tiên hoạt động như mong đợi nhưng điều gì đã xảy ra với truy vấn thứ hai? Tại sao chúng tôi không nhận được bất kỳ đầu ra nào, điều gì đã nên xảy ra? Có sự khác biệt nào trong truy vấn không? Không .

Sự thay đổi nằm trong dữ liệu của bảng table_b. Chúng tôi đã giới thiệu một nullgiá trị trong bảng. Nhưng tại sao nó lại hoạt động như thế này? Hãy tách hai truy vấn thành "AND""OR"toán tử.

Truy vấn đầu tiên:

Truy vấn đầu tiên sẽ được xử lý nội bộ như thế này. Vì vậy, a nullsẽ không tạo ra vấn đề ở đây vì hai toán hạng đầu tiên của tôi sẽ đánh giá đến truehoặc false. Nhưng toán hạng thứ ba của tôi a = nullsẽ không đánh giá truevà cũng không false. Nó sẽ chỉ đánh giá null.

select * from table_a whara a = 3 or a = 4 or a = null;

a = 3  is either true or false
a = 4  is either true or false
a = null is null

Truy vấn thứ hai:

Truy vấn thứ hai sẽ được xử lý như bên dưới. Vì chúng tôi đang sử dụng một "AND"toán tử và bất kỳ thứ gì khác ngoài truebất kỳ toán hạng nào sẽ không cung cấp cho tôi bất kỳ đầu ra nào.

select * from table_a whara a <> 3 and a <> 4 and a <> null;

a <> 3 is either true or false
a <> 4 is either true or false
a <> null is null

Vậy chúng ta phải xử lý việc này như thế nào? Chúng tôi sẽ chọn tất cả các not nullgiá trị từ bảng table_btrong khi sử dụng NOT INtoán tử.

SQL> select * from table_a where a not in (select * from table_b where b is not null);

         A
----------
         1
         2

Vì vậy, hãy luôn cẩn thận về NULLcác giá trị trong cột khi sử dụng NOT INtoán tử.

Hãy coi chừng NULL !!


Câu trả lời xuất sắc. Tôi vừa mới phát hiện ra vấn đề trong công việc của mình. Hành vi rất kỳ lạ của Oracle.
oputyk

0

Tôi biết là đã muộn để trả lời nhưng có thể hữu ích cho người khác. Bạn có thể sử dụng truy vấn phụ và chuyển giá trị null thành 0

SELECT *
FROM (SELECT CASE WHEN id_field IS NULL 
                THEN 0 
                ELSE id_field 
            END AS id_field
      FROM tbl_name) AS tbl
WHERE tbl.id_field IN ('value1', 'value2', 'value3', 0)

Điều này tương tự như câu trả lời của Ove Halseth sử dụng liên kết.
user890332

0

Nullđề cập đến sự vắng mặt của dữ liệu. Nullđược định nghĩa chính thức là một giá trị không có sẵn, chưa được gán, không xác định hoặc không thể áp dụng (Cơ sở dữ liệu OCA Oracle 12c, Hướng dẫn Kiểm tra Cơ bản về SQL, tr87). Vì vậy, bạn có thể không nhìn thấy các bản ghi có cột chứa giá trị rỗng khi các cột đã nói bị hạn chế bằng cách sử dụng mệnh đề "trong" hoặc "không trong".

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.