フィールドをidの値に更新するMySQLトリガー
質問
挿入されたレコードに対して次の操作を実行するトリガーが欲しい:
# pseudocode
if new.group_id is null
set new.group_id = new.id
else
# don't touch it
end
より明確に:3つの列を持つテーブルが1つあるとします: id
主キー、 group_id
int、 value
varchar。
そのような group_id
で挿入すると:
INSERT INTO table(value, group_id) VALUES ('a', 10)
欲しいのは:
id | group_id | value
---+----------+------
1 | 10 | a
しかし、 group_id
を省略すると:
INSERT INTO table(value) VALUES ('b')
このレコードの id
に自動的に設定される必要があります:
id | group_id | value
---+----------+------
2 | 2 | b
トリガーで可能ですか? (挿入後にレコードを更新できることはわかっていますが、トリガーを使用する方が良いでしょう。)
解決
トリガーを使用しても、1つのステートメントでこれを行う方法はわかりません。
@Luckyが提案したトリガーソリューションは、MySQLでは次のようになります。
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
SET NEW.group_id = COALESCE(NEW.group_id, NEW.id);
END
ただし、問題があります。 BEFORE INSERT
フェーズでは、自動生成された id
値はまだ生成されていません。したがって、 group_id
がnullの場合、デフォルトは NEW.id
であり、常に0です。
ただし、 AFTER INSERT
フェーズ中にこのトリガーを起動するように変更すると、生成された NEW.id
の値にアクセスできるため、列を変更できません値。
MySQLは列の DEFAULT
の式をサポートしていないため、テーブル定義でもこの動作を宣言できません。
唯一の解決策は、 INSERT
を実行し、設定されていない場合はすぐに UPDATE
を実行して group_id
を変更することです。
INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a');
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID();
他のヒント
ここで回答しています。受け入れられている回答ビルカーウィンは次のように述べています。
BEFORE INSERTフェーズでは、自動生成されたid値は まだ生成されています。したがって、group_idがnullの場合、デフォルトはNEW.idになります。 常に0です。
私はそれに対する答えを持っています-OP(および来るべき訪問者)にとって、ここにいくつかのポイントがあります: トリガーが呼び出される場所からテーブルを更新することはできません。そのため、エラー1442 が表示されます:
Error Code: 1442
Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
1。新しい行を更新する
BEFORE INSERT ON
トリガーを使用して、この方法で新しい行のすべてのフィールドを更新できます。これには、NEW演算子、つまり
set NEW.group_id = NEW.id
2。挿入前にauto_increment値を取得:
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable'
要約すると、 'dのトリガーSQLは次のようになります:
DELIMITER //
DROP TRIGGER IF EXISTS MyTrigger//
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
IF new.group_id IS NULL
set @auto_id := (SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA=DATABASE() );
set NEW.group_id = @auto_id;
ENF IF;
END;
//
DELIMITER ;
これは私のために動作します
DELIMITER $
CREATE TRIGGER `myTriggerNameHere`
BEFORE INSERT ON `table` FOR EACH ROW
BEGIN
SET NEW.group_id = IF(NEW.group_id IS NULL, LAST_INSERT_ID()+1, NEW.group_id);
END;
$
DELIMITER ;
これはあなたに役立つと信じています
2つのテーブルがあります
test_b: a_id, value
test_c: a_id, value
そして、ここにテストbの挿入のトリガーがあります。 a_idがnullであるかどうかを確認し、nullである場合は0を挿入します
CREATE TRIGGER test_b AFTER INSERT ON test_b
FOR EACH ROW
INSERT INTO test_c (a_id, value) VALUES (IFNULL(NEW.a_id, 0),NEW.value)
このトリガーは、あなたが要求したことを行うはずです。
CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
IF new.group_id IS NULL
SET new.group_id = new.id
END IF
END;
この状況では、トリガーは過剰に思えます。デフォルトを適用するだけです。
CREATE TABLE `test` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`value` varchar(100) NOT NULL,
`group_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '2'
)