使用WITH和CASE进行UPDATE - PostgreSQL

53

我试图将一列的值更改为从其他两个表中的信息构建的标题,但是我在获取数据时遇到了麻烦。我目前想在表中的所有条目上执行此查询。我在CASE上遇到语法错误,但我无法弄清楚原因。

UPDATE campaigns AS cmp
    SET name = (
        WITH ptn AS (SELECT first_name, last_name FROM politicians WHERE id = cmp.politician_id),
            rc AS (SELECT office FROM races WHERE id = cmp.race_id)

        CASE
            WHEN rc.office IS NULL OR rc.office = '' THEN ptn.first_name || ' ' || ptn.last_name
            ELSE ptn.first_name || ' ' || ptn.last_name || ' for ' || rc.office
        END
    )

这是PostGres 9.4。以下是我遇到的错误信息:

ERROR:  syntax error at or near "case"
LINE 5:   case
          ^

********** Error **********

ERROR: syntax error at or near "case"
SQL state: 42601
Character: 189

将错误添加到帖子中。 - cfatt10
请编辑您的问题并注明您的确切postgresql版本标签。请阅读帮助中心关于提问的内容。 - philipxy
我认为CTE必须存在于update语句之前,而不是像你现在这样放在中间。 - xQbert
@xQbert,我刚刚尝试了你的建议,不幸的是它没有起作用。我发现这个建议,说我的语法可能会起作用。https://dev59.com/gW445IYBdhLWcg3wfKcZ - cfatt10
2个回答

77

语法错误是因为你的相关子查询无效。在这两个公共表达式之后,需要有一些select语句:

公共表达式的基本结构如下:

with ptn as (...),
  rc as (...)
select --<< you are missing this select here

但我认为整个事情可以更简短、更有效率地写出来(如果我没有弄错的话)

UPDATE campaigns AS cmp
    SET name = CASE
                 WHEN rc.office IS NULL OR rc.office = '' THEN ptn.first_name || ' ' || ptn.last_name
                ELSE ptn.first_name || ' ' || ptn.last_name || ' for ' || rc.office
              END
from politicians ptn, races rc 
where ptn.id = cmp.politician_id
  and rc.id = cmp.race_id

22

我倾向于使用 from 子句来完成这个任务:

UPDATE campaigns AS cmp
    SET name = (CASE WHEN rc.office IS NULL OR rc.office = ''
                     THEN ptn.first_name || ' ' || ptn.last_name
                     ELSE ptn.first_name || ' ' || ptn.last_name || ' for ' || rc.office
                END)
    FROM politicians ptn, races rc
    WHERE ptn.id = cmp.politician_id and rc.id = cmp.race_id ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接