Tránh NOT IN
như bệnh dịch nếu
SELECT ID_Courses FROM Evaluation where `NAME`='JOHN' and Year=1
bao giờ có thể chứa NULL. Thay vào đó, hãy sử dụng KHÔNG TỒN TẠI hoặc Kết nối Trái
sử dụng các phép nối rõ ràng, không phải phép nối kiểu của năm 1980 bằng cách sử dụng WHERE
mệnh đề
Để minh họa sự khốn khổ của việc KHÔNG VÀO:
SQL NOT IN () nguy hiểm
create table mStatus
( id int auto_increment primary key,
status varchar(10) not null
);
insert mStatus (status) values ('single'),('married'),('divorced'),('widow');
create table people
( id int auto_increment primary key,
fullName varchar(100) not null,
status varchar(10) null
);
Chunk1:
truncate table people;
insert people (fullName,`status`) values ('John Henry','single');
select * from mstatus where `status` not in (select status from people);
** 3 hàng, như mong đợi **
Chunk2:
truncate table people;
insert people (fullName,`status`) values ('John Henry','single'),('Kim Billings',null);
select * from mstatus where status not in (select status from people);
không có hàng nào?
Rõ ràng điều này là 'không chính xác'. Nó phát sinh từ việc SQL sử dụng logic ba giá trị, được thúc đẩy bởi sự tồn tại của NULL, một giá trị không chỉ ra thông tin bị thiếu (hoặc UNKNOWN).
status NOT IN ('married', 'divorced', 'widowed', NULL)
Điều này tương đương với:
NOT(status='single' OR status='married' OR status='widowed' OR status=NULL)
Biểu thức "status =NULL" đánh giá là UNKNOWN và theo các quy tắc của logic ba giá trị, NOT UNKNOWN cũng đánh giá là UNKNOWN. Kết quả là tất cả các hàng được lọc ra và truy vấn trả về một tập hợp trống.
Các giải pháp khả thi bao gồm:
select s.status
from mstatus s
left join people p
on p.status=s.status
where p.status is null
hoặc sử dụng not exists