0

我想将表中的外键更新为来自新插入的值,其中该键当前为空。这里需要注意的是,INSERT 中的信息与表相关。

考虑这个例子:

  1. 汽车有一个car_part
  2. car 和 car_part 都与 version_control 有关联(version_control 有一个 id,from_version,to_version,active)
  3. 一些汽车目前有一个空版本控制。
  4. 由于汽车有一个带有 version_control 的 car_part,我们本质上想为汽车创建一个新的 version_control,并使用与 car_part 的 version_control 相同的信息填充它

例如:

CAR
|id|car_part_id|version_control_id|
|1 |10         |                  |

CAR_PART
|id|version_control_id|
|10|100               |

VERSION_CONTROL
|id |from    |to         |
|100|1990    |2012       |

对于上面的例子,我们想要:

  1. 更新汽车1,
  2. 添加与 version_control #100 具有相同信息的新 version_control

在实际示例中,有数百辆汽车,其中数十辆汽车的 version_control_id 为空,因此我们需要在单个查询中完成。

我们如何将下面的 PSEUDO 代码更改为解决此问题的有效 SQL?

UPDATE car
WITH inserted_version as (
    INSERT INTO version_control(
            id, active, from_version_id, to_version_id)
    WITH vc_to_create as (
        select c.id as car_id,vc.* from car c
        inner join car_part cp on cp.id = c.car_part_id 
        inner join version_control vc on cp.version_control_id=vc.id
        where c.version_control_id IS NULL
        )
    SELECT nextval('pk_entities'),vctc.active, vctc.from_version_id, vctc.to_version_id)
    FROM vc_to_create vctc
    RETURNING id
    )
SET version_control_id=(SELECT i_vc.id  FROM inserted_vc i_vc)
WHERE id=vc_to_create.car_id -->vc_to_create Not available here
4

1 回答 1

1

听起来您想对事务块中的不同表进行两次修改。

这是一个开始。http://www.postgresql.org/docs/9.1/static/tutorial-transactions.html

在进入事务之前,可能还需要将事务隔离级别设置为 SERIALIZABLE 。请参阅http://www.postgresql.org/docs/9.1/static/sql-set-transaction.html以了解我在说什么。

如果我们不需要那么严格的隔离级别,请有人纠正我。不幸的是,我对哪些场景严格要求这种隔离级别的细节感到模糊。严格来说,这可能不需要那种隔离级别,尤其是取决于编写的 SQL,但是这听起来可能是那种情况。只是一个可能不必要的预警。

编辑:

好的,您仍然不需要“在单个查询中”完成所有这些操作。严格来说,您只需要识别或跟踪刚刚插入的行。您应该可以为此使用临时表。那是:

  1. 开始交易。
  2. 将事务隔离级别设置为 SERIALIZABLE。(再次,如果需要,但坦率地说,如果我没有设置它,我会担心,除非另有证明。还要注意使用 SERIALIZABLE 你可能需要重试:http ://www.postgresql.org/docs/9.1/interactive /transaction-iso.html#XACT-SERIALIZABLE )
  3. 创建临时表作为(使用查询)您将插入到 version_control 的行以及与每个版本控制行相关的汽车的 ID。也就是说,每一行都会有版本控制信息和 id 信息。我们只需要抓住nextval('pk_entities')这里。
  4. 将临时表中的数据插入到版本控制中(如前所述,我们已经生成了密钥)。
  5. 使用临时表中的数据更新汽车。
  6. 提交/删除表。(这显然可以在事务提交时通过在临时表的创建语句中声明它来完成。)

这是对我如何计划它的高/中级描述,由于我还没有明确地为此编写代码,我可能错过了一些东西。

于 2012-07-17T18:12:35.933 回答