2009-07-27 58 views
0

假設我有一張主表a_id和外鍵b_id確保主鍵和外鍵永不交叉的最佳方法是什麼?

a_idb_id從不相交是重要的,即不應該存在a_id = b_id的情況。

什麼是最好的實施方式?我可以以某種方式在數據庫端(mySql)執行此操作,還是應該通過編程來確保這一點?如果我以編程方式確保這一點,爲主鍵插入數字(而不是讓數據庫自動增量)是不好的做法嗎?我假設我只是創建一個例程來檢查最新的主鍵並簡單地增加它(並且我還需要確保a_id的範圍從不與b_id的範圍相交)。有什麼建議麼?

+0

通常,外鍵必須與相應的主鍵相匹配; A和B的交集必須等於B(儘管A中可能有條目而B中沒有匹配的條目)。那麼,你的意思是主鍵和外鍵不相交?爲什麼? – 2009-07-27 23:57:29

回答

2

您可以創建另一個具有自動增量字段的表。插入記錄後,它將插入到「密鑰表」中並在那裏使用引用的值。所以如果你在一個表中有兩個全局唯一的鍵,每個插入將是兩個關鍵的插入。這個解決方案也可以擴展到2以上。我不得不問:爲什麼?

1

在Oracle中,您可以使用sequence實現此行爲,該行爲用於將id分配給兩個表中的行。每張表在INSERT上都會有一個觸發器,其中id將從序列中的下一個數字開始設置。

1

您可以設置AUTO_INCREMENT值,以便一個表格只有奇數,而另一個表格只有平均值。

這很可能是非常高效的,但它不會爲使用另一個唯一密鑰添加第3個表格留出餘地。

我不是100%確定MySQL的,但用Oracle你可以定義一個序列,然後簡單地使用相同的序列來選擇所有的值,這可能是最好的選擇(如果它可用於MySQL )。

+0

如果`b_id`是一個父ID並引用`a_id`作爲超集,這將不起作用。 – Eric 2009-07-27 23:33:08

+0

也許我誤解了這個問題,但是我沒有看到任何說他希望b_id成爲a_id子集的內容。如果是這樣,那麼你是正確的。但是,如果他們使用序列,就會出現同樣的缺陷,正如其他一些答案中所建議的那樣。 – 2009-07-27 23:37:16

0

實現此目的的最簡單方法是使用CHECK約束。不幸的是,MySQL是MySQL,它不支持CHECK

爲了在MySQL中達到相同的效果,您需要創建一個BEFORE INSERT和一個BEFORE UPDATE觸發器,以確保兩個值都有效。 FK本身負責確保關係有效。這裏有一個例子:

CREATE TRIGGER upd_check BEFORE UPDATE ON sometable 
FOR EACH ROW 
BEGIN 
    IF NEW.a_id = NEW.b_id THEN 
     call ERROR_SELFREFERENCING_ID(); 
    END IF; 
END; 

關於MySQL觸發器的詳細信息MySQL手冊中提供:

18.3.1: Trigger Syntax

編輯:的MySQL目前不支持RAISESIGNAL在他們的觸發器,所以我不得不求助於調用一個不存在的程序ERROR_SELFREFERENCING_ID()它失敗。這將導致INSERTUPDATE失敗,如果a_id = b_id,幾乎相同的方式,如果你將設置一個無效b_id

0

您可以使用GUID(UUID)作爲唯一鍵。

我已經在幾個項目中使用過它,它對於唯一性很好,但它對索引性能並不是最好的。