这只是一个好奇的问题,但我正在查看一个数据库并从一个表中提取数据,并在其中一个列上查询。该列有四个可能的值null
,0
,1
,2
。当我将查询运行为:
SELECT * FROM STATUS WHERE STATE != '1' AND STATE != '2';
我得到的结果与跑步相同:
SELECT * FROM STATUS WHERE STATE = '0';
即。查询列中top命令中具有空值的行似乎从结果中省略,这是否总是发生在SQL中?
我正在通过Oracle SQL Developer运行我的命令。
答案 0 :(得分:29)
在几种语言中,NULL的处理方式不同:大多数人都知道二值逻辑,其中true
和false
是布尔表达式中唯一可比较的值(即使是假定义为0,也是真的其他任何事情)。
在标准SQL中,您必须考虑three-valued logic。 NULL不被视为实际值,您可以将其称为“未知”。因此,如果值未知,则不清楚在您的情况下state
是0,1还是其他任何内容。因此NULL != 1
再次向NULL
结果。
这样就得出结论,无论您过滤掉可能为NULL的内容,都必须自己处理NULL值。请注意,语法也不同:NULL值只能与x IS NULL
而不是x = NULL
进行比较。请参阅Wikipedia,了解显示逻辑运算结果的真值表。
答案 1 :(得分:9)
是的,这是正常的,你可以设置一个数据库设置来修复
但你可以修改你的代码并做类似的事情:
SELECT * FROM STATUS WHERE STATE != '1' OR STATE != '2' or STATE is null;
请查看此信息以获取更多信息: http://www.w3schools.com/sql/sql_null_values.asp
答案 2 :(得分:5)
or
的多个where
很快就会变得难以阅读并且不确定结果。
我建议使用额外的括号加上使用IN
语句(在这种情况下为NOT IN
),例如
SELECT * FROM STATUS WHERE (STATE NOT IN ('1', '2')) or STATE is null;
数据库供应商之间的实施可能有所不同,但上述显式语法应确保结果。
答案 3 :(得分:2)
像这样使用NVL
:SELECT * FROM STATUS WHERE NVL(STATE,'X') != '1' AND NVL(STATE,'X')!= '2';
答案 4 :(得分:0)
我为research Oracle行为创建了脚本:
create table field_values ( is_user_deletable VARCHAR2(1 CHAR), resource_mark VARCHAR2(3 CHAR) ) insert into field_values values (NULL, NULL); insert into field_values values ('Y', NULL); insert into field_values values ('N', NULL); select * from field_values; -- 3 row -- 1 row, bad update field_values set resource_mark = 'D' where is_user_deletable = 'Y'; update field_values set resource_mark = 'D' where is_user_deletable <> 'N'; update field_values set resource_mark = 'D' where is_user_deletable != 'N'; update field_values set resource_mark = 'D' where is_user_deletable not in ('Y'); -- 2 rows, good, but needs more SQL and more comparisons. Does DB optimizes? update field_values set resource_mark = 'D' where is_user_deletable = 'N' or is_user_deletable is null; -- it better to have ('Y' and NULL) or ('N' and NULL), but not 'Y' and 'N' and NULL (avoid quires with https://en.wikipedia.org/wiki/Three-valued_logic) -- adding new column which is 'Y' or 'N' only into existing table may be very long locking operation on existing table (or running long DML script)