2013-03-27 26 views
1

由於我可以在不使用關係鍵(主鍵和外鍵)的情況下連接兩個表,因此首先定義這些鍵的目的是什麼?如果我可以加入而不定義它們,主鍵和foriegn鍵的用途是什麼?

例如,我的第一個表是

customer table 
fields are cust_id, lastname, firstname 

和我的第二個表是

product table 
fields are product_id, productno, cust_id 

即使我沒有宣佈任何領域,如原發性或foriegn鍵,我仍然可以加入兩個表格:

SELECT * 
FROM customer c 
LEFT OUTER JOIN product p ON p.custid=c.cust_id 

爲什麼我應該定義鍵?

+0

http://en.wikipedia.org/wiki/Referential_integrity – 2013-03-27 20:26:56

+0

它的用途是讓數據庫在任何時候都可以幫助您,而無需您自行完成整個過程。 – Randy 2013-03-27 20:27:38

+0

請***停止***問一遍又一遍的同一個問題! http://stackoverflow.com/questions/15668323/what-is-the-need-of-primary-and-foreign-key-in-joining-two-tables – 2013-03-27 20:43:23

回答

4

已經有一些很好的答案,讓我推斷一點點。如「dasblinkenlight」所述,檢索速度(數據庫預先知道兩個表之間的關係並可能優化查詢),更重要的是,參考/數據完整性。

讓我們再討論第二個問題。

考慮一個簡單的場景,你有以下三個表(我簡化了這個在現實中,你必須訂購許多產品的能力,但我只會簡單說明簡潔。):

CustomerTable 
    ID 
    FirstName 
    LastName 


OrderTable 
    ID 
    CustomerID 
    ProductID  

ProductTable 
    ID 
    Description 

沒有外鍵,我們可以自由能:

  • 創建訂單沒有產品
  • 沒有客戶創建訂單
  • 刪除銅有訂單
  • 有產品 等刪除訂單stomers ...

這是災難

配方使用外鍵,我們就可以重新設計上面,正是如此:

CustomerTable 
    ID 
    FirstName 
    LastName 


OrderTable 
    ID 
    CustomerID -> References CustomerTable.ID 
    ProductID -> References ProductTable.ID 

ProductTable 
    ID 
    Description 

我們可以指定CustomerID和ProductID是「NOT NULL」(就像其他列一樣)。這意味着要創建一個訂單,我們有一個現有的客戶和現有的產品。優秀!

但它變得更好。如果我開始刪除產品會發生什麼?除非我們已經指定了一些級聯選項(參見this),否則數據庫將拋出一個搖擺不定的問題並說「不,你不能刪除它,它被某個東西引用」。

這是數據的完整性等式的一部分。我們不能指向那些不存在的東西(外鍵堅持說我們將它指向任何東西(如果允許爲null),或者其他東西),主鍵幫助我們完成這個任務。

突然之間,數據庫本身正在確保一切運行良好並且很好地結合在一起。沒有它,你可以刪除所有的命令...刪除產品...刪除你想要的東西,然後你的應用程序會想知道到底發生了什麼。

使用它們:)

1

答案簡短,數據完整。

同樣使用這樣的外鍵可以確保搜索發生的更快,因爲更多的數據輸入到表中。

+0

並非總是如此 - 例如,SQL Server不會自動在外鍵上添加索引,因此您仍然需要添加該索引以獲得查詢優勢。 – zimdanen 2013-03-27 20:34:35

3

背後告訴你的RDBMS,這兩個鍵是相關的

  • 加快檢索的原因有兩個 - RDBMS可能增加隱含索引,以加快加入在聲明初級到外鍵關係
  • 處理參照完整性 - RDBMS可以對刪除主鍵進行檢查,以查看是否刪除從「子」記錄引用的行,並且可以刪除子記錄或引發錯誤。你的RDBMS也會告訴你,如果你嘗試插入一個帶有在父表中沒有匹配主鍵的外鍵的記錄。

除此之外,可以以類似的方式使用密鑰和非密鑰字段。特別是,加入未聲明爲主鍵或外鍵的列當然是正確的。

3

這不是關於「能夠加入」這是關於什麼是允許進入表。另外,如果刪除客戶,會發生什麼情況,但數據庫中有優秀的產品?如果沒有外鍵,它們就是所謂的孤兒記錄。默認情況下,添加外鍵可防止您刪除子表引用的對象。

0

連接僅用於「公共變量」,因此可以使用連接將兩個表中彼此相等的值連接起來。主鍵必須是唯一的,因此您始終可以引用它們,因此您也可以將它們用作其他表格的參考。基本上,當你從2個表中進行查詢時,發生的事情就是笛卡爾積。 (這在實際實施中並未發生,因爲時間是一個因素),這會產生大量數據,但連接會減少結果中的數據(理論上)。 你可以閱讀更多的在這裏加入:

http://www.w3schools.com/sql/sql_join.asp

2

這些概念都是有關約束的。

PRIMARY KEY是一個約束,指示一組列是唯一的而不是NULL。大多數實現使用索引來支持這一點,並且在某些實現中,主鍵也是用於對磁盤存儲中頁面中的數據進行排序的集羣索引。

A FOREIGN KEY是一個約束條件,指示一組列引用另一個表中的另一組列。一般來說,外鍵仍然可以是NULL,但如果它不是NULL,那麼它必須是它引用的表中的有效鍵,並且也必須是唯一的。它所引用的關鍵字不一定是PRIMARY KEY,只是一個唯一的關鍵字(數據庫通常從一個約束如獨特的約束或索引來確定它)。外鍵本身不一定要有索引,但這通常是一個好主意,因爲除去引用的表中的行需要在允許刪除之前檢查所有外鍵。這些都屬於參照完整性的概念。

一般來說,數據庫的所有約束都可以保護數據的完整性,並且還可以讓優化器理解侷限性並獲得有關最佳執行計劃的更多線索。但是,可以簡單地在表上具有適當的唯一索引,並且仍然獲得相同的執行計劃,而不將索引作爲主鍵的一部分或作爲定義外鍵引用的先導,但索引是獨特一定會影響計劃的選擇。

有很多事情在查詢(DML)允許,但DDL聲明數據的結構

+0

不幸的是,由於向後兼容性問題,SQLite *確實允許空主鍵:( – 2013-03-27 20:56:47

+0

@ Moo-Juice是的,跨越ANSI定義所說的東西和不同的實現所做的事情是痛苦的,例如SQL Server允許一個'PRIMARY KEY **和**一個獨立定義的聚集索引,MySQL不允許你有一個'PRIMARY KEY'和一個單獨的聚集索引。Teradata有一個關鍵邏輯模型的概念,但並不關心它與它的相比'PRIMARY INDEX'的概念,它用於在放大器之間進行數據分配。當然ANSI對於索引根本沒有什麼可說的 - 但是它確實指出'PRIMARY KEY'不能爲空, *嘆* – 2013-03-27 21:10:37

相關問題