筛数据想排除某个值,随手写了个不等于,结果不是报错就是少数据,这种情况太常见了。sql不等于有两种写法:尖括号<>是标准SQL的写法,主流数据库都认;感叹号加等号!=是很多数据库提供的等价形式,MySQL、SQL Server、PostgreSQL、Oracle都支持。新写的SQL建议统一用尖括号,读老代码时知道两者等价就行。
基本写法
SELECT * FROM student WHERE status <> 1; SELECT * FROM student WHERE status != 1;两条等价,把状态不是1的行都查出来。字符和日期同样适用,比如WHERE name <> '张三',注意文本要配单引号。日期也一样,排除某天的记录用create_time <> 对应时间点就行。
最大的坑:NULL不参与比较
用不等于过滤时,NULL的行不会出现在结果里。WHERE status <> 1查不出status为NULL的行,因为NULL和任何值比较的结果都是未知,不是真。想把这些行一起拿进来,条件要显式写全:
SELECT * FROM student WHERE status <> 1 OR status IS NULL;反过来,判断空也不能写<>NULL,得用IS NULL和IS NOT NULL,这是标准规定,不是哪个数据库的毛病。
NOT IN的连带问题
NOT IN后面的子查询里只要混进一个NULL,整条查询直接返回空集,一行都出不来,很多人在这里耗了半天。比如排查为什么明明有数据却查不出来,先看看子查询那一列有没有空值。稳妥做法是子查询里先用IS NOT NULL把空值排掉,或者干脆改成NOT EXISTS的写法,语义更清楚。
实际建议两条:团队里统一用<>,把!=当方言看;sql不等于的条件写完,顺手想一下这一列有没有NULL,十有八九能省掉一次排查。