Я всегда слышу, что использование lastInsertId (или mysql_insert_id (), если вы не используете PDO) - зло. В случае триггеров это очевидно, потому что он может вернуть что-то, что совершенно не является последним идентификатором, созданным вашим INSERT.
$DB->exec("INSERT INTO example (column1) VALUES ('test')");
// Usually returns your newly created ID.
// However when a TRIGGER inserts into another table with auto-increment:
// -> Returns newly created ID of trigger's INSERT
$id = $DB->lastInsertId();
Какая альтернатива?






Это не сложно и неэффективно, но если данные, которые вы вставили, включают уникальные поля, тогда SELECT, очевидно, может дать то, что вам нужно.
Например:
INSERT INTO example (column1) VALUES ('test');
SELECT id FROM example WHERE column1 = 'test';
Я думаю, что это тоже не самое современное искусство, но я использую блокировки записи, чтобы убедиться, что я действительно получаю последний вставленный идентификатор.
Очевидно, тоже работает, но блокировка IMHO еще более зла в высокопроизводительных веб-приложениях ...
ИМХО это считается «злом», потому что вряд ли в какой-либо другой базе данных SQL (если таковая имеется) он есть.
Лично я считаю это невероятно полезным и хочу, чтобы мне не приходилось прибегать к другим более сложным методам в других системах.
По крайней мере, у MSSQL есть такая же функция. В моей старой работе использование «идентификатора вставки» вызывало большие головные боли, когда кто-то добавлял триггер в таблицу, что нарушало работу всего веб-сайта - без очевидной причины для тех, кто не знал об этом триггере ...
Если вы идете по маршруту ADOdb (http://adodb.sourceforge.net/), вы можете создать идентификатор вставки перед рукой и явно указать идентификатор при вставке. Это может быть реализовано переносимо (ADOdb поддерживает множество различных баз данных ...) и гарантирует, что вы используете правильный идентификатор вставки.
Тип данных PostgreSQL SERIAL аналогичен, за исключением того, что он для каждой таблицы / последовательности, вы указываете таблицу / последовательность, для которой требуется последний идентификатор вставки, когда вы ее запрашиваете.
Смотрится довольно интересно. Как этот прием влияет на производительность?
Да, но что делать, если вы застряли с PDO?
Вы можете написать свой собственный код, чтобы делать то же самое, что и ADOdb, за исключением использования PDO. По сути, вы получаете отдельную таблицу для хранения последовательности, которую вы ЗАПИВАЕТЕ БЛОКИРОВАТЬ перед увеличением значения последовательности при получении нового идентификатора.
Это не должно сильно влиять на производительность, это всего лишь очень простая таблица, которая блокируется, выбирает одну запись, увеличивает, разблокирует. Я не заметил разницы в производительности ни в одном приложении, с которым я его использовал. Помните: сначала заставьте его работать, а потом настраивайте производительность.
Одна альтернатива - использовать вместо этого последовательности, поэтому вы сами создаете идентификатор, прежде чем делать вставку.
К сожалению, они не поддерживаются в MySQL, но библиотеки, такие как Adodb, могут имитировать их, используя другую таблицу. Я думаю, однако, что сама эмуляция будет использовать lastInsertId () или эквивалент ... но, по крайней мере, у вас меньше шансов иметь триггер в таблице, которая используется исключительно для последовательности
Вы можете попробовать это:
$sql = "SELECT id FROM files ORDER BY id DESC LIMIT 1";
$PS = $DB -> prepare($sql);
$PS -> execute();
$result = $PS -> fetch();
Это не альтернатива в условиях высокой посещаемости. Вы будете постоянно получать неправильные идентификаторы.
Очевидно;) - Но тоже, очевидно, довольно некрасиво;)