2

mysqlにストアドプロシージャがあり、多くの行を更新してから1つ挿入しています(具体的には階層データ構造)。@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クエリとして機能し、前の行の現在挿入されていない行のIDである「120」などの値を持つ1つの行を持つ1つの列「insert_id」を取得しています。

これは、SQL文字列を受け取り、単一の値を返す関数です。

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

1 に答える 1

1

どのように行うかはわかりませんが、次のようにする必要があります

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

挿入 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"); 

bind を使用して、出力パラメーターを PHP 変数に直接指定することもできます (マニュアルの 3 番目の例を参照してください)。


編集:「コマンドが同期されていません。現在、このコマンドを実行できません」というメッセージが表示された場合は、バッファリングされていないクエリがオンになっていることを意味します。これは、その間に結果を読み取るか、バッファリングされたクエリを使用する必要があることを意味します。$stmt->store_result()これを支援するために、最初のクエリの後、次のクエリを実行する前に使用できます 。詳細については、このスレッドを参照してください。

于 2013-03-14T23:07:18.510 に答える