2012-08-28 73 views
6

我已經和bar一個多到多間foofoo_idbar_id建模爲表foo_bar轉換一個多到許多關係到一個一對多PostgreSQL中

我現在想把它建模爲一對多(我的數據允許)。

我已將foo_id列添加到bar但現在我想遷移我的數據。所以,我想

UPDATE bar SET foo_id = f where id = b; 

每個fb對從

SELECT foo_id AS f, bar_id AS b FROM foo_bar; 

未來是否有可能做到這一點的SQL(特別的PostgreSQL 9.0)?

我知道如何在只有一個值的情況下在UPDATE中執行子SELECT,但在這種情況下難以做到。

回答

5
UPDATE bar b 
SET foo_id = fb.foo_id 
FROM foo_bar fb 
WHERE fb.bar_id = b.bar_id; 

如果您有一個bar多行(你不應該,根據你的描述)的一個行將被多次更新,其結果是任意的。

這種形式的查詢一般比相關的子查詢執行得更好。

請注意,bar的主鍵真的應該命名爲bar_id - 我在查詢中使用該名稱。

+0

應該最後一行fb.bar_id = b.id? –

+0

@JamesTauber:不可以。模型中不應該有'id'。使用非描述性列名「id」是反模式。主鍵應該命名爲'bar_id'。 –

+0

足夠公平,只是將它映射到我的問題的具體細節 –

2

如果你確實有一對多的關係,那麼你在給定的酒吧裏拿哪個foo值是沒有關係的 - 只有一個值或者它們都是一樣的。

你可以做到以下幾點:

update bar 
    set foo_id = (select max(foo_id) from foo_bar where foo_bar.bar_id = bar.id) 

子查詢將結果限制爲單個值。

3

,您仍然可以連接表中UPDATE語句,嘗試

UPDATE bar a 
SET  foo_id = c.foo_id 
FROM (
      SELECT foo_id, bar_id 
      FROM foo_bar 
     ) c 
WHERE a.id = c.bar_id 

或僅僅作爲

​​
+0

SET'不接受符合表格限定的列名稱。 –

+0

@ErwinBrandstetter實際上沒有經過測試。 postgre足夠嚴格嗎?嘿,所以在這種情況下,我應該重寫它'SET foo_id = c.foo_id'?「 –

+0

準確地說:'SET foo_id = c.foo_id',就像在我的答案中。我引用手冊[here](http:// www.postgresql.org/docs/current/interactive/sql-update.html):「不要在目標列的規範中包含表名 - 例如,UPDATE選項卡SET tab.col = 1無效。」 –