2017-11-14 11 views
0

10-12個のSQL文を実行するストアドプロシージャを構築しています。 1172、Result consisted of more than one rowというエラーが表示されます。どのステートメントが責任を持っているのか把握しようとしています。MySQLストアドプロシージャの終了ハンドラ内でSQL文を取得する

最も明白な方法は、エラーを発生させたステートメントのSQLを返すことです。ここで

は、私の終了ハンドラである:それはエラーを生成し、私のSQL文のどの私に教えてくれますように

DECLARE EXIT HANDLER FOR SQLEXCEPTION 
    BEGIN 
    GET DIAGNOSTICS @n = NUMBER, @c = ROW_COUNT; 
    GET DIAGNOSTICS CONDITION @n 
     @s = RETURNED_SQLSTATE, 
     @m = MESSAGE_TEXT, 
     @e = MYSQL_ERRNO; 
    ROLLBACK; 
    SELECT @s as RETURNED_SQLSTATE, @e as MYSQL_ERRNO, @m as MESSAGE_TEXT, @n as NUMBER, @c as ROW_COUNT; 
    END; 

は、私が何を追加することができますか?参考のため

は、ここに完全なストアドプロシージャです:

DROP PROCEDURE IF EXISTS `unlink_item`; 
CREATE PROCEDURE `unlink_item` ( 
    IN item_id   varchar(36), 
    IN parent_id  varchar(36), 
    IN author   varchar(64), 
    IN conversation_id varchar(36), 
    IN transaction_id varchar(36) 
) 
BEGIN 

    DECLARE EXIT HANDLER FOR SQLEXCEPTION 
    BEGIN 
    GET DIAGNOSTICS @n = NUMBER, @c = ROW_COUNT; 
    GET DIAGNOSTICS CONDITION @n 
     @s = RETURNED_SQLSTATE, 
     @m = MESSAGE_TEXT, 
     @e = MYSQL_ERRNO; 
    ROLLBACK; 
    SELECT @s as RETURNED_SQLSTATE, @e as MYSQL_ERRNO, @m as MESSAGE_TEXT, @n as NUMBER, @c as ROW_COUNT; 
    END; 

    START TRANSACTION; 

    SET @when = now(); 

    -- identify the record we are supposed to delete -- 
    SET @deleted = '123'; 
    SELECT `id` 
    FROM `item_contains` 
    WHERE `parent_id` = parent_id 
    AND `child_id` = item_id 
    INTO @deleted; 

    -- delete the record -- 
    DELETE FROM `item_contains` 
    WHERE `id` = @deleted; 

    -- update the change history for the item_contains table -- 
    INSERT INTO `change_history` (
    `date_time`, 
    `author`, 
    `action`, 
    `table_name`, 
    `record_id`, 
    `conversation_id`, 
    `transaction_id` 
) VALUES (
    @when, 
    author, 
    'delete', 
    'item_contains', 
    @deleted, 
    conversation_id, 
    transaction_id 
); 

    -- update the change history for the parent item -- 
    INSERT INTO `change_history` (
    `date_time`, 
    `author`, 
    `action`, 
    `table_name`, 
    `record_id`, 
    `conversation_id`, 
    `transaction_id` 
) VALUES (
    @when, 
    author, 
    concat('unlink from ',parent_id), 
    'item', 
    item_id, 
    conversation_id, 
    transaction_id 
); 

    -- update the change history for the item being unlinked -- 
    INSERT INTO `change_history` (
    `date_time`, 
    `author`, 
    `action`, 
    `table_name`, 
    `record_id`, 
    `conversation_id`, 
    `transaction_id` 
) VALUES (
    @when, 
    author, 
    concat('unlink ',item_id, ' from this'), 
    'item', 
    parent_id, 
    conversation_id, 
    transaction_id 
); 

    -- if the unlinked item is now orphaned either delete it if it is empty, or re-attach it somewhere to make it accessible -- 
    SET @instances = 0; 

    SELECT count(`id`) 
    FROM `item_contains` 
    WHERE `child_id` = item_id 
    INTO @instances; 

    IF (@instances = 0) THEN 

    SET @children = 0; 
    SELECT count(`id`) 
     FROM `item_contains` 
     WHERE `parent_id` = item_id 
     INTO @children; 

    IF (@children = 0) THEN 

     -- delete the now inaccessible item from the database -- 
     DELETE FROM `item` 
     WHERE `id` = item_id; 

     -- update the change history for that item -- 
     INSERT INTO `change_history` (
     `date_time`, 
     `author`, 
     `action`, 
     `table_name`, 
     `record_id`, 
     `conversation_id`, 
     `transaction_id` 
    ) VALUES (
     @when, 
     author, 
     'delete', 
     'item', 
     item_id, 
     conversation_id, 
     transaction_id 
    ); 

    ELSE 

     -- get the ID of the orphan folder -- 
     SET @orphan_id = '123'; 
     SELECT `id` 
     FROM `item` 
     WHERE `name` = '### orphans ###' 
     INTO @orphan_id; 

     -- move the item into the orphan folder -- 
     SET @inserted = uuid(); 
     INSERT INTO `item_contains` (
     `id`, 
     `parent_id`, 
     `child_id` 
    ) VALUES (
     @inserted, 
     @orphan_id, 
     item_id 
    ); 

     -- update the change history to reflect the orphaning of the item -- 
     INSERT INTO `change_history` (
     `date_time`, 
     `author`, 
     `action`, 
     `table_name`, 
     `record_id`, 
     `conversation_id`, 
     `transaction_id` 
    ) VALUES (
     @when, 
     author, 
     'orphaned', 
     'item', 
     item_id, 
     conversation_id, 
     transaction_id 
    ); 

    END IF; 

    END IF; 

    SELECT 
    0 AS `RETURNED_SQLSTATE`, 
    0 AS `MYSQL_ERRNO`, 
    'Item unlinked' AS `MESSAGE_TEXT`, 
    1 as `ROW_COUNT`; 

    COMMIT; 

