私のデータベースには次のテーブルがあります。
TAG
----------------------
| tag_id | tag_name |
----------------------
TAG_VALUE: Stores values associated to each tag
----------------------------------------
| tag_id | insertion_timestamp | value |
----------------------------------------
ALARM: Defines alarms for each tag
-------------------------------------
| alarm_id | tag_id | function_name |
-------------------------------------
ALARM ACTIVATION: Stores information regarding each time the alarms were triggered
-----------------------------------------------------
| alarm_id | activation_timestamp | activation_value|
-----------------------------------------------------
したがって、新しい値がTAG_VALUEに挿入されるたびに、その新しい値がそのタグに関連付けられているアラームをトリガーするかどうかを確認する必要があります。アラーム間に共通の基準がないので、アラームをトリガーするかどうかを決定するために後で使用される関数名を保存しています。
TAG_VALUEには次のAFTER_INSERTトリガーがあります:
CREATE DEFINER=`root`@`localhost` TRIGGER `mydb`.`tag_value_AFTER_INSERT` AFTER INSERT ON `tag_value` FOR EACH ROW
BEGIN
call sp_alarm_handler(NEW.tag_value, NEW.tag_id);
END
また、sp_alarm_handlerは次のようにコーディングされています。
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_alarm_handler`(IN tag_value VARCHAR(255), IN value_tag_id INT(11))
BEGIN
DECLARE exit_loop BOOLEAN;
DECLARE v_alarm_id INT(11);
DECLARE function_name VARCHAR(255);
DECLARE value_triggers_alarm TINYINT(1);
DECLARE custom_alarm_cur CURSOR FOR
Select alarm_id, function_name From vw_custom_alarms where tag_id = value_tag_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN custom_alarm_cur;
custom_alarm_lp: LOOP
FETCH custom_alarm_cur into v_alarm_id, function_name;
IF exit_loop THEN
leave custom_alarm_lp;
END IF;
#************************************************
#*********HERE'S THE DYNAMIC SQL PIECE'**********
#************************************************
set @query = CONCAT('Select ',function_name,'(',tag_value,')', 'into @value_triggers_alarm');
PREPARE stmt FROM @query;
Execute stmt;
IF fn_is_alarm_active(v_alarm_id) = 0 THEN
If @value_triggers_alarm = 1 THEN
INSERT INTO alarm_activation(alarm_id, activation_timestamp, activation_value)
VALUES (v_alarm_id, NOW(), tag_value);
end if;
ELSE IF @value_triggers_alarm = 0 THEN
call sp_deactivate_alarm(v_alarm_id);
END IF;
END IF;
END LOOP custom_alarm_lp;
Close custom_alarm_cur;
END
これによりエラー1336:1336:動的SQLはストアドファンクションまたはトリガーでは許可されません私の場合、回避策はありますか?
チェックする項目のリストが一定である場合は、テストを構築するのではなく、それらを詳しく説明してください。 (実行不可能)
しかし、おそらくそうではありません...
プランA:トリガーを呼び出す必要があるINSERT
をPROCEDURE
呼び出しに置き換えます。このルーチンには、INSERT
に加えて、提示した残りのコードが含まれています。
プランB:プランAと同じですが、アプリケーションコードで行います。
注:AまたはBのどちらかをBEGIN
...COMMIT
でラップして、「アトミック」にします。
結論:トリガーはすべてを実行できるわけではありません。
Aの適用(これにより、他のユーザーがストアドプロシージャをバイパスするのを防ぐことができると思います。)
CREATE USER special@... ...
-新しいユーザーGRANT INSERT ON db.tbl TO special@...
-入るSECURITY special@...
-procを「特別な」ものとして実行し、INSERTs
を実行できるようにしますINSERT PRIVILEGE
他のテーブルから。 (これは乱雑になるか、おそらく不要になります。)(テーブルが現在誰もアクセスできない別のデータベースにある場合、may役立ちます。)