MySQL Procedureでハマったこと

Procedureって何?

複数のクエリを一気に実行できる関数みたいな便利な機能です
sqliteにはないので注意してください
詳しい説明は
ここここここ

登録するとき

procedureを使うにはまず登録する必要があります
登録する方法は下のようにすればいいですがすでに登録してあった場合は実行するとエラーになります

CREATE PROCEDURE add_count(IN _xuid BIGINT, IN _item VARCHAR(99), IN _count INT)
BEGIN;
    SET @int_value = NULL;
    SELECT count
    INTO @int_value
    FROM StackStorage
    WHERE xuid = _xuid
      AND item = _item;
    IF @int_value IS NULL
    THEN
        if _count > 0
        then
            INSERT INTO StackStorage
            VALUES (_xuid, _item, _count);
        end if;
    ELSE
        SET @last_count = _count + cast(@int_value as INTEGER);
        if @last_count > 0
        then
            UPDATE StackStorage
            SET count = @last_count
            WHERE xuid = _xuid
              AND item = _item;
        else
            DELETE
            FROM StackStorage
            WHERE xuid = _xuid
              AND item = _item;
        end if;
    END IF;
END;

テーブルを作成するときみたいにIF NOT EXISTSを付ければと思いましたがなんとprocedureにはない!
見つけた解決策は下のようにすでに登録している場合は削除するという方法でした

DROP PROCEDURE IF EXISTS add_count;

IF NOT EXISTSと比べて不効率な気もしますが短期間で何回も実行するわけではないしprocedureを変更したときも反映されるので気にしないことにします

SELECT INTOで複数のデータを受け取れない

そのまんまの意味でSELECTで必ず一つのデータに絞らないとエラーが出ます
DECLAREという存在を知らなかった

SELECT count
INTO @int_value
FROM StackStorage
WHERE xuid = _xuid
  AND item = _item;

SELECT INTOで型が引き継がれる

もし指定したデータのカラムが UNSIGNDだったらマイナスを入れれないってことです
それはいいとして自分の場合はINTのデータ(_count) + INT UNSIGNDのデータ(@int_value)を足した結果がマイナスになるとエラーが出ました
なぜ厳しい方が優先されるんですか???
解決策は下のようにキャストするだけです

SELECT count
INTO @int_value
FROM StackStorage
WHERE xuid = _xuid
  AND item = _item;
SET @last_count = _count + @int_value;

ree

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です