2009-02-06 147 views
0

爲什麼SQL標準接受這個?哪些好處?爲什麼這種外鍵可能?

如果有這些表:

create table prova_a (a number, b number); 
alter table prova_a add primary key (a,b); 
create table prova_b (a number, b number); 
alter table prova_b add foreign key (a,b) references prova_a(a,b) ; 
insert into prova_a values (1,2); 

你可以沒有錯誤插入此:

insert into prova_b values (123,null); 
insert into prova_b values (null,123); 

注1:這來源於此answer

注2:這可以避免,兩列設置不爲空。

備註:我不是在問關於避免,我關心哪些是好處。

參考文獻:

  • Oracle documentation關係模型允許外鍵的值要匹配被引用的主鍵或唯一鍵的值,或爲null。如果組合外鍵的任何列爲空,則該鍵的非空部分不必匹配父鍵的任何對應部分。

  • SQL Server documentationFOREIGN KEY約束可以包含空值;但是,如果複合FOREIGN KEY約束的任何列包含空值,則會跳過組成FOREIGN KEY約束的所有值的驗證。

回答

4

我知道某些DBMS只是當它涉及到與外鍵約束外鍵並不強制參照完整性。 SQLite浮現在腦海。這是談到here

其他數據庫管理系統是不同的,我知道如果你嘗試類似的東西,MS SQL服務器會投訴。

SQLite有其用途,但它並不意味着在高併發情況下使用。如果您在不同的DBMS中看到此行爲,請檢查他們的文檔以查看他們是否做了類似的事情。但大多數應該是強制執行完整性。

+0

MSSQL允許這... – FerranB 2009-02-06 09:04:18

+0

我想我並不明確,當我說,「當涉及到外鍵」。我的意思是存在外鍵約束。 SQLite解析,但不強制約束。 – colithium 2009-02-06 11:17:15

0

SQL標準不接受這個;你已經找到了一個不強制引用完整性的DBMS。卸載它現在如果你很聰明。至少,不要將其用於生產目的。

早期的SQL標準(SQL86)沒有參照完整性,SQL89級別2修復了這個問題。

2

至少可以使用合理標準的RDBMS來開展您的DEV工作,即使您正在使用SQLite(這是一個優秀的數據庫 - 它運行在您的Ipod touch中)來執行您的生產系統!它將清除所有這些錯誤 - 像Lint真的。如果你使用SQL Server Express運行你的代碼,你可以免費下載,你會得到很多錯誤,比如......

Msg 8111, Level 16, State 1, Line 2 
Cannot define PRIMARY KEY constraint on nullable column in table 'prova_a'. 
Msg 1750, Level 16, State 0, Line 2 
Could not create constraint. See previous errors. 
0

嘗試增加此聲明:

ALTER TABLE prova_b添加主鍵(A,B);

這將禁止NULLS在prova_b中。它也會禁止重複輸入。在Oracle和SQL服務器中,它也會創建一個索引。這個索引將加速查找和連接,代價是減慢插入一點點。

這是你想要做的嗎?

至於爲什麼標準SQL讓你做一些你認爲很愚蠢的事情,那是一個哲學問題。大多數工具允許一些愚蠢的選擇。試圖禁止所有愚蠢選擇的工具通常最終會無意中禁止一些真正聰明的選擇。

1

Oracle和SQL Server都允許NULL外鍵,並且很容易理解爲什麼這是必需的。 想象一棵樹,例如,每一行都有一個引用同一個表的主鍵的父鍵。樹中必須有一個沒有父節點的根節點,並且父鍵將爲空。 一個更具體的例子:想想員工和經理。公司中的一些人,如果只是首席執行官,則不會有經理。如果不能將員工表上的經理ID設置爲NULL,則必須創建一個「無經理」員工 - 這是錯誤的,因爲它沒有真實的對應關係。

現在我們知道了這一點,這很明顯,爲什麼你的複合鍵的行爲就像他們一樣。邏輯上,如果組合的一部分爲NULL,則整個密鑰爲空。如果其中一個塊爲NULL,則字符串連接會返回NULL。無法匹配,並且在這些情況下不會強制約束。

相關問題