2016-03-29 3 views
4

У меня есть таблица в базе данных, в которой хранятся элементы. Каждый элемент имеет уникальный идентификатор, который создается БД при вставке (автоинкремент).
Пользователь может выполнить определенную задачу, которая добавит элементы X в базу данных, однако моя программа (серверное приложение C++ с использованием соединителя MySQL) должна вернуть идентификаторы, сгенерированные в базе данных сразу. Например, если я добавлю 6 элементов, сервер должен вернуть клиенту 6 новых уникальных идентификаторов.
Какой самый быстрый/самый чистый способ сделать такую ​​вещь? До сих пор я делал INSERT, за которым следует SELECT для каждого нового элемента ИЛИ INSERT, за которым следует last_insert_id, однако если есть 50 элементов для добавления, это займет несколько секунд, по крайней мере, что не очень хорошо для пользователей.Самый быстрый способ выбора нескольких вставленных строк

sql_task.query("INSERT INTO `ItemDB` (`ItemName`, `Type`, `Time`) VALUES ('%s', '%d', '%d')", strName.c_str(), uiType, uiTime); 

Получение ID:

uint64_t item_id { sql_task.last_id() }; //This calls mysql_insert_id 
+0

пожалуйста, добавьте код –

+0

Хорошо, я добавил код. Все работает отлично, но это совсем не быстро. – Spook

ответ

-1

Как идентификатор autoincremental, вы можете сделать только два SELECT запросов - до и после INSERT запросов:

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'dbTable' AND table_schema = DATABASE(); 
-- 
-- INSERT INTO dbTable... (one or many, does not matter); 
-- 
SELECT LAST_INSERT_ID() AS lastID; 

Это даст вам siquence между первым и последним вставленными идентификаторами. Тогда вы можете легко рассчитать, сколько они есть.

+0

Это не так просто. Параллельная сессия также может увеличивать идентификатор вставки. И, конечно, кластеры с несколькими мастерами MySQL не увеличиваются на 1. – rkosegi

+0

Я согласен с rkosegi, так как меня тоже беспокоит. Если у меня есть внешний инструмент, который может добавлять элементы в ту же самую таблицу, и я случайно добавляю элементы одновременно, клиент может получить несколько идентификаторов, которые отличаются друг от друга. – Spook

+0

@rkosegi вообще да, вы правы, но это зависит. Поскольку InnoDB выполняет блокировку во время вставки, другие вставки должны ждать, пока вставка закончит транзакцию (если таковая имеется). Все зависит от реализации. – mitkosoft

1

Я считаю, что вам нужно немного переосмыслить свой дизайн. Давайте используем аналогию заказа клиента. При заказе клиента (или счет-фактуре #) пользователь получает номер счета-фактуры (auto_incr), а также несколько номеров позиций (также auto_inc).

Порядок продаж и все позиции выбираются для вставки (из графического интерфейса пользователя) и выполняются вставки. Во-первых, строка заказа клиента вставляется и ее идентификатор сохраняется в переменной для последующих вызовов для вставки позиций. Но позиции затем просто вставляются без немедленного возврата их значений id auto_inc. Приложение просто возвращает номер заказа клиента в конце. Как ваше приложение использует этот номер заказа клиента в последующих вызовах, зависит от вас. Но сразу не нужно сразу извлекать все строки X или 50, так как у него есть номер заказа клиента, который был заморожен и где-то сохранен. Назовем этот номер заказа клиента XYZ.

Когда вы на самом деле нужна информация, пример вызова может выглядеть

select lineItemId 
from lineItems 
where salesOrderNumber=XYZ 
order by lineItemId 

Вы должны помнить, что в системе с несколькими пользователями, что нет никакой гарантии получения непрерывного блока чисел , И это не имеет значения для вас, так как все они надлежащим образом привязаны к правильному номеру заказа клиента.

Опять же, приведенное выше является просто аналогом, используемым для иллюстративных целей.

+0

Эта аналогия была большой, спасибо! На самом деле, это даже не мой дизайн, так как я пытаюсь воспроизвести поведение сервера, но эта часть сбивает с толку. Пользователь может сразу купить пару элементов, и сервер добавит их в БД, а затем вернет уникальный идентификатор клиенту для каждого купленного товара. Они делают это очень быстро, поэтому мне было интересно, есть ли что-то, что я пропустил. – Spook

0

Это распространенная проблема, но трудно решить. Unsure для mysql, но PostreSQL использует последовательностей для генерации автоматических идентификаторов. Вставка фреймворков (объектно-ориентированных карт) использует это, когда они ожидают вставить много значений: они запрашивают непосредственно последовательность для набора идентификаторов, а затем вставляют новые строки с использованием уже известных идентификаторов. Таким образом, нет необходимости в дополнительном запросе после каждой вставки, чтобы получить идентификатор.

Недостатком является то, что отношение ID - время вставки может быть немонотонным, когда разные авторы смешивают свои вставки. Это не проблема для базы данных, но некоторые (плохо написанные?) Программы могли ожидать, что это так.

Смежные вопросы