根據null的定義,null表示的是未知,因此兩個null比較的結果既不相等,也不不等,結果仍然是未知。根據這個定義,多個null值的存在應該不違反唯一約束。
實際上oracle也是如此實現的:
sql>但是當唯一約束為復合欄位時,則情況發生了變化。根據oracle文件的描述,對於復合欄位的唯一約束,不為空字段的值是不能重複的。也就是說,如果兩個字段構成了乙個唯一約束,其中乙個欄位為空,那麼另乙個欄位的值不能出現重複。create
table t (id number
);表已建立。
sql>
alter
table t add
unique
(id);
表已更改。
sql>
insert
into t values (1
);已建立 1行。
sql>
insert
into t values (1
);insert
into t values (1
)*第 1
行出現錯誤:
ora-
00001
: 違反唯一約束條件 (yangtk.sys_c007300)
sql>
insert
into t values (null
);已建立 1行。
sql>
insert
into t values (null
);已建立 1行。
sql>
insert
into t values (null
);已建立
1 行。
sql>view codedrop
table
t purge;
表已刪除。
sql>
create
table t (id number, id2 number
);表已建立。
sql>
alter
table t add
unique
(id, id2);
表已更改。
sql>
insert
into t values (1, 1
);已建立 1行。
sql>
insert
into t values (1, null
);已建立 1行。
sql>
insert
into t values (2, null
);已建立 1行。
sql>
insert
into t values (1, null
);insert
into t values (1, null
)*第 1
行出現錯誤:
ora-
00001
: 違反唯一約束條件 (yangtk.sys_c007301)
sql>
insert
into t values (null, null
);已建立 1行。
sql>
insert
into t values (null, null
);已建立 1行。
sql>
insert
into t values (null, null
);已建立
1 行。
對於全部為null的情況,仍然和單字段唯一約束一樣,不會造成重複,但是對於部分為null的情況,就如上面例子所示,只要其中不為null的部分發生了重複,oracle就認為約束發生了重複。
而這似乎和null的定義有所衝突,第一次看concept的時候一直沒有搞明白oracle為什麼這麼實現,不過這次再看concept的時候,已經想明白了。
由於oracle的唯一約束是依賴索引實現的,而oracle的btree索引又是不儲存null值的,所以鍵值全部為null的記錄不會記錄在索引中,因此也就不會違反唯一約束了,而對於部分為null的記錄,索引是要記錄數值的,因此一旦鍵值中非null部分發生了衝突,oracle就認為違反了的唯一約束。
oracle在這裡還是選擇了自己的方便的方法來實現,而沒有完全真正的根據null的定義去實現唯一約束。
oracle違反唯一約束
報錯資訊 nested exception is org.hibernate.exception.constraintviolationexception could not execute statement 背景 修改原有的邏輯,取消掉某個欄位的唯一約束。框架 spring data jpa 1...
Oracle資料庫的唯一約束
一 唯一約束的作用 保證字段值得唯一性。二 唯一約束和主鍵約束的區別 主鍵字段值必須是非空的。唯一約束允許有乙個空值。主鍵在每張表中只能有乙個。唯一約束在每張表中可以有多個。三 在建立表時設定唯一約束 1 在列級建立唯一約束 語法 create table table name column nam...
Oracle 資料庫唯一約束中的NULL的處理
根據null的定義,null表示的是未知,因此兩個null比較的結果既不相等,也不不等,結果仍然是未知。根據這個定義,多個null值的存在應該不違反唯一約束。實際上oracle也是如此實現的 sql create table t id number 表已建立。sql alter table t ad...