LAST_INSERT_ID()来自存储过程

时间:2013-03-14 21:09:56

标签: php mysql stored-procedures 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执行此过程时,它返回正确的最后一个id,但是当我从php调用它时,它返回前一个插入行的id ???可能是什么问题,有没有更好的方法,你建议我应该这样做。

这是我从PHP中调用它的方式:

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

这本身就是一个SELECT查询,我得到一列“insert_id”,其中一行带有值,例如“120”,这是前一个非当前插入行的ID。

这是接收sql字符串并返回单个值的函数:

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

1 个答案:

答案 0 :(得分:1)

我不确定你是怎么做的,但是你应该这样做

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

请注意,您需要单独的SELECT查询来获取插入ID的更新值。否则你只会得到旧的。

或者,更好的是,像:

$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"); 

也可以使用bind直接在PHP变量中输出输出参数(参见the third example in manual)。


编辑:如果收到消息“命令不同步;您现在无法运行此命令”,则表示您已打开未缓冲的查询。这意味着您需要在两者之间读取结果或使用缓冲查询。为了解决这个问题,您可以在第一次查询后使用$stmt->store_result(),但在运行下一个查询之前。请在this thread了解详情。