LAST_INSERT_ID() результат хранимой процедуры

У меня есть хранимая процедура в MySQL, которая обновляет много строк, а затем вставляет одну (иерархическая структура данных, чтобы быть конкретным). Не смотрите больше на код, за исключением последнего, где я устанавливаю переменную @insert_id.

CREATE DEFINER=`root`@`localhost` PROCEDURE `addTaskNextTo`(IN `prev_id` INT, IN `pid` INT, IN `name` VARCHAR(100), IN `type` TINYINT, IN `uid` INT, IN `starting_date` DATE, IN `description` TEXT, OUT `insert_id` INT)
MODIFIES SQL DATA
BEGIN
    SELECT @myRight := rgt FROM tasks WHERE id = prev_id;
    UPDATE tasks SET rgt = rgt + 2 WHERE rgt > @myRight AND pid = pid;
    UPDATE tasks SET lft = lft + 2 WHERE lft > @myRight AND pid = pid;
    INSERT INTO tasks(pid, name, lft, rgt, type, uid, starting_date, description)
          VALUES(pid, name, @myRight + 1, @myRight + 2, type, uid, starting_date, description);
    SET @insert_id = LAST_INSERT_ID();
END

Теперь, когда я выполняю эту процедуру из phpMyAdmin, он возвращает правильный последний идентификатор, но когда я вызываю его из php, он возвращает идентификатор из предыдущей вставленной строки??? В чем может быть проблема, и есть ли лучший способ предложить мне это сделать.

Вот как я это называю из PHP:

$sql = "CALL addTaskNextTo($last_tid, $pid, '$task_name', 0, $uid, '$task_start', '$task_desc', @insert_id)";

Это само по себе действует как запрос SELECT, и я получаю 1 столбец "insert_id" с одной строкой со значением, например, "120", который является идентификатором текущей текущей вставленной строки, но предыдущей.

Здесь это функция, которая получает строку sql и возвращает единственное значение:

public static function get_single_value($sql) {
    global $db;
    $rez = $db->query($sql);
    return !empty($rez) ? mysql_result($rez,0) : false;
}

1 ответ

Я не уверен, как ты это делаешь, но ты должен сделать это что-то вроде

$dbh->query("CALL addTaskNextTo($last_tid, $pid, '$task_name', 0, $uid, '$task_start', '$task_desc', @insert_id)");
$dbh->query("SELECT @insert_id"); 

обратите внимание, что вам нужен отдельный запрос SELECT, чтобы получить обновленное значение идентификатора вставки. В противном случае вы просто получите старый.

Или, еще лучше, что-то вроде:

$stmt = $dbh->prepare("CALL addTaskNextTo(?, ?, ?, ?, ?, ?, ?, @insert_id)");
$stmt->execute(array($last_tid, $pid, $task_name, 0, $uid, $task_start, $task_desc));
$dbh->query("SELECT @insert_id"); 

Также возможно использовать связывание для непосредственного получения выходного параметра в переменной PHP (см. Третий пример в руководстве).


Редактировать: если вы получаете сообщение "Команды не синхронизированы; вы не можете запустить эту команду сейчас", это означает, что у вас включены небуферизованные запросы. Это означает, что вам нужно либо прочитать результат между, либо использовать буферизованные запросы. Чтобы помочь с этим, вы можете использовать $stmt->store_result() после первого запроса, но до запуска следующего. Смотрите более подробную информацию в этой теме.

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