プロが教える店舗&オフィスのセキュリティ対策術

このジャンルでお願いします。
次のようなテーブルで

DROP TABLE IF EXISTS item;

CREATE TABLE IF NOT EXISTS item (
id int(11) NOT NULL AUTO_INCREMENT,
parent_id INT,
name varchar(32) NOT NULL,
level int NOT NULL,
FOREIGN KEY (parent_id) REFERENCES item(id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO item (parent_id, name) VALUES (null, 'item1');
INSERT INTO item (parent_id, name) VALUES (1, 'item2');
INSERT INTO item (parent_id, name) VALUES (2, 'item3');
INSERT INTO item (parent_id, name) VALUES (3, 'item4');
INSERT INTO item (parent_id, name) VALUES (2, 'item5');
INSERT INTO item (parent_id, name) VALUES (null, 'item6');
INSERT INTO item (parent_id, name) VALUES (6, 'item7');
INSERT INTO item (parent_id, name) VALUES (null, 'item8');

DROP PROCEDURE IF EXISTS UPDATE_LEVEL;
DELIMITER //
CREATE PROCEDURE UPDATE_LEVEL()
BEGIN
DECLARE CNT INT;
DECLARE LVL INT;
SET LVL=1;
UPDATE item SET level=0;
UPDATE item
SET level=LVL
WHERE parent_id IS NULL;
SELECT COUNT(*) INTO CNT FROM item WHERE level=LVL;
WHILE CNT>0 DO
UPDATE item
INNER JOIN (SELECT id FROM item WHERE level=LVL) as temp ON parent_id=temp.id
SET item.level=LVL+1;
SET LVL=LVL+1;
SELECT COUNT(*) INTO CNT FROM item WHERE level=LVL;
END WHILE;
END
//
DELIMITER ;

DROP TRIGGER IF EXISTS TRG_INSERT_ITEM;
DELIMITER //
CREATE TRIGGER TRG_INSERT_ITEM AFTER INSERT ON item
FOR EACH ROW BEGIN
CALL UPDATE_LEVEL();
END;
//
DELIMITER ;

itemテーブルにinsertした場合にトリガーでUPDATE_LEVEL()を実行するようにしているのですが、
実際に挿入すると、

>Can't update table 'item' in stored function/trigger because it is already used by statment which invoked this stored function/trigger .

このようなエラーが出てしまいます・・・
UPDATE_LEVEL()にinsertらしき記述はないと思うのですが、
これはなぜこのようなエラーが出るのでしょうか?

A 回答 (3件)

外部キー制約とインサートのトリガーが競合していますね


外部キー制約はどうしてもいりますか?
    • good
    • 0
この回答へのお礼

ご回答有難うございます。
外部キー制約を次のように

DROP TABLE IF EXISTS item;
CREATE TABLE IF NOT EXISTS item (
id int(11) NOT NULL AUTO_INCREMENT,
parent_id INT,
name varchar(32) NOT NULL,
level int NOT NULL,
PRIMARY KEY(id)
) DEFAULT CHARSET=utf8;

外して試してみたのですが全く同じようなエラーでした・・・
外部キーって当然itemテーブルでのことですよね?
一応、自分としては外部キー制約があればもし削除した場合に
それに関連する行もついでに削除してくれるし、
あとphpmyadminなどを利用して閲覧するときにリンクが貼ってあってそのカラムを辿れるのが便利だなと思って
なんとなく使用しています。
そこら辺も含めて一般的に外部キー制約に対するyambejpさんのお考えがあれば
アドバイス頂けないでしょうか?

お礼日時:2014/09/26 17:04

あ、ごめんなさい


itemテーブルにデータをつっこんだときに
itemテーブル自信をアップデートするということですか?

http://dev.mysql.com/doc/refman/5.1/ja/routine-r …

その関数やトリガを実行したステートメントが ( 読み取り、または書込みに )
すでに使用しているテーブルを改変することはできない
・・・という制限があります
    • good
    • 0
この回答へのお礼

ご回答有難うございます。
なるほど、たしかにそうですね。
ではitemテーブルにデータを挿入した場合は次に
CALL UPDATE_LEVEL();
を呼び出す方法でしか更新する方法ないということなのでしょうか?
なにかこのテーブルに関しても自動的(トリガ的な感じで)に更新するやり方があれば良いのですが。。

お礼日時:2014/09/26 22:38

無限ループ処理になりそうなので無理だと思います



たしょうタイムラグはでますが
スケジュール管理用のテーブルをひとつ用意して、
コールしたいイベントが発生したときに管理テーブルのフラグをたて
イベントスケジューラでフラグが立っていたらcallしてフラグを消す
・・・的な処理を5分ごとに実行すればある程度目的は達成できるかと

どうしても即座に反映したければ、アプリケーション側でCALLする方が
確実ですが。
    • good
    • 0
この回答へのお礼

ご回答有難うございます。
なるほど、たしかにそのやり方だと大変そうですね。。
自分もアプリケーション側で呼び出すしかないのかなぁとは思っています。
とりあえず参考になりました。
ありがとうございます。

お礼日時:2014/09/30 12:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す