Postgres更新了3个表的内连接?

时间:2012-09-26 12:51:21

标签: sql postgresql sql-update inner-join

今天早上我问this非常相似的问题,答案很精彩。

然而,在审阅了该剧之后,我发现我的实际问题是稍微比我在该问题中描述的更复杂。基本上,我有3个Postgres表:

[myschema].[animals]
--------------------
animal_id
animal_attrib_type_id (foreign key to [myschema].[animal_attrib_types])
animal_attrib_value_id (foreign key to [myschema].[animal_attrib_values])

[myschema].[animal_attrib_types]
--------------------------------
animal_attrib_type_id
animal_attrib_type_name

[myschema].[animal_attrib_values]
--------------------------------
animal_attrib_value_id
animal_attrib_value_name

所以,我可能会有animal这样的记录:

[myschema].[animals]
--------------------
animal_id = 458
animal_attrib_type_id = 38
animal_attrib_value_id = 23

相应的animal_attrib_type(id = 38)具有以下值:

[myschema].[animal_attrib_types]
--------------------------------
animal_attrib_type_id = 38
animal_attrib_type_name = 'animals.should-make-noise'

相应的animal_attrib_value(id = 23)具有以下值:

[myschema].[animal_attrib_values]
--------------------------------
animal_attrib_type_id = 23
animal_attrib_type_name = 'true'

因此,相同的animal记录可以有多个类型/值对。在这种情况下,动物的animal_attrib_type_nameanimals.should-make-noise”对应animal_attrib_value_nametrue”。

在运行时,我只有animal_id(即458)和animal_attrib_type_id(即38)。我需要能够仅查找与给定animal_attrib_value_nameanimal_id相对应的animal_attrib_type_id相应的{{1}},然后将其值更新为某些静态文本('true'或'false') ;所有这些都来自同一个UPDATE语句。

上面提到的问题的答案对于我说的问题是正确的,但由于同一个动物有0 +类型/值组合,我实际上需要一个稍微不同的SQL语句。提前谢谢!

2 个答案:

答案 0 :(得分:7)

利用FROM clause in the PostgreSQL UPDATE command。这通常更清洁,更快。

UPDATE animal_attrib_values av
SET    animal_attrib_value_name = 'true'
FROM   animals a 
WHERE  a.animal_id = 458 
AND    a.animal_attrib_type_id  = 38
AND    a.animal_attrib_value_id = av.animal_attrib_value_id;

由于我们已经知道animal_attrib_type_id,因此我们根本不需要包含第三个表animal_attrib_types。如果需要,我们可以另外加入......

此外,请勿对SET中的UPDATE项进行表格限定。这是一个语法错误。我引用manual on said page

  

不要在目标规范中包含表的名称   列 - 例如,UPDATE tab SET tab.col = 1 无效

大胆强调我的。

答案 1 :(得分:1)

以下SQL应该按照您的要求执行:

UPDATE animal_attrib_values aav
SET animal_attrib_value_name= 'true'
WHERE aav.animal_attrib_value_id = (
    SELECT a.animal_attrib_value_id 
    FROM animals a 
    WHERE a.animal_id = 458 
        AND a.animal_attrib_type_id  = 38
)
;