用 select 插入,得到插入的值

insert with select, get inserted value

我正在使用特定查询来生成没有自动增量的 ID:

'insert into global_ids (`id`) select (((max(id)>>4)+1)<<4)+1 from global_ids'


CREATE TABLE `global_ids` (
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

我在获取最后插入的行 ID 时遇到问题(因为我没有使用自动增量,cur.lastrowid 是 None)

在我的案例中,如何获取插入的行 ID 值的结果?

如果不关心竞争条件,可以用SELECT MAX(id) AS id FROM global_ids.

得到table中最高的id

但是,您确实关心竞争条件。如果您的 python 程序的两个副本是 运行 会怎样?一个可以插入,然后另一个可以在第一个执行我建议的 select 之前执行插入。如果发生这种情况,select 将 return 一个错误的值。

你可以试试

     START TRANSACTION;
     SELECT (((max(id)>>4)+1)<<4)+1 INTO @id FROM global_ids WITH UPDATE;
     INSERT INTO global_ids (id) VALUES (@id);
     COMMIT;
     SELECT @id AS id;

使用事务序列化您的 id 生成/检索操作。 (这在 MyISAM tables 中不起作用,因为它们会忽略事务。)

但是,在 MySQL 中避免竞争条件麻烦的最佳方法是实际使用自动递增功能。你可以试试这个。

CREATE TABLE global_ids (
     id INT NOT NULL AUTO_INCREMENT,
     PRIMARY KEY (`id`)
) 

然后依次发出这些查询:

INSERT INTO global_ids () VALUES ();
SELECT (((LAST_INSERT_ID()>>4)+1)<<4)+1 AS id;

这将使用自动递增功能生成转换后的 id 值,而不会 运行 竞争条件的风险。