【问题标题】:postgresql update multiple tables in single querypostgresql 在单个查询中更新多个表
【发布时间】:2015-04-27 14:15:41
【问题描述】:

我有两张表如下:

  1. serial_table

    id CHARACTER VARYING(20),
    serial_key CHARACTER VARYING(20),
    PRIMARY KEY(id, serial_key)
    
  2. serial_rate:

    id CHARACTER VARYING(20), 
    serial_key CHARACTER VARYING(20),
    rate NUMERIC,
    PRIMARY KEY(id, serial_key),
    FOREIGN KEY (id, serial_key) REFERENCES serial_table(id, serial_key)
    

现在我想从单个 SQL 查询更新 serial_rate.rateserial_table.serial_key,例如:

UPDATE inventory.serial_table AS s 
JOIN inventory.serial_rate AS r 
ON (s.id, s.serial_key) = (r.id, r.serial_key) 
SET s.serial_key = '0002', r.rate = 22.53
WHERE (s.id, s.serial_key) = ('01', '002');

我知道这是不正确的。 有没有办法做到这一点,因为我想使用该语句在 Java 中创建 PreparedStatement

编辑 这个问题与 Java 中的 PreparedStatements 无关,而是关于我希望在创建 PreparedStatement 时作为参数传递的 SQL 语法。 我不想得到任何关于PreparedStatement的答案

【问题讨论】:

  • 你真的打算更新serial_table.serial_key这个PK组件吗?并且:serial_rate.serial_key 是否也应该更新(也是 PK 组件,FK 到第一个)?如果不是:可能会违反 FK 约束。
  • @wildplasser 第一个答案是肯定的,至于第二部分,FK 是 ON UPDATE CASCADE ON DELETE RESTRICT。
  • @JarrodRoberson 我无法理解您为什么认为这个问题与您所链接的问题相似?我在该链接中没有得到我想要的答案。
  • 如果您的问题只是关于 SQL 语法,我会删除所有提到的“准备好的语句”。

标签: sql postgresql sql-update common-table-expression


【解决方案1】:

这是一个 CTE 的东西(但我不知道如何将它包装成一个准备好的 Java 东西)

WITH src AS (
        UPDATE serial_rate
        SET rate = 22.53, serial_key = '0002'
        WHERE serial_key = '002' AND id = '01'
        RETURNING *
        )
UPDATE serial_table dst
SET serial_key = src.serial_key
FROM src
-- WHERE dst.id = src.id AND dst.serial_key  = '002'
WHERE dst.id = '01' AND dst.serial_key  = '002'
        ;

【讨论】:

  • 这仍然是两个语句,在一个事务/存储过程中只是执行两个更新语句还不是很清楚,并且作为一个准备好的语句来实现会更加困难(想想一个带有变量的长而丑陋的字符串到处都是)
  • 不,它们被链接在一起(相当笨拙)。提示:只有一个分号。只需将EXPLAIN 放在它前面,您就会看到它会为组合更新生成一个查询计划。
  • 它实际上是一个子查询,对吧?一个查询计划是两个查询?
  • @DanField:不,这只是一个查询。当然,它只有一个查询计划。诀窍是结合 CTE 和在第一个 UPDATE 命令中使用 RETURNING,这将在第二个 UPDATE 命令中使用。
  • @Blip:是的,在查询中使用另一个 CTE 是可能的:sqlfiddle.com/#!15/75387/1
【解决方案2】:

这是 a_horse_with_no_name 在 sqlfiddle.com 上发布的内容:

   WITH id_values (new_key, old_key, id) as (
      values ('0002', '002', '01')
    ), src AS (
      UPDATE serial_rate
          SET rate = 22.53, 
              serial_key = (select new_key from id_values)
      WHERE serial_key = (select old_key from id_values)
        AND id = (select id from id_values)
      RETURNING *
    )
    UPDATE serial_table dst
       SET serial_key = src.serial_key
    FROM src
    WHERE dst.id = (select id from id_values)
      AND dst.serial_key = (select old_key from id_values)
    ;

这实际上是 wildplasser 发布的内容的修改版本,作为对 serial_key 字段是否可以使用一次的查询的回复。

【讨论】:

    猜你喜欢
    • 2021-02-13
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    相关资源
    最近更新 更多