【问题标题】:MySQL Trigger To Update New RowMySQL 触发器更新新行
【发布时间】:2011-07-07 16:00:03
【问题描述】:

我们正在 2 个系统之间迁移,需要为我们的一个数据库表提供 2 个字段,这些字段始终保持同步。这是表结构:

CREATE TABLE `example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `object_id` int(11) NOT NULL DEFAULT '0',
  `value` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `object_id` (`object_id`)
);

每次其中一个系统插入新行时,我们都需要将 object_id 设置为 id。我们不能使用'before insert',因为 id 列是一个 auto_increment 列,所以它在 insert 之前的值为 NULL,并且由于 MySQL 'after insert' 对触发器的限制,我不能执行以下操作:

CREATE TRIGGER insert_example 
  AFTER INSERT ON  example 
  FOR EACH ROW 
  SET NEW.object_id = NEW.id;

我无法更新任一系统的代码,因此我需要一种在数据库端完成此操作的方法。两个系统都将插入新行。我怎样才能做到这一点?

【问题讨论】:

    标签: mysql sql triggers


    【解决方案1】:

    使用在插入操作之前触发的触发器

    CREATE TRIGGER insert_example 
      BEFORE INSERT ON  example 
      FOR EACH ROW 
      SET NEW.object_id = NEW.id;
    

    编辑:

    正如 OP 指出的那样,NEW.id 不适用于自动增量;一个可以使用以下触发器(使用风险自负):

    CREATE TRIGGER insert_example 
          BEFORE INSERT ON  example 
          FOR EACH ROW 
          SET NEW.object_id = (
                SELECT AUTO_INCREMENT 
                FROM information_schema.TABLES 
                WHERE TABLE_SCHEMA = DATABASE() 
                AND TABLE_NAME = 'example'
          );
    

    但我宁愿重新考虑这个有点奇怪的要求——为什么表中需要两次 pk 值?

    【讨论】:

    • 之前不能使用,因为 NEW.id 是在插入时生成的,所以在插入之前它的值为 0。
    【解决方案2】:

    您有什么理由不能使用BEFORE INSERT 触发器吗?

    我一直将AFTER INSERT 触发器视为一种操作其他表而不是对其执行触发器的表的方法。

    经验法则,操作触发器正在运行的表 = BEFORE INSERT,操作其他表 AFTER INSERT :)

    【讨论】:

    • 之前不能使用,因为 NEW.id 是在插入时生成的,所以在插入之前它的值为 0。
    • 啊,有道理。忽略了它是一个 auto_increment 字段的事实,抱歉。想想你有点卡在这里。无论如何,您可以修复数据库设计并摆脱冗余数据吗? (就像把它标准化一点)
    • 不。不幸的是,在系统之间的迁移过程中,我们不得不忍受这种情况。一个系统使用 ID 字段,而另一个系统使用 OBJECT_ID 字段。两者都需要存在并同步。
    • 好吧,wonk0 为您提供了一个潜在的解决方案。我从来不敢(或需要)直接从信息模式中直接读取。如果你和我有同样程度的偏执狂。您也许可以引入一个丑陋的黑客(但是嘿,丑陋的黑客似乎已经开始了:P)并引入一个“hacktable”,使用 AFTER INSERT 写入,然后在“hacktable”上触发更新'例子'
    • 这也是我的想法。不知道为什么 MySQL 不允许这个漂亮的触发器,因为它可以通过两个触发器和一个 hack 表来完成。
    【解决方案3】:

    我认为您的触发器一开始就永远不会创建,因为您不能在 AFTER INSERT 触发器中引用 NEW.column_name。

    尝试在 BEFORE INSERT 触发器中执行此操作(请忽略此修复,因为它不起作用):

    CREATE TRIGGER `insert_example` BEFORE INSERT ON `t`
    FOR EACH ROW 
    SET NEW.`object_id` = NEW.`id`;
    

    请根据您的架构更改表名和列名。

    希望这会有所帮助。

    【讨论】:

    • 之前不能使用,因为 NEW.id 是在插入时生成的,所以在插入之前它的值为 0。
    • 没错@Russell C,我想我在这里混淆了两件事。无论如何,谢谢你纠正我
    猜你喜欢
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2013-01-02
    • 1970-01-01
    相关资源
    最近更新 更多