一尘不染

用联接更新postgres

sql

我正在尝试使用ht的数据更新表tr。两者都有几乎相同的列。因此,为了进行测试,我运行了此查询。

SELECT * FROM tr a
RIGHT OUTER JOIN ht b
USING (date, name, ft )
WHERE ft IS NOT NULL

给出129行检查没问题,然后我将更新查询运行为->

UPDATE tr
SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id) 
    = (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a, 
    a.cd_id)
FROM tr a
RIGHT OUTER JOIN ht b
USING (date, name, ft )
WHERE a.ft IS NOT NULL

查询成功返回:受影响的行数为4134

有人可以指导我哪里出了问题以及如何解决。


阅读 213

收藏
2021-03-08

共1个答案

一尘不染

在Postgres中,这有点复杂。但是,我质疑你的逻辑。似乎aright outer join是不正确的,因为您正在检查第一个表不是NULL。因此,这 似乎 可以捕获您的逻辑:

UPDATE tr
SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id) 
    = (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a, 
    a.cd_id)
FROM tr a JOIN
     ht b
     USING (date, name, ft );

where子句是偶数冗余的,因为该值不能NULL由于join条件。无论如何,这是行不通的,但是它确实指出了正确的解决方案。

在Postgres中,除非您的意图是自我联接,否则表中的表update不能位于FROM子句中。因此,请尝试以下版本:

UPDATE tr
SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id) 
    = (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a, 
    a.cd_id)
FROM tr a JOIN
     ht b
     USING (date, name, ft )
WHERE tr.date = a.date and tr.name = a.name and tr.ft = a.ft;

但是,此更新没有意义。我怀疑您希望值匹配时来自ht不是 tr。如果是这样,这是最简单的方法:

UPDATE tr
    SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id) 
        = (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a, 
        a.cd_id)
    FROM ht a
    WHERE tr.date = a.date and tr.name = a.name and tr.ft = a.ft;
2021-03-08