我如何在 CakePHP3 中 运行 事务同时检索最后的插入 ID 并为 PostgreSQL 和 MySQL 工作?

How do I run transactions in CakePHP3 while retrieving last insert id and work for both PostgreSQL and MySQL?

我正在使用 CakePHP 3.x

There is a way to execute transactions in CakePHP 3.x.

但是,我的某些执行语句需要前面插入语句的 ID。

如何在选择 CakePHP 3.x 并允许 PostgreSQL 或 MySQL 作为我的数据库时在事务中执行该操作?

我预期的查询是这样的:

INSERT INTO dynamic_views (`title`, `created`) values ('view 37', NOW());

-- take the id of the above insert query and assuming the view id is 37
INSERT INTO users_access_dynamic_views(user_id, view_id) values (44, 37);

我想使用 CakePHP3.x.

使用事务执行上述操作

同时想问一下,对于上述情况,使用事务是否是个坏主意?

获取MySQL中最后插入的id的函数调用last_insert_id(), while in PostgreSQL it is lastval()。所以要么你必须在两者之间创建一些映射,要么你必须检查你在 CakePHP 中使用的是哪个驱动程序,然后调用特定的函数。

例如,您可以在 PostgreSQL 中创建以下函数。

CREATE FUNCTION last_insert_id() RETURNS BIGINT AS $$
  SELECT lastval();
$$ LANGUAGE sql VOLATILE;

然后你可以在第二个查询中调用它,它将在 MySQL 和 PostgreSQL 中工作。

INSERT INTO users_access_dynamic_views
  (user_id, view_id)
VALUES
  (44, LAST_INSERT_ID());

还请注意,PostgreSQL 使用序列生成 ID,因此当涉及触发器(自行在某处插入数据)时,仅依赖 lastval 可能会产生意想不到的结果。因此,最好通过 currval.

明确指定涉及的序列
CURRVAL(PG_GET_SERIAL_SEQUENCE('dynamic_views', 'view_id'))

执行插入查询后,您可以使用正确的参数调用 lastInsertId() 以获得正确的值:

$connection->transactional(function ($connection) {
    $statement = $connection->newQuery
        ->insert($fields)
        ->into($table)
        ->values($values)
        ->execute();

     $insertId = $statement->lastInsertId($table, 'id'); // id is primary key
});