我對FOREIGN KEY和CHECK約束之間的區別感到困惑 - 他們似乎達到了相同的結果。檢查和外鍵有什麼區別?
我的意思是我可以創建一個表並在另一個表上強制執行一個外鍵,但是我可以創建一個CHECK來確保另一個表中的值。
有什麼區別以及何時使用這個或那個?
我對FOREIGN KEY和CHECK約束之間的區別感到困惑 - 他們似乎達到了相同的結果。檢查和外鍵有什麼區別?
我的意思是我可以創建一個表並在另一個表上強制執行一個外鍵,但是我可以創建一個CHECK來確保另一個表中的值。
有什麼區別以及何時使用這個或那個?
一個外鍵約束確保項不存在
編輯 另一個表
按照正確的註釋存在於另一個表...或相同的表。 - Mark Byers
CHECK約束確保條目遵循一些規則。
CHECK約束通過限制由列接受的值執行域的完整性。它們與FOREIGN KEY約束類似,它們控制放在列中的值。 區別在於它們如何確定哪些值是有效的:FOREIGN KEY約束從另一個表中獲取有效值的列表,並且CHECK約束根據不基於另一列中的數據的邏輯表達式確定有效值。
外鍵約束比CHECK約束更強大。
外鍵約束意味着列(在當前表中)只能具有已存在於外表列中的值(可能包括相同的表,通常是爲分層數據完成的)。這意味着隨着值列表的變化 - 變大或變小 - 不需要更新約束。
檢查約束不能引用當前表之外的任何列,也不能包含子查詢。通常,這些值是硬編碼的,如BETWEEN 100 and 999
或IN (1, 2, 3)
。這意味着隨着情況的變化,您必須每次更新CHECK約束。此外,外鍵關係在實體關係圖(ERD)上可見,而CHECK約束永遠不會。好處是有人可以讀取ERD並從中構建查詢,而無需使用大量的DESC表命令來知道哪些列是哪裏以及哪些與構建適當的連接有關。
最佳做法是首先使用外鍵(和支持表)。使用CHECK約束作爲不能使用外鍵的情況的備份,而不是驗證數據的主要解決方案。
外鍵不必是單列鍵。 – 2010-04-11 18:04:04
它取決於您的DBMS(您沒有指定),但從某種意義上說,您是正確的:外鍵約束是檢查約束的特定情況。有數據庫管理系統不允許你制定一個外鍵約束作爲檢查約束。
檢查約束的主要目的是描述適用於表中單個行的條件。例如,我有一張元素表(如氫,氦,...),並且元素的符號被限制爲以大寫字母開頭,並且後面跟着零個,一個或兩個小寫字母(兩個小寫字母,但尚未被發現但預測的元素:Uus - ununseptium(117) ,它剛剛被隔離但尚未命名)。這可以是一個CHECK約束的主題:
CHECK(Symbol MATCHES "[A-Z][a-z]{0,2}")
假設MATCHES存在並支持適當的正則表達式語言。
你也可以有一個比較值的檢查約束:
CHECK(OrderDate <= ShipDate OR ShipDate IS NULL)
爲了表達一個外鍵約束的檢查約束,你要允許CHECK子句中執行查詢。假設:
CHECK(EXISTS(SELECT * FROM SomeTable AS s
WHERE ThisTable.pk_col1 = s.pk_col1 AND
ThisTable.pk_col2 = s.pk_col2))
此示例顯示了一些問題。我沒有一個方便的表格別名,用於編寫檢查約束的表格 - 我認爲它是'ThisTable'。構造是冗長的。假設在SomeTable主鍵的列pk_col1
和pk_col2
聲明,那麼外鍵子句是更加緊湊:
FOREIGN KEY (pk_col1, pk_col2) REFERENCES SomeTable
或者,如果你引用一個替代鍵,而不是主鍵:
FOREIGN KEY (pk_col1, pk_col2) REFERENCES SomeTable(ak_col1, ak_col2)
這在命名上更加緊湊 - 因此出錯的可能性更小 - 並且可以由服務器進行特殊配置,因爲特殊符號意味着它知道它正在處理外鍵約束,而通用檢查子句必須仔細檢查,看它是否符合許多可能的形式之一相當於外鍵。
問題問:何時使用檢查約束以及何時使用外鍵約束?
存在於另一張桌子......或同一張桌子上。 – 2010-04-11 17:29:19
CHECK約束確定不基於另一列中的數據的...。 不太正確,檢查約束可以包含多列(至少10g)。更好的是說「不是基於另一個表中的數據」。 – Juraj 2010-04-19 20:43:38