2012-08-28 43 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无效。” –