【问题标题】:PostgreSQL Transaction in one Trip一次旅行的 PostgreSQL 交易
【发布时间】:2017-10-10 03:10:13
【问题描述】:

在我非常简单的 PostgreSQL v8.4.13 数据库中,表 AB,列 A.a 是一个 SERIAL PRIMARY KEY,即 FOREIGN KEYed 到 B.a。两个表中还有其他列。 a 不是 UNIQUEB 中。

在一个事务的范围内,我想在A 中添加一行,在B 中添加相应的行。

我正在使用用于 PGL 的 PHP PDO 编写脚本。

这样的事情有可能在一次往返中完成吗?

是否可以在一次往返中对B 的多行进行类似的操作?

【问题讨论】:

  • 当然,您必须通过manual mode 选择退出自动提交。
  • 当您说“一次往返”时,您是指一次 exec 调用(单个查询)吗?
  • 我的意思是从脚本到数据库的一条消息,带有一个返回值。我对连接的了解不够,不知道如何比这更好地说明它。
  • 只需在 sql 字符串参数中用 ; 分隔查询即可。

标签: php postgresql pdo


【解决方案1】:

您可以使用INSERT ... RETURNING 语句检索A.a 新生成的SERIAL 值,并且可以使用CTE 将两个INSERTs 打包到同一个语句中:

WITH Inserted AS (
  INSERT INTO A (data)
  VALUES ('data')
  RETURNING A.a
)
INSERT INTO B (a, data)
SELECT Inserted.a, 'more data'
FROM Inserted;

如果要在B 中插入多条记录,可以在VALUES 表达式中填写剩余字段,并为INSERT 加入新的A.a 值:

WITH Inserted (a) AS (
  INSERT INTO A (data)
  VALUES ('data')
  RETURNING A.a
),
BValues (data) AS (
  VALUES
    ('data1'),
    ('data2'),
    ('data3')
)
INSERT INTO B (a, data)
SELECT Inserted.a, BValues.data
FROM Inserted CROSS JOIN BValues;

【讨论】:

  • 谢谢!现在我很想知道这是否在没有我明确这样做的情况下作为交易执行。
  • @QED:如果您没有显式启动事务,Postgres 将开始并为每个语句提交一个(尽管有多个子表达式,但 CTE 算作单个语句)。许多客户端库将通过在幕后启动自己的事务来覆盖此行为,尽管据我所知,PDO 的默认行为似乎与 Postgres 一致。
  • 是否可以一次往返在B 中插入多行?
【解决方案2】:

只要更新到同一个数据库,每个事务可以有多个执行:

$dbh->beginTransaction();
$dbh->exec("UPDATE A SET last = 'hi'");
$dbh->exec("UPDATE B SET name = 'Rafael'");
/* MULTIPLE EXECS HERE */
$dbh->commit();

【讨论】:

  • 我为什么要丢表A
  • 这是您将运行的语句的一个示例,在 one 事务中都有这两个语句。我误解你的问题了吗?
  • 我的回答并没有误导你,look hereusing multiple transactions in one function call is not recommended.,我不知道你为什么不给我投票。
  • 我没有对你投反对票,我认为其他人这样做是因为他知道A 中的数据对我来说非常重要。
  • DROP 语句是一个事务中的多个语句的示例。当然,您不会复制粘贴此代码并盲目运行它...
猜你喜欢
  • 1970-01-01
  • 2012-04-23
  • 2011-03-18
  • 2010-11-16
  • 2022-10-25
  • 1970-01-01
  • 2022-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多