web-dev-qa-db-ja.com

フィールドを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、valuevarchar。

このように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

トリガーで可能ですか? (挿入後にレコードを更新できることはわかっていますが、トリガーがある方が良いでしょう。)

17
szeryf

トリガーを使用しても、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();
29
Bill Karwin

受け入れられた答えのように、私はここで答えています ビルカーウィン 状態:

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 ;
1
Nabeel Ahmed

これは私のために働きます

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 ;
1

私はこれがあなたのために働くと信じています

私は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)
0
Justin Giboney