Вставить с помощью выбора, получить вставленное значение

Я использую определенный запрос для создания идентификаторов без автоинкремента:

'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;

У меня проблема с получением последнего вставленного идентификатора строки (поскольку я не использую автоинкремент, cur.lastrowid - None)

Как я могу получить результат вставленного значения идентификатора строки в моем случае?

1 ответ

Решение

Если вас не волнуют условия гонки, вы можете получить id значение в таблице с SELECT MAX(id) AS id FROM global_ids,

Но вы заботитесь об условиях гонки. Что произойдет, если запущены две копии вашей программы на Python? Один может сделать вставку, затем другой может сделать вставку, прежде чем первый сделает выбор, который я предложил. Если это произойдет, выбор вернет неправильное значение.

Вы могли бы попробовать

     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, потому что они игнорируют транзакции.)

Но лучше всего избегать неприятностей с состоянием гонки в 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 значения без риска для условий гонки.

Другие вопросы по тегам