2017-10-26 9 views
0

テーブルtbtableには次のカラムが含まれています。 enter image description hereMySQLの更新ローIDをOUTパラメータに設定する

tbtableにエントリを作成または更新する手順は次のとおりです。

今は更新が発生したときにエントリのIDを取得する方法がありません。どのスクリプトに私の現在のcreateOrUpdateメソッドを変更して、更新が行われたときにidを取得できるようにする必要がありますか?

他の同様の質問を確認しましたが、OUTというパラメータがないため、私の場合は該当しません。

ありがとうございました。

EDIT:

BEGIN 

    IF EXISTS (SELECT*FROM `tbtable` WHERE `pid` = this_pid AND `sid` = this_sid) 
    THEN 
     UPDATE `tbtable` 
     SET 
     `ri` = this_ri, `defaults` = this_defaults, `approved` = this_approved 
     WHERE `pid` = this_pid AND `sid` = this_sid; 
     SET id = `id` ; 
    ELSE 
     INSERT INTO `tbtable` (`pid`, `sid`, `ri`, `defaults`, `approved`) 
     VALUES (this_pid, this_sid, this_ri, this_defaults, this_approved); 
     SET id = LAST_INSERT_ID(); 
    END IF; 

END 

私もこのアプローチを試みたが、更新がある場合idはNULLです。

答えて

1

です。

また、ユーザー定義の変数を設定することもできます。

ルーチンパラメータ、ローカル変数、および列に同じ識別子を使用できることに注意してください。ルーチンのパラメータがテーブルの列よりも優先されます。

一般的に、UPDATE文は複数の行に影響する可能性があるため、複数の行を持つことができます。手続き引数はスカラーなので、idを返す行を決める必要があります。 id列が(残念ながら命名)tbtableテーブル内の非NULLであることが保証されると仮定すると

...この手順は同時で、競合状態にさらされること

BEGIN 
    DECLARE lv_id BIGINT DEFAULT NULL; 
    -- test if row(s) exist, and fetch lowest id value of from matching rows 
    SELECT t.id 
    INTO lv_id -- save retrieved id value into procedure variable 
    FROM tbtable t 
    WHERE t.pid = this_pid 
     AND t.sid = this_sid 
    ORDER BY t.id 
    LIMIT 1 
    ; 
    -- if we got a non-NULL value returned 
    IF lv_id IS NOT NULL THEN 
     -- do the update 
     UPDATE `tbtable` t 
     SET t.ri  = this_ri 
      , t.defaults = this_defaults 
      , t.approved = this_approved 
     WHERE t.pid = this_pid 
     AND t.sid = this_sid 
     ; 
    ELSE 
     INSERT INTO `tbtable` (`pid`, `sid`, `ri`, `defaults`, `approved`) 
     VALUES (this_pid, this_sid, this_ri, this_defaults, this_approved) 
     ; 
     SET lv_id = LAST_INSERT_ID(); 
    END IF; 
    -- set OUT parameter 
    SET id = lv_id ; 
END$$ 

注意他のセッションから操作を削除します。私たちのSELECTステートメントは一致する行にidを返し、別のセッションはその行を削除して更新を実行し、その行を見つけられませんでした。ここでのタイミングは非常にタイトですが、更新の直前にSELECT WAIT(15);のような手順を遅らせることなくこれを実証するのは難しいでしょう(別のセッションからの削除を実行するのに15秒を要します)。)

-1

あなたは最後に明示的な戻り値を必要とする:あなたは、単一の値を返すようにしようとしていませんが、更新文が複数の行で実行することができ

IF ROW_COUNT() = 0 
     THEN 
     INSERT INTO `tbplanhassurface` (`planid`, `surfaceid`, `roi`, `defaultsurface`, `approved`) 
     VALUES (this_planid, this_surfaceid, this_roi, this_defaultsurface, this_approved); 
     SET id = LAST_INSERT_ID(); 
ELSE 
     SELECT @id = your_id_field 
     FROM `tbplanhassurface` 
     WHERE `planid` = this_planid 
     AND `surfaceid` = this_surfaceid; 
END IF; 

    SELECT @id; 

END 
+0

スクリプトを編集して表示してもらえますか? –

+0

が完了しました。今はいいですか? –

+1

いいえこれは、OUTパラメーターの値を設定しません。結果セットが返されます。 (これは、プロシージャ内の他の場所では参照されていない@idというユーザ定義変数の現在の値を返します。 – spencer7593

0

を。したがって、そのタイプの更新されたステートメントからIDを返すときは、更新された行をループし、更新された行の値のいずれかを返す必要があります(pidとsidの組み合わせが一意であるためです)。ここで私はそれと一時データベースを作成しないようRID列なしのサンプルコード:)私たちは、ローカルプロシージャ変数に値を格納するためのSELECT t.myid INTO v_id FROM t WHERE ...ステートメントを実行することができ

CREATE PROCEDURE createOrUpdateTbTable ( IN this_pid INT UNSIGNED, IN this_sid INT UNSIGNED, IN this_ri LONGBLOB, IN this_defaults TINYINT, IN this_approved TINYINT, OUT id INT UNSIGNED ) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE updated_id INT; DECLARE updatedIds CURSOR FOR SELECT tbtable.id FROM tbtableWHERE pid = this_pid AND sid = this_sid; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

IF EXISTS (SELECT*FROM `tbtable` WHERE `pid` = this_pid AND `sid` = this_sid) THEN UPDATE `tbtable` SET `defaults` = this_defaults, `approved` = this_approved WHERE `pid` = this_pid AND `sid` = this_sid; OPEN updatedIds; read_loop: LOOP FETCH updatedIds INTO updated_id; SET id = updated_id; IF done THEN LEAVE read_loop; END IF; END LOOP; CLOSE updatedIds; ELSE INSERT INTO `tbtable` (`pid`, `sid`, `defaults`, `approved`) VALUES (this_pid, this_sid, this_defaults, this_approved); SET id = LAST_INSERT_ID(); END IF;END

関連する問題