web-dev-qa-db-ja.com

MySQL-挿入後に同じテーブルを更新するトリガー

これが私がやろうとしていることです:

テーブルINSERTに新しいACCOUNTSがある場合、ACCOUNTSの行を更新する必要があります。ここで、pk = _NEW.edit_on_は_status='E'_は、特定の(古い)アカウントが編集されたことを示します。

_DELIMITER $$

DROP TRIGGER IF EXISTS `setEditStatus`$$
CREATE TRIGGER `setEditStatus` AFTER INSERT on ACCOUNTS
FOR EACH ROW BEGIN
    update ACCOUNTS set status='E' where ACCOUNTS.pk = NEW.edit_on ;
END$$

DELIMITER ;
_

要件は[〜#〜] not [〜#〜]で、新しく挿入した列、ただし_pk = NEW.edit_on_を持つalready existing

ただし、同じテーブルを更新することはできません:_Can't update table ACCOUNTS ... already used by the statement that invoked this trigger_

回避策を提案してください

PS:私はすでに 同じテーブルの更新後にトリガーのテーブルを更新する同じテーブルトリガーmysqlに挿入する同じの後に挿入トリガーで更新するテーブル および テーブルへの挿入後の挿入および更新を伴うmysqlトリガー しかし、彼らは私の質問に答えていないようです。

編集

ACCOUNTSテーブル:

_CREATE TABLE  `ACCOUNTS` (
  `pk` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(9) unsigned NOT NULL,
  `edit_on` bigint(10) unsigned DEFAULT NULL,
  `status` varchar(1) NOT NULL DEFAULT 'A',
  PRIMARY KEY (`pk`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=2147483726 DEFAULT CHARSET=latin1
_
22
th3an0maly

このすべてをトリガーで行うことはできないようです。 ドキュメント によると:

ストアド関数またはトリガー内では、関数またはトリガーを呼び出したステートメントによって既に(読み取りまたは書き込み用に)使用されているテーブルを変更することはできません。

この答え によると、次のようにする必要があるようです:

ターゲットテーブルに挿入/更新するストアドプロシージャを作成し、すべてトランザクションで他の行を更新します。

ストアドプロシージャを使用すると、変更を手動でコミットします(挿入と更新)。 MySQLでこれを行ったことはありませんが、 この投稿 は良い例のように見えます。

23
pjama

これは、挿入時に同じテーブルの行を更新する方法です

activationCodeとemailは、テーブルUSERの行です。挿入時にactivationCodeの値を指定しないと、mysqlによってその場で作成されます。

「username」をmysqlユーザー名に、「db_name」をdb名に変更します。

CREATE DEFINER=`username`@`localhost` 
       TRIGGER `db_name`.`user_BEFORE_INSERT` 
       BEFORE INSERT ON `user` 
       FOR EACH ROW
         BEGIN
            SET new.activationCode = MD5(new.email);
         END
9
Rangel

同じ問題がありましたが、入力しようとしているIDで列を更新する必要があったので、更新を行う前に行う必要があります。

DELIMITER $$
DROP TRIGGER IF EXISTS `codigo_video`$$
CREATE TRIGGER `codigo_video` BEFORE INSERT ON `videos` 
FOR EACH ROW BEGIN
    DECLARE ultimo_id, proximo_id INT(11);
    SELECT id INTO ultimo_id FROM videos ORDER BY id DESC LIMIT 1;
    SET proximo_id = ultimo_id+1;
    SET NEW.cassette = CONCAT(NEW.cassette, LPAD(proximo_id, 5, '0'));
END$$
DELIMITER ;
5
JCLG

最後のエントリ。これは別のトリックです:

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_schema = ... and table_name = ...
2
Raymond B

デリミター$$

トリガーが存在する場合のドロップsetEditStatus $$ CREATE TRIGGER setEditStatus[〜#〜] before [〜#〜]各行のアカウントに挿入

SET NEW.STATUS = 'E';

END $$

区切り記号;

0
KenZo

代わりに、特定のテーブルの挿入前に使用してmax pkidを取得し、maximium pkidテーブルレコードを更新できます。