使用许多常见的子表达式进行更新

时间:2019-02-22 10:42:37

标签: postgresql sql-update database-performance code-maintainability

计算表的最佳方法是从同一表中的其他列中计算出许多列,并且公式以复杂的方式彼此建立。

如果您不关心性能,则可以简单地使用其自己的update语句计算每一列:

update x set b1 = a1 + a2;
update x set b2 = a3 * b1;
update x set b3 = a4 * b2;
...

或者,如果您手动展开公式,则可以在一次更新中完成所有操作:

update x set
  b1 = a1 + a2,
  b2 = a3 * (a1 + a2),
  b3 = a4 * (a3 * (a1 + a2));

这里的问题是这些公式会变得庞大且难以更改和调试。

Postgres(甚至可能是一般的SQL)中是否有某种方法可以使您在这些情况下既具有性能又具有可维护性?

这是我希望可以做的事情:

update x set
  b1 = _b1,
  b2 = _b2,
  b3 = _b3
with
  _b1 = a1 + a2,
  _b2 = a3 * _b1,
  _b3 = a4 * _b2;

我有一个可行的解决方案,其中公式是在具有多个返回值的函数中定义的,但是在其他方式上这不太灵活,因此我正在寻找替代方案。

2 个答案:

答案 0 :(得分:0)

您可以在最新的PostgreSQL版本中使用以下内容:

UPDATE atable
SET (col1, col2, col3) =
SELECT expr1, expr2, expr3
FROM ...

如果需要在查询中重用计算所得的表达式,则可以使用WITH

WITH t1(x1) AS (
   SELECT /* complicated */
), t2(x2) AS (
   SELECT /* complicated using t1 */
) ...
SELECT /* final results */

我不确定这是否会使代码更易读,但避免使用函数且符合标准(我认为没有检查)。

答案 1 :(得分:0)

我想出了与我想要的东西相近的东西:

update x set (b1, b2, b3) = ((
  select b1, b2, b3
  from (select b1, b2, a4 * b2 as b3
  from (select b1, a3 * b1 as b2
  from (select a1 + a2 as b1
  ) as _) as _) as _
));

它仍然比我想要的更为冗长,但是基本上达到了无需使用函数就无需扩展公式的目的。