2010-04-20 81 views
1

爲了說明問題,我讓一個例子:唯一約束(W/O觸發)上的「一到多」關係

甲tag_bundle由一個或一個以上的標記。 獨特的標籤組合可以映射到唯一的標籤塊,反之亦然。

tag_bundle     tag   tag_bundle_relation 
+---------------+  +--------+  +---------------+--------+ 
| tag_bundle_id |  | tag_id |  | tag_bundle_id | tag_id | 
+---------------+  +--------+  +---------------+--------+ 
|  1  |  | 100 |  |  1  | 100 | 
+---------------+  +--------+  +---------------+--------+ 
|  2  |  | 101 |  |  1  | 101 | 
+---------------+  +--------+  +---------------+--------+ 
          | 102 |  |  2  | 101 | 
          +--------+  +---------------+--------+ 
              |  2  | 102 | 
              +---------------+--------+ 

不能有具有正好從標籤100和標籤相同的組合101 不能有具有正好從標籤101和標籤102

同一組合的另一tag_bundle另一個tag_bundle如何確保執行SQL 「同時」時的這種唯一約束! 就是防止同時將兩束具有完全相同相同標籤組合

添加任何表不起作用簡單的唯一約束, 難道還有比觸發或顯式鎖以外的任何解決方案。

我只想到了這樣一種簡單的方法:將標記組合變成字符串,並讓它成爲一個獨特的列。

tag_bundle (unique on tags)   tag   tag_bundle_relation 
+---------------+-----------+  +--------+  +---------------+--------+ 
| tag_bundle_id | tags  |  | tag_id |  | tag_bundle_id | tag_id | 
+---------------+-----------+  +--------+  +---------------+--------+ 
|  1  | "100,101" |  | 101 |  |  1  | 101 | 
+---------------+-----------+  +--------+  +---------------+--------+ 
            | 100 |  |  1  | 100 | 
            +--------+  +---------------+--------+ 

但它似乎不是一個好辦法:(

+0

您是否希望允許tab_id參與多個捆綁包?例如,'tag_bundle_id = 2'有'tags =(100,200)'?超級集合/子集怎麼樣,'tag_bundle_id = 3是否有標籤(100,101,102)'? – 2010-04-20 21:44:19

+0

tag_bundle_id = 2允許標籤=(100,200), tag_bundle_id = 3允許標籤(100,101,102)。 – elgcom 2010-04-20 21:53:31

+0

那麼,是或否的子集? – MkV 2010-04-20 23:52:49

回答

1

爲什麼的「沒有觸發器」約束?有了它,帶着幾分重複數據的結合,你可以得到你所需要的。更改解決方案中的'標籤'字段到INTEGER的數組字段(或任何類型的tag_id)

雖然認識到解決方案的不愉快性,但我沒有看到它的方法,儘管我會使用數組而不是'tags'的字符串,將其放在與tag_bundle分開的表中,仍然使其唯一併在tag_bundle_relation上放置一個觸發器,以使用array_agg(t ag_id)(> 8.4),如果失敗,觸發器更新失敗。

-1

爲了在多個事務更新表格時正常工作,您需要創建一個可拒絕的,最初推遲的constraint trigger

+1

糾正我,如果我錯了,但 - 除非您序列化函數調用 - 觸發器不會保存您的競爭條件,因爲並行執行的其他事務所做的更改不可見。 *延遲*約束觸發器*減少了競爭條件的機會窗口,但仍有可能兩個此類觸發器並行運行,而不會看到彼此的(尚未完成的)數據。 – intgr 2010-04-21 14:23:52

+0

@intgr優秀的問題。我不知道答案。我推測提交事務是序列化的,因此觸發器函數的處理也是推遲到事務提交時進行的。或許需要序列化隔離級別來保證這一點。如果決定是否允許更新取決於其他併發事務是提交還是回滾,那麼需要首先完成其他提交或回滾以及其延遲觸發器。 – 2010-04-21 22:44:50