2011-11-07 464 views
24

這只是一個出於好奇而提出的問題,但我正在查看數據庫,並從其中一列的查詢中提取數據。該列有四個可能的值null0,1,2。當我運行查詢爲:SQL在不等於查詢上不顯示空值?

SELECT * FROM STATUS WHERE STATE != '1' AND STATE != '2'; 

我得到相同的結果運行:

SELECT * FROM STATUS WHERE STATE = '0'; 

即查詢列中頂部命令中具有空值的行似乎從結果中省略,這是否總是在SQL中發生?

我正在通過Oracle SQL Developer運行我的命令。

+4

「這是否總在SQL發生嗎?」 - 簡短的回答:不。 SQL展品[三值邏輯(3VL)](http://en.wikipedia。組織/維基/三valued_logic)。我非常故意地說「展覽」,因爲SQL 3VL的規格不一致和不完整。你只需要學習所有的邊緣情況。 IMO最好的方法是避免SQL中的空值。 – onedaywhen

+1

我知道這不會增加洞察力,但是'OR'應該是'AND'嗎? – user123444555621

+0

從我記得當我這樣做,讓它作爲OR是正確的,即我只想要STATE 0行,但我也得到NULL行。我沒有意識到@Vash在他的回答中描述的三值邏輯。 Michael Durrant指出,我應該使用STATE NOT IN('1','2')。我的SQL比現在好多了,然後就是大聲笑。 –

回答

20

在幾種語言中,NULL的處理方式不同:大多數人都知道二值邏輯,其中truefalse是布爾ex中唯一可比較的值壓力(甚至是虛假的被定義爲0,其他都是真實的)。

在標準SQL中,您必須考慮three-valued logic。 NULL不被視爲真正的值,你可以把它稱爲「未知」。所以如果價值是未知的,不清楚你的情況state是0,1還是其他。所以NULL != 1結果再次NULL

這樣得出結論,無論您過濾可能爲NULL的內容,您都必須自行處理NULL值。請注意,語法也不同:NULL值只能與x IS NULL比較,而不是x = NULL。請參閱維基百科,瞭解顯示邏輯運算結果的真值表。

+0

我明白了,爲快速回答Vash而歡呼:)我一定會在將來記住這一點。 –

+1

我認爲在stackexchange中,你會收到很快的答案。如果您嘗試自己回答問題,您會發現很難找到您能夠回答並且想要回答的未答覆問題。然而,這也是一個簡短的答案,現在我在家裏也會更新它,以反映三值邏輯。 – Alex

7

Yest這是正常的,你也許可以將數據庫設置固定的

但是你可以修改你的代碼,做這樣的事情:

SELECT * FROM STATUS WHERE STATE != '1' OR STATE != '2' or STATE is null; 

看看本作的詳細信息: http://www.w3schools.com/sql/sql_null_values.asp

3

多個orwhere的s可以很快變得難以閱讀和結果不確定。

我會建議額外的括號加上使用IN語句(在這種情況下爲NOT IN),例如,

SELECT * FROM STATUS WHERE (STATE NOT IN ('1', '2')) or STATE is null;

Implmentations可以數據庫供應商,但上面明確語法應確保結果有所不同。

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) 

0

使用NVL像這樣:SELECT * FROM STATUS WHERE NVL(STATE,'X') != '1' AND NVL(STATE,'X')!= '2';