MySQL触发器将字段更新为id值

时间:2009-07-31 10:20:00

标签: mysql insert triggers

我希望有一个触发器来执行插入记录的以下操作:

 # pseudocode
 if new.group_id is null
    set new.group_id = new.id
 else
    # don't touch it
 end

更清楚地说:我有一个包含三列的表: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

是否可以使用触发器? (我知道我可以在插入后更新记录,但触发器会更好。)

6 个答案:

答案 0 :(得分:27)

即使使用触发器,我也不知道如何在一个声明中做到这一点。

@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为空,则默认为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();

答案 1 :(得分:1)

我在这里回答,如接受的答案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 ;

答案 2 :(得分:1)

这对我有用

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 ;

答案 3 :(得分:0)

我相信这对你有用

我有两张桌子

test_b: a_id, value
test_c: a_id, value

这是插入测试b的触发器。它检查a_id是否为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)

答案 4 :(得分:-2)

此触发器应该按照您的要求执行。

   CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
          IF new.group_id IS NULL
            SET new.group_id = new.id
          END IF
      END;

它是从MYSQL documentation页面中非常相似的示例复制而来的。

答案 5 :(得分:-3)

在这种情况下,触发器似乎有些过分。只需应用默认值。

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'
)