3

プロシージャ内から別のプロシージャを呼び出すことが可能かどうか、またいずれかのプロシージャの一部が失敗した場合はすべてをロールバックできるかどうか教えてもらえますか?

これが可能であれば、誰かがこれを実装する方法の小さな例を見せてもらえますか?

編集:プロシージャ "b" は失敗しますが、プロシージャ "a" はテーブル "a" に行を挿入します。挿入の一部が失敗した場合、ここでは発生していないすべて (両方の挿入) がロールバックされることを理解しています。質問は、なぜですか?

手順「a」

BEGIN
  DECLARE b INT DEFAULT 0;
  DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;

  START TRANSACTION;
    INSERT INTO a(a)
    VALUES(iA);

     CALL b(iB,LAST_INSERT_ID(),@b);
     SELECT @b INTO b;

     IF b !=1 THEN
        ROLLBACK;
      ELSE
        COMMIT;
  END IF;
END

手順「b」

BEGIN
  DECLARE b INT DEFAULT 0;
  DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;
  DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;

  START TRANSACTION;
    INSERT INTO b VALUES(iB,id);
    SET b=1;
  COMMIT;
END;
4

1 に答える 1

1

両方のプロシージャでトランザクションを処理する必要がありますが、もう一方を呼び出しているプロシージャは、戻り値をチェックし、それに基づいてトランザクションをロールバックする必要があります。内部プロシージャの例を次に示します。

MySQLストアドプロシージャでロールバックを検出する方法は?

p_return_code次に、親トランザクションを確認してロールバックします。

編集:

私が考えているのは、内側の SP COMMIT または ROLLBACK が外側の SP TRANSACTION に影響を与えるということです。このコードは私にとってはうまくいきます。内部 SP が失敗すると、両方の挿入ステートメントがロールバックされます。ab() への最初の呼び出しが機能し、新しいユーザー レコードが挿入され、新しいゲーム レコードが挿入されます。ゲーム テーブルからレコードを削除して ab() を再度実行すると、ユーザー ID が既に存在するため、ゲーム テーブルの挿入がロールバックされます。

create procedure ab()
BEGIN
  START TRANSACTION;
    INSERT INTO games (title) VALUES ('bad game');
    CALL ba(@ret);
    IF @ret!=0 THEN
      ROLLBACK;
    ELSE
      COMMIT;
    END IF;
END;


create procedure ba(OUT return_value tinyint unsigned)
BEGIN
  DECLARE exit handler for sqlexception
  BEGIN
    set return_value = 1;
  END;

  INSERT INTO users (id) VALUES(1);
  set return_value = 0;
END;

使用をテストするにはcall ab();

于 2012-10-10T19:44:04.290 に答える