web-dev-qa-db-ja.com

MYSQLストアドプロシージャ:変数宣言と条件付きステートメント

私は数多くのチュートリアル、マニュアル、およびドキュメントを見てきましたが、これを機能させることはできません。

PhpMyAdminを使用してストアドプロシージャを作成しようとしています。

私はここでエラーを見つけることができないようです、SQLエラーはとても曖昧です...

CREATE PROCEDURE insertToonOneShot(IN locale CHAR(2), IN name VARCHAR(16), IN realm VARCHAR(24), IN faction CHAR(1), IN toon_level INT, IN class_name INT)
BEGIN
DECLARE @realmID INT;
DECLARE @classID INT;
DECLARE @toonID INT;
SET @realmID = SELECT id FROM realms WHERE realms.name = realm;
SET @classID = SELECT id FROM classes WHERE classes.name = class_name;
IF NOT @realmID IS NULL AND NOT @classID IS NULL AND @toonID IS NULL THEN
INSERT INTO 
toon (`locale`, `name`, `realm_id`, `faction`, `level`, `class_id`)
VALUES
(locale, name, @realmID, faction, toon_level, @classID);
END IF;
END;

私が今得ているエラーは次のとおりです。

#1064-SQL構文にエラーがあります。 @realmID INTの近くで使用する正しい構文については、MySQLサーバーのバージョンに対応するマニュアルを確認してください。 DECLARE @classID INT; DECLARE @toonID INT;行3の@reaを設定する

おそらく私がやらなければならなかったもっとイライラすることの一つ...

変数宣言で@記号を使用することを示す多くのチュートリアルをオンラインで見ましたが、それを使用しないチュートリアルや、DECLAREの代わりにVARを使用するチュートリアルも見ました。正しい構文は何ですか?...

12
Vigs

これはトリックを行います:

CREATE PROCEDURE insertToonOneShot(IN locale CHAR(2), IN name VARCHAR(16), IN realm VARCHAR(24), IN faction CHAR(1), IN toon_level INT, IN class_name VARCHAR(12))
BEGIN
SELECT @realmID := id FROM realms WHERE realms.name = realm;
SELECT @classID := id FROM classes WHERE classes.name = class_name;
SELECT @toonID := id FROM toon WHERE toon.name = name AND toon.realm_id = @realmID;
IF NOT @realmID IS NULL AND NOT @classID IS NULL AND @toonID IS NULL
THEN 
INSERT INTO toon (`locale`, `name`, `class_id`, `realm_id`, `faction`, `level`)
VALUES (locale, name, @classID, @realmID, faction, toon_level);
END IF;
END;
//

どうやら宣言文は不要でした...誰が知っていただろうか?

私を正しい方向に向けてくれたGordon Linoffに感謝します。

9
Vigs

サブクエリがある場合は、括弧が必要です。これらの行:

SET @realmID = SELECT id FROM realms WHERE realms.name = realm;
SET @classID = SELECT id FROM classes WHERE classes.name = class_name;

する必要があります:

SET @realmID = (SELECT id FROM realms WHERE realms.name = realm);
SET @classID = (SELECT id FROM classes WHERE classes.name = class_name);

または、さらに良いことに、setは必要ありません:

SELECT @realmID := id FROM realms WHERE realms.name = realm;
SELECT @classID := id FROM classes WHERE classes.name = class_name;
11
Gordon Linoff

古い質問ですが、@で始まるセッション変数とそうでない手続き変数を混同しているように思われることは言及する価値があると思います。

受け入れられたソリューションはエラーを解決しますが、変数がプロシージャの外部で定義されてから内部で使用される場合、変数スコープに関連する問題を引き起こす可能性があります。これを解決する正しい方法は、手続き変数のみを使用することです。

DELIMITER $$

CREATE PROCEDURE insertToonOneShot(
    IN locale CHAR(2),
    IN name VARCHAR(16),
    IN realm VARCHAR(24),
    IN faction CHAR(1),
    IN toon_level INT,
    IN class_name INT
)
BEGIN
    DECLARE realmID INT;
    DECLARE classID INT;

    SELECT id INTO realmID FROM realms WHERE realms.name = realm LIMIT 1;
    SELECT id INTO classID FROM classes WHERE classes.name = class_name LIMIT 1;
    IF realmID IS NOT NULL AND classID IS NOT NULL THEN
        INSERT INTO toon (`locale`, `name`, `realm_id`, `faction`, `level`, `class_id`)
        VALUES (locale, name, realmID, faction, toon_level, classID);
    END IF;
END$$

DELIMITER ;
9
miken32