問:什么是NULL?
答:在我們不知道具體有什么數(shù)據(jù)的時候,也即未知,可以用NULL,我們稱它為空,ORACLE中,含有空值的表列長度為零。
ORACLE允許任何一種數(shù)據(jù)類型的字段為空,除了以下兩種情況:
1、主鍵字段(primary key),
2、定義時已經(jīng)加了NOT NULL限制條件的字段
說明:
1、等價于沒有任何值、是未知數(shù)。
2、NULL與0、空字符串、空格都不同。
3、對空值做加、減、乘、除等運算操作,結果仍為空。
4、NULL的處理使用NVL函數(shù)。
5、比較時使用關鍵字用“is null”和“is not null”。
6、空值不能被索引,所以查詢時有些符合條件的數(shù)據(jù)可能查不出來,count(*)中,用nvl(列名,0)處理后再查。
7、排序時比其他數(shù)據(jù)都大(索引默認是降序排列,小→大),所以NULL值總是排在最后。
使用方法:
SQL> select 1 from dual where null=null;
沒有查到記錄
SQL> select 1 from dual where null='';
沒有查到記錄
SQL> select 1 from dual where ''='';
沒有查到記錄
SQL> select 1 from dual where null is null;
1
---------
1
SQL> select 1 from dual where nvl(null,0)=nvl(null,0);
1
---------
1
對空值做加、減、乘、除等運算操作,結果仍為空。
SQL> select 1+null from dual;
SQL> select 1-null from dual;
SQL> select 1*null from dual;
SQL> select 1/null from dual;
以上四條語句均查詢到一個記錄.
注:這個記錄就是SQL語句中的那個null
設置某些列為空值
update table1 set 列1=NULL where 列1 is not null;
現(xiàn)有一個商品銷售表sale,表結構為:
month char(6) --月份
sellnumber(10,2) --月銷售金額
create table sale (month char(6),sell number);
insert into sale values('200001',1000);
insert into sale values('200002',1100);
insert into sale values('200003',1200);
insert into sale values('200004',1300);
insert into sale values('200005',1400);
insert into sale values('200006',1500);
insert into sale values('200007',1600);
insert into sale values('200101',1100);
insert into sale values('200202',1200);
insert into sale values('200301',1300);
insert into sale values('200008',1000);
insert into sale(month) values('200009');(注意:這條記錄的sell值為空)
commit;
共輸入12條記錄
SQL> select * from sale where sell like '%';
MONTH SELL
------ ---------
200001 1000
200002 1100
200003 1200
200004 1300
200005 1400
200006 1500
200007 1600
200101 1100
200202 1200
200301 1300
200008 1000
查詢到11記錄.
結果說明:
查詢結果說明此SQL語句查詢不出列值為NULL的字段,此時需對字段為NULL的情況另外處理。
SQL> select * from sale where sell like '%' or sell is null;
SQL> select * from sale where nvl(sell,0) like '%';
MONTH SELL
------ ---------
200001 1000
200002 1100
200003 1200
200004 1300
200005 1400
200006 1500
200007 1600
200101 1100
200202 1200
200301 1300
200008 1000
200009
查詢到12記錄.
Oracle的空值就是這么的用法,我們最好熟悉它的約定,以防查出的結果不正確
----------------------------------------------------------------------------------
根據(jù)NULL的定義,NULL表示的是未知,因此兩個NULL比較的結果既不相等,也不不等,結果仍然是未知。根據(jù)這個定義,多個NULL值的存在應該不違反唯一約束。
實際上Oracle也是如此實現(xiàn)的:
SQL CREATE TABLE T (ID NUMBER);
表已創(chuàng)建。
SQL ALTER TABLE T ADD UNIQUE (ID);
表已更改。
SQL INSERT INTO T VALUES (1);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (1);
INSERT INTO T VALUES (1)
第 1 行出現(xiàn)錯誤:
ORA-00001: 違反唯一約束條件 (YANGTK。SYS_C007300)
SQL INSERT INTO T VALUES (NULL);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (NULL);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (NULL);
已創(chuàng)建 1 行。
但是當唯一約束為復合字段時,則情況發(fā)生了變化。根據(jù)Oracle文檔的描述,對于復合字段的唯一約束,不為空字段的值是不能重復的。也就是說,如果兩個字段構成了一個唯一約束,其中一個字段為空,那么另一個字段的值不能出現(xiàn)重復。
SQL DROP TABLE T PURGE;
表已刪除。
SQL CREATE TABLE T (ID NUMBER, ID2 NUMBER);
表已創(chuàng)建。
SQL ALTER TABLE T ADD UNIQUE (ID, ID2);
表已更改。
SQL INSERT INTO T VALUES (1, 1);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (1, NULL);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (2, NULL);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (1, NULL);
INSERT INTO T VALUES (1, NULL)
第 1 行出現(xiàn)錯誤:
ORA-00001: 違反唯一約束條件 (YANGTK。SYS_C007301)
SQL INSERT INTO T VALUES (NULL, NULL);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (NULL, NULL);
已創(chuàng)建 1 行。
SQL INSERT INTO T VALUES (NULL, NULL);
已創(chuàng)建 1 行。
對于全部為NULL的情況,仍然和單字段唯一約束一樣,不會造成重復,但是對于部分為NULL的情況,就如上面例子所示,只要其中不為NULL的部分發(fā)生了重復,Oracle就認為約束發(fā)生了重復。
而這似乎和NULL的定義有所沖突,第一次看concept的時候一直沒有搞明白Oracle為什么這么實現(xiàn),不過這次再看concept的時候,已經(jīng)想明白了。
由于Oracle的唯一約束是依賴索引實現(xiàn)的,而Oracle的BTREE索引又是不存儲NULL值的,所以鍵值全部為NULL的記錄不會記錄在索引中,因此也就不會違反唯一約束了,而對于部分為NULL的記錄,索引是要記錄數(shù)值的,因此一旦鍵值中非NULL部分發(fā)生了沖突,Oracle就認為違反了的唯一約束。
Oracle在這里還是選擇了自己的方便的方法來實現(xiàn),而沒有完全真正的根據(jù)NULL的定義去實現(xiàn)唯一約束。
########################################################
view plaincopy to clipboardprint?
剛才測試了一下null和空字符串的關系
SQL> create table t1(id number,name varchar2(20));
Table created.
SQL> insert into t1 values(1,'');
1 row created.
SQL> insert into t1 values(2,'ww');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t1;
ID NAME
---------- --------------------
1
2 ww
SQL> select * from t1
2 where name is null;
ID NAME
---------- --------------------
1
SQL> select * from t1
2 where name=null;
no rows selected
SQL> select * from t1
2 where name='';
no rows selected
SQL> insert into t1
2 values(3,null);
1 row created.
SQL> select * from t1;
ID NAME
---------- --------------------
1
2 ww
3
//感覺ORACLE就是把空字符串''當做NULL在處理 可是在判斷的時候不能用='' 而需要用is null或者is not null