私のデータベースにはテーブルがあります。Employee
再帰的な関連付けにより、従業員は他の従業員の上司になることができます。
テーブルの説明:
mysql> DESC Employee;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| SSN | varchar(64) | NO | PRI | NULL | |
| name | varchar(64) | YES | | NULL | |
| designation | varchar(128) | NO | | NULL | |
| MSSN | varchar(64) | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+-------+
従業員テーブルの現在の状態は次のとおりです。
mysql> SELECT * FROM Employee;
+-----+------+-------------+------+
| SSN | name | designation | MSSN |
+-----+------+-------------+------+
| 1 | A | OWNER | 1 |
| 2 | B | BOSS | 1 |
| 3 | C | WORKER | 2 |
| 4 | D | BOSS | 2 |
| 5 | E | WORKER | 4 |
| 6 | F | WORKER | 1 |
| 7 | G | WORKER | 4 |
+-----+------+-------------+------+
7 rows in set (0.00 sec)
以下は、テーブル内の行間の階層関係です。
A
/ \
B F
/ \
c D
/ \
G E
INSERT に次の制約を課したかったのです。
- 従業員は自分自身を BOSS することはできません。これは OWNER のみに許可されます。したがって、クエリのように。
INSERT INTO Employee VALUES ("8", "H", "BOSS", "8");
断るべきです。 - 新しい
OWNER
ものを挿入できます。
私は 5.5 より前の MYSQL バージョンを使用しているため (シグナルをサポートしていません)。そのため、ストアド プロシージャで あるmy_singal()
を使用しています。
このように書かれています:
CREATE PROCEDURE `my_signal`(in_errortext VARCHAR(255)) BEGIN SET @sql=CONCAT('UPDATE `', in_errortext, '` SET x=1'); PREPARE my_signal_stmt FROM @sql; EXECUTE my_signal_stmt; DEALLOCATE PREPARE my_signal_stmt; END//
そして、制約を適用するwritten a Trigger
には、私はそれを知るようになりましたcheck constraints are not yet implemented in MySQL
!
DELIMITER $$ CREATE TRIGGER `employee_before_insert` BEFORE INSERT ON `Employee` FOR EACH ROW BEGIN CASE WHEN NEW.designation = 'OWNER' THEN CALL my_signal('Error: can not insert new OWNER !'); WHEN NEW.SSN = NEW.MSSN THEN CALL my_signal('Error: Row can not reference itself!'); END CASE; END$$ DELIMITER ;
正常にコンパイルされ、データベースにロードされました。しかし、挿入しようとしたとき:
mysql> INSERT INTO Employee VALUES ("12", "K", "BOSS", "12");
ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger
- SQL プリペアド ステートメント (PREPARE、EXECUTE、DEALLOCATE PREPARE) はストアド プロシージャで使用できますが、ストアド ファンクションまたはトリガーでは使用できません。したがって、ストアド関数とトリガーは動的 SQLを使用できません(ステートメントを文字列として構築してから実行する場合)。
少し努力した後、以下のように別のトリガーを書くことができました。私の要件に従って正常に動作しています。
mysql> CREATE -> TRIGGER `employee_before_insert` BEFORE INSERT -> ON `Employee` -> FOR EACH ROW BEGIN -> IF UCASE(NEW.designation) = 'OWNER' THEN /*UCASE*/ -> UPDATE `Error: can not insert new OWNER !` set x=1; -> END IF; -> IF (NEW.SSN = NEW.MSSN) THEN -> UPDATE `Error: Row can not reference itself!` set x=1; -> END IF; -> END$$ Query OK, 0 rows affected (0.08 sec) mysql> DELIMITER ; mysql> INSERT INTO Employee VALUES ("12", "K", 'owner', "11"); ERROR 1146 (42S02): Table 'dumy.Error: can not insert new OWNER !' doesn't exist mysql> INSERT INTO Employee VALUES ("12", "K", 'Ajay', "12"); ERROR 1146 (42S02): Table 'dumy.Error: Row can not reference itself!' doesn't exist
私はすでに多くの手順で使用しており、関数が再びmy_signal()
必要になる多くの新しいストアド関数とトリガーを作成する必要があるためです。my_signal()
It would also good for easy manipulation if sometime MYSQL version upgraded to 5.5(+)
.
カスタマイズされたエラーメッセージを出力できる my_signal() を書く他の方法を誰かが提案できますか?
私は次のように試しました:
区切り記号 $$
CREATE PROCEDUREmy_signal
(in_errortext VARCHAR(255))
DECLARE sql varchar(512);
始める
SET sql=CONCAT('UPDATE', in_errortext, '
SET x=1');
UPDATE sql SET x =1;
END$$
しかし、役に立たない:(。
これについて私を助けてください.私は非常に感謝します!
私は MYSQL 特に @ ストアド プロシージャが苦手です。
ここでシステムを試してみたい場合は、このデータベースを構築する ためのコマンドをすぐに見つけることができます。
編集 ~コンパイラとして動作する MySQL インタープリター!
トリガーとストアド関数から 動的 SQLステートメントを呼び出すことはできません。
すべての格納されたルーチンで同じインターフェイス my_signal() を維持するために、my_signal(); を変更しました。Static SQL
ステートメントを追加しDynamic SQL
、トリガーから実行されないことを確認しました。許されるべきだと思いましたbecause MySQL is an interpreter not a compiler
。
新しい my_signal()
DELIMITER $$
CREATE PROCEDURE `my_signal`(in_errortext VARCHAR(255))
BEGIN
IF in_errortext = 'ERROR_INSERT_OWNER' THEN /* Static SQL*/
UPDATE `Error: can not insert new OWNER !` set x=1;
END IF;
IF in_errortext = 'ERROR_INSERT_SELF_REFERENCE' THEN /* Static SQL*/
UPDATE `Error: Row can not reference itself!` set x=1;
ELSE /* Dynamic SQL*/
SET @sql=CONCAT('UPDATE `', in_errortext, '` SET x=1');
PREPARE my_signal_stmt FROM @sql;
EXECUTE my_signal_stmt;
DEALLOCATE PREPARE my_signal_stmt;
END IF;
END$$
新しいトリガー
DELIMITER $$
CREATE
TRIGGER `employee_before_insert` BEFORE INSERT
ON `Employee`
FOR EACH ROW BEGIN
CASE
WHEN UPPER(NEW.name) = 'OWNER' THEN
CALL my_signal('ERROR_INSERT_OWNER');
WHEN NEW.SSN = NEW.MSSN THEN
CALL my_signal('ERROR_INSERT_SELF_REFERENCE');
END CASE;
END$$
DELIMITER ;
うまくいけば、私は挿入しようとしました:
mysql> INSERT INTO Employee VALUES ("9", "X", "WOKER", "9" );
ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger
mysql> INSERT INTO Employee VALUES ("9", "X", "OWNER", "9" );
ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger
おっとっと!コンパイラのように動作しますが、インタプリタではありません。そうじゃない?
編集:答え
幸運にも質問を編集しているときに、RolandoMySQLDBAから回答を得ました。
回答はこちら
最後に:トリガーで動的 SQL を実行できないことは理解できました。my_signal() のコーディングに頼る必要があるかもしれません。MySQL にはまだ他のオプションはありません。