2016-02-01 39 views
1

假設我們有作業的表像這樣:將外鍵綁定到非主鍵時是否有任何缺點?

  • 作業(ID,數量);

假設我們有一個客戶的要求來跟蹤工作時間,我們創建了一個表像這樣:

  • (A)job_timer(ID,JOB_ID,時間戳);

,但我們有我們要如何把它綁job表的選擇,所以我們也可以:

  • (B)job_timer(ID,job_number,時間戳);

假設job_number是UNIQUE

我條件反射地使基於ID的外鍵,所以A)job_id是我見過它做的方式。但是,客戶正在按職位編號查找職位,如果我直接通過B)job_number進行查詢,它可以爲我和數據庫節省一些工作量。但我應該這樣做嗎?

通過更多的工作使用job_id我的意思時,即給定的作業數量,我只需要使用job_timer表。當給出job_id我需要配合這兩個表 - 更多的認知編程工作,更多的數據庫工作。

請注意,類似的問題Foreign Key to non-primary key解決了非主鍵的唯一性問題,但我不認爲它解決了我的問題。

原始表(job)是遺留代碼庫的一部分,其中字段idnumber在整個代碼中廣泛使用,從這個意義上說,我有一個「拆分主鍵」條件。由於缺乏全面的測試覆蓋率,除去這一點將會令人望而卻步。爲什麼number字段被創建,並且爲什麼它被作爲varchar是很好的問題。我確信在某個時刻一定有一個理由。

我正在尋找類似「是的,繼續它完全好,有在這種情況下沒有最佳實踐」,或「沒有,如果你這樣做,你可能會遇到的問題,X,Y,Z在將來」。

+0

噢,對了......多個匹配的父母ID將會模棱兩可......我應該趕上睡眠。 –

+4

如果'job'表中的'number'是唯一的,那麼你應該使_that_主鍵完全擺脫'id'列(因爲它顯然不會爲表添加任何值)。這意味着工作號碼也永遠不會改變。 –

+0

@ horse:很好! 'id'字段是多餘的... – Dennis

回答

1

TL; DR始終聲明一個FOREIGN KEY約束(鏈)當用於列的列表中的值必須作爲用於PRIMARY KEYUNIQUE NOT NULL列另一個列表中的值。但是,如果有多個CK,選擇哪個CK(候選鍵)作爲FK(外鍵)參考最終是實用的。該標準基本上是用於選擇PK(主鍵)的標準,因爲將CK區分爲PK最終在FK中優選使用。典型的列表是familiarity, irreducibility, stability & simplicity。這裏過去的使用表明CK或者​​是合理的。雖然考慮number是隻對最終輸出儘管存在&獨特的id說明其varcharness和它的獨特性。如果您包含兩者,請注意在對上聲明FOREIGN KEY可能是適當的。 (要求在job中增加UNIQUE NOT NULL。)


superkey是一組唯一不爲空的列。 CK是一個超級密鑰,不包含更小的超級密鑰。一個表可以有任意數量的CK。 PK是一個傑出的CK。

當表中某個子行的值也是某個引用表中的某個superkey子行的值時,我們可以說「外部超級鍵」成立。如果超級鍵是CK,那麼外鍵超級鍵是FK。我們告訴DBMS關於CK和外國超級用戶的信息,這樣可以防止無效的數據庫狀態。

SQL UNIQUE NOT NULL實際上聲明瞭一個超級鍵。所以SQL PRIMARY KEY實際上聲明瞭一個卓越的超級密鑰。如果superkey是CK,那麼它是PK。 SQL FOREIGN KEY實際上聲明瞭一個外鍵。如果引用的超級密鑰是CK,則是FK。

你的表格與「拆分PK」只是一張有兩個CK的表格。 (這形成超級密鑰,因爲CK的所有超集都是超級密鑰。)就限制性聲明而言,首要性是無關緊要的。您應該聲明約束條件,以便DBMS可以執行它們。

要知道,如果你有一個表idnumber爲FKS那麼很可能對值必須出現在job。如果是這樣,那麼通過FOREIGN KEY宣佈這對貨幣爲外國超級貨幣。當存在自然鍵時,這種添加外國超級密鑰的需求是具有代理鍵的缺點。另一方面,只要有多個CK,就會出現這種情況。

PS獨特列集合的任何超集都是唯一的。但是SQL需要你聲明FK的目標爲UNIQUE NOT NULL,即使它必須已經是唯一的,通過包含一些聲明爲唯一的較小集合。所以當有id-number對,其中對必須出現在job中時,您應該聲明覆合FK和複合超級密鑰。 PPS所有這些聲明的要點是完整性,而不是索引進行優化。 (雖然這也很重要。)

+0

謝謝。關於在* pair *上聲明UNIQUE的問題。沒有索引工作的方式,如果我做UNIQUE(id,number),然後我只查找'number',索引不會被使用?我的印象是,這樣的索引僅用於僅查找「id」或同時查找「id」,「number」。但是當僅查找「數字」時,該索引未被使用。我看不出在配對上如何聲明UNIQUE比分別在'id'上聲明'id'和UNIQUE上的UNIQUE更好。目前的代碼只對id或number進行很多查找,但不能同時進行查找。你會提出什麼建議? – Dennis

+1

你說得對,唯一性和多餘的索引是多餘的。但是SQL只需要將每個FK目標列設置爲UNIQUE NOT NULL。查看我答案的最後一段。另見我編輯的第一句話。 – philipxy

+1

我相信很多SQL實現會自動爲主鍵創建索引,但不一定適用於其他CK,即使它們被某些FK引用。所以可能有FK提到的CK沒有索引可用,這會在某些時候損害性能。 (這裏的關鍵是「缺點」是由於沒有索引,而不是所引用的密鑰是「次要」的事實。) –