Введите поле идентификатора, сгенерированное с помощью триггера, но не пройденное

В MySQL у меня есть триггер:

BEGIN IF (EXISTS(SELECT * FROM devices WHERE device_id = NEW.device_id)) THEN SET NEW.id = NULL; ELSE INSERT INTO objects (object_type) VALUES ('3'); SET NEW.id = LAST_INSERT_ID(); END IF; END 

Когда этот триггер получает новый идентификатор (из таблицы объектов), он вставляет идентификатор в столбец id таблицы устройств.

Когда я обращаюсь к нему (например, с mysql_insert_id(); в PHP), его пустой.

Как я могу вернуть id вставки из триггера ( LAST_INSERT_ID(); ) в функцию в PHP как mysql_insert_id(); ?

Лично я использую хранимые процедуры.
Вот базовый пример с PDO:

Код для создания хранимых процедур :

 CREATE DEFINER=`user`@`localhost` PROCEDURE `InsertUser`(IN `Input_username` INT, OUT `Out_ID` INT) LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER COMMENT '' BEGIN INSERT INTO users( username) VALUES ( Input_username); SET Out_ID = LAST_INSERT_ID(); SELECT Out_ID; END 

И PHP-код :

  $insert = "CALL InsertUser(:Input_username, @Out_ID)"; $bdd = new PDO('mysql:host=localhost;dbname=db-name', 'user', 'password'); $stmt = $bdd->prepare($insert); $stmt->bindParam(':Input_username', rand(), PDO::PARAM_STR); // to create random name $stmt->execute(); $tabResultat = $stmt->fetch(); $id_user = $tabResultat['Out_ID']; var_dump($id_user); 

Надеюсь, я помог. 🙂

Это по дизайну :

Если хранимая процедура выполняет инструкции, которые изменяют значение LAST_INSERT_ID() , измененное значение видно из операторов, которые следуют за вызовом процедуры.

Для хранимых функций и триггеров, которые изменяют значение, значение восстанавливается при завершении функции или триггера, поэтому следующие операторы не будут видеть измененное значение.

  • Обходной путь 1: Хранимые процедуры

К сожалению, это создает риск несоответствий между вашей таблицей и objects , поскольку вставки могут все же произойти за пределами этой процедуры (эту проблему можно было бы перенаправить со строгими ограничениями доступа на таблицу)

  • Обходной путь 2:

Сохраните значение в пользовательской переменной:

 CREATE TRIGGER .... BEGIN INSERT INTO objects (object_type) VALUES ('3'); SET NEW.id = LAST_INSERT_ID(); SET @myLastInsertID = LAST_INSERT_ID(); END // INSERT INTO your_table... -- trigger the above SELECT @myLastInsertID; -- here is your value 
  • Обходной путь 3:

Просто получите значение от object 😉

 INSERT INTO your_table... -- trigger the above SELECT MAX(autoinc_column) FROM objects; -- here is your value! 

Временные решения 2 и 3 должны быть завернуты в транзакцию, чтобы гарантировать, что никто не вмешивается в @myLastInsertID или object во время процесса.