END; 

UPDATE:私は左parent_idがあろうと想定していた

SELECT `id` FROM `item_contains` 
WHERE `parent_id` = parent_id 
AND `child_id` = item_id 

:根本的な問題は、最初のSELECT文でいましたitem_containsと右側のparent_idの1つがストアドプロシージャのパラメータになります。私は間違っていた。どちらもストアドプロシージャのパラメータとして解釈されます。

SELECT ic.id FROM item_contains AS ic 
WHERE ic.parent_id = parent_id 
AND ic.child_id = item_id 

もつとも:解決策はそうのように、エイリアス経由で表を別名とフィールドを参照した元の質問はまだ立って:

は、私は私のEXIT HANDLERに追加できるものがありますそれはエラーが発生した私のストアドプロシージャのどこに教えてくれるのでしょうか?

+0

SQLの例外を引き起こすSQL? –

+0

ストアドプロシージャでのデバッグは簡単ではありません。使用可能なデバッグ機能はありません。 –

+0

完全なMySQLコードを共有できませんか? –

答えて

1

すべてSELECT ... INTOステートメントは1行だけを返す必要があります。

例えば、以下のコードは、1つの以上のレコードを返すことがあります。あなたが別の変数とselectに結果を格納する文をデバッグすることができます

SELECT `id` 
    FROM `item_contains` 
    WHERE `parent_id` = parent_id 
    AND `child_id` = item_id 
    INTO @deleted; 

は:確認のみにする

SELECT count(*) 
    FROM `item_contains` 
    WHERE `parent_id` = parent_id 
    AND `child_id` = item_id 
    INTO @supposed_to_delete; 

SELECT @supposed_to_delete; /*you will see the value after execute*/ 

別の方法1つのレコード(推奨されない)は、aを追加していますlimit

SELECT `id` 
    FROM `item_contains` 
    WHERE `parent_id` = parent_id 
    AND `child_id` = item_id 
    LIMIT 1 /* <-- force to return only one record */ 
    INTO @deleted; 
+0

私はSELECT文を単独で実行すると動作します。ストアドプロシージャのコンテキストでのみ失敗します。一致するレコードは1つだけです。これは 'item_contains'テーブルの制約によって強制されるため、複数の値を返すことはできません。 –

+0

しかし、驚くことに、 'LIMIT 1 'を加えることはうまくいくようです。明らかに、一致する行が1つしかない場合でも、そのエラーをスローします。 –

+0

さて、 'どこで 'parent_id' = parent_id'が私がそれと思ったように解釈されていないことが判明しました。左側のものと右側のものは、どちらもストアドプロシージャのパラメータとして解釈されていました。 –

関連する問題