如何从 Postgresql 的 CASE 中更新多个列

问题描述 投票:0回答:1

是否可以在没有多个 CASE 块的情况下解决这个问题?

这是我到目前为止所得到的:我已经为此工作了几个小时,并且不知道如何在不重复 CASE 语句并一次设置一个的情况下做到这一点。这是我得到的:

UPDATE my_table
SET (status, mined_at) = CASE
                             WHEN id <= $1 AND status <> $2 AND status <> $3
                                 THEN ($2, CURRENT_TIMESTAMP)
                             WHEN id > $1
                                 THEN ($4, NULL)
                             ELSE (status, mined_at)
                         END

非常感谢任何帮助。

sql postgresql sql-update case
1个回答
0
投票

您可能应该在 index

 上有一个 
id
,并针对不同 
update
语句中的不同行。

CREATE INDEX ON my_table (id);

UPDATE my_table
SET (status, mined_at) = ($2, CURRENT_TIMESTAMP)
WHERE id <= $1 AND status NOT IN ($2,$3);

UPDATE my_table
SET (status, mined_at) = ($4, NULL)
WHERE id > $1;
  1. 结合起来,它们具有完全相同的结果。
  2. 它们不针对相同的行,因此它们的
    ROW EXCLUSIVE
    不会发生冲突。因此,它们可以并行运行,使它们的总执行时间大约是完成较长部分所需的时间。
  3. 并行运行可能是有意义的,但如果您为此提供的可能状态和参数的数量最终更新了整个表,那么您可能会使用 case
    更好

如果您的情况听起来像上面的第 3 点,您必须修复语法:

UPDATE my_table
SET (status, mined_at)=(CASE WHEN id <= $1 AND status <> $2 AND status <> $3
                                   THEN $2
                               WHEN id > $1
                                   THEN $4
                              ELSE status
                         END,
                         CASE WHEN id <= $1 AND status <> $2 AND status <> $3
                                   THEN CURRENT_TIMESTAMP
                              WHEN id > $1 
                                   THEN NULL
                              ELSE mined_at
                         END);

或者

UPDATE my_table
SET status=CASE WHEN id <= $1 AND status <> $2 AND status <> $3
                    THEN $2
                WHEN id > $1
                    THEN $4
                ELSE status
            END,
    mined_at=CASE WHEN id <= $1 AND status <> $2 AND status <> $3
                      THEN CURRENT_TIMESTAMP
                  WHEN id > $1 
                      THEN NULL
                  ELSE mined_at
              END;

否则你会得到一个错误

ERROR:  source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression
LINE 2: SET (status, mined_at) = CASE
                                 ^
© www.soinside.com 2019 - 2024. All rights reserved.