3

A と B など、2 つの同様のテーブルがあります。A への挿入を B に複製し、B への挿入を A に複製して、2 つのユーザー システムを統合したいと考えています。それぞれに「トリガーの挿入後」を構成しました。例:

DELIMITER $$
CREATE DEFINER = `root`@`localhost` TRIGGER
`after_A_INSERT`
AFTER INSERT ON `A`
FOR EACH ROW BEGIN 
INSERT INTO `B`
SET `id` = NEW.`id`,`name` = NEW.`name`;
END$$
DELIMITER ;

DELIMITER $$
CREATE DEFINER = `root`@`localhost` TRIGGER
`after_B_INSERT`
AFTER INSERT ON `B`
FOR EACH ROW BEGIN 
INSERT INTO `A`
SET `id` = NEW.`id`,`name` = NEW.`name`;
END$$
DELIMITER ;

Aに挿入すると、トリガーはBの挿入を呼び出しますが、この挿入はBでトリガーを実行し、デッドロックが発生して無限ループを回避します。

トリガーを編集して、INSERT を実行する前に別のテーブル トリガーを DROP し、その後にもう一度 CREATE しようとしました。例:

DELIMITER $$
CREATE DEFINER = `root`@`localhost` TRIGGER
`after_B_INSERT`
AFTER INSERT ON `B`
FOR EACH ROW BEGIN 
DROP TRIGGER IF EXISTS `after_A_INSERT`;
INSERT INTO `A`
SET `id` = NEW.`id`, `name` = NEW.`name`;
/* And CREATE again here */
END$$
DELIMITER ;

ただし、CREATE は暗黙的なコミットを行うデータ定義言語 (DDL) ステートメントです。したがって、これはできません。

コミットを明示的に処理するために、内部に DROP を指定して PROCEDURE を呼び出そうとしましたが、それもできません。

この 2 つのテーブルをミラーリングするための提案はありますか?


更新: Bill Karwinの 提案を使用して、各テーブルにフィールドを追加originし、それぞれのデフォルト値AまたはB. 次に、次のようにトリガーを変更 (DROP および reCREATE) します。

A のトリガー:

...
BEGIN 
IF NEW.`origin`='A' THEN
    INSERT INTO `B`
        SET `id` = NEW.`id`, `name` = NEW.`name`,  `origin` = NEW.`origin`;
    END IF;
END

B のトリガー:

...
BEGIN 
IF NEW.`origin`='B' THEN
    INSERT INTO `A`
        SET `id` = NEW.`id`, `name` = NEW.`name`, `origin` = NEW.`origin`;
    END IF;
END
4

1 に答える 1

4

サイクルを作成しないようにするには、何らかの方法が必要です。

origin両方のテーブルに列を追加することをお勧めします。表 A で、 を作成しDEFAULT 'A'ます。表 B で、 を作成しDEFAULT 'B'ます。

アプリケーションでいずれかのテーブルに挿入する場合は、常にorigin列を省略して、デフォルト値を使用できるようにします。

NEW.origin両方のトリガーで、がそれぞれのテーブルのデフォルトと等しい場合にのみ、他のテーブルに複製します。


あなたのコメントと新しいエラーについて:

申し訳ありませんが、他のテーブルに挿入するときのトリガーで、の値もコピーする必要があることを忘れていましたNEW.origin。アプリケーションで元の挿入を行うときに省略しますorigin

A のトリガー:

...
BEGIN 
IF NEW.`origin`='A' THEN
    INSERT INTO `B`
        SET `id` = NEW.`id`, `name` = NEW.`name`, `origin` = NEW.`origin`;
    END IF;
END

B のトリガー:

...
BEGIN 
IF NEW.`origin`='B' THEN
    INSERT INTO `A`
        SET `id` = NEW.`id`, `name` = NEW.`name`, `origin` = NEW.`origin`;
    END IF;
END

これらのトリガーを作成してテストしました。

mysql> insert into A set name = 'bill';
Query OK, 1 row affected (0.00 sec)

mysql> insert into B set name = 'john';
Query OK, 1 row affected (0.01 sec)

mysql> select * from A;
+----+------+--------+
| id | name | origin |
+----+------+--------+
|  1 | bill | A      |
|  2 | john | B      |
+----+------+--------+
2 rows in set (0.00 sec)

mysql> select * from B;
+----+------+--------+
| id | name | origin |
+----+------+--------+
|  1 | bill | A      |
|  2 | john | B      |
+----+------+--------+
于 2014-10-06T16:24:33.837 に答える