使用LNNVL替代NOT IN处理含NULL的SQL查询是否有更简洁方案?
最优方案(Oracle专属,扩展性最佳)
直接使用 lnnvl() 配合 IN 关键字即可,只需要一行条件就能实现需求,无论校验的取值集合多大都可以直接扩展:
SELECT * FROM foo WHERE lnnvl(foo.bar IN ('X', 'Y'));
这个写法的逻辑和你之前的三种实现完全等价:当foo.bar等于列表中任意值时返回false,当foo.bar为NULL或者不在列表中时返回true,完美符合过滤要求。
其他可选方案说明
1. NVL/COALESCE 改造方案
你原本用的nvl(foo.bar, ' ') NOT IN ('X', 'Y')写法本身可用,唯一需要注意的是你选的默认填充值绝对不能出现在待排除的取值集合中,否则会出现逻辑错误。如果需要更好的兼容性,可以用标准SQL的COALESCE替代nvl:
SELECT * FROM foo WHERE COALESCE(foo.bar, '/* 不会出现在排除集合中的特殊值 */') NOT IN ('X', 'Y');
2. 跨数据库兼容方案
如果需要考虑代码跨数据库运行,不依赖Oracle独有的lnnvl函数,最稳妥的还是原生的NOT IN + IS NULL写法,逻辑清晰无隐含坑:
SELECT * FROM foo WHERE foo.bar NOT IN ('X', 'Y') OR foo.bar IS NULL;
内容的提问来源于stack exchange,提问作者Zeda
相关产品推荐
相关产品推荐

