【问题标题】:MySQL trigger for insert with no primary key没有主键的插入的 MySQL 触发器
【发布时间】:2019-06-26 11:50:11
【问题描述】:

如果插入语句中未说明该字段,我正在尝试创建一个创建主键的触发器。 例如:

insert into mydb.mytable (nonprimarykeyfield) values ('test');

触发器是

CREATE DEFINER=`root`@`%` TRIGGER `mydb`.`mytable_BEFORE_INSERT` 
BEFORE INSERT ON `mytable` 
FOR EACH ROW
    BEGIN
        if NEW.pk is null then 
            SET NEW.pk = UUID();
        end if;
        set new.created_at=now();
    END

插入失败

Error Code: 1062. Duplicate entry '' for key 'PRIMARY'

但是没有以null为主键的行。

【问题讨论】:

  • 你有充分的理由使用UUID()进行PK吗?
  • UUID - 想要安全的唯一标识符
  • “UUID - 想要安全的唯一标识符”-> PRIMARY KEY AUTO_INCREMENT 是 MySQL 中唯一有保证的唯一标识符。UUID() 仍然可以非常非常重复小机会.. 除了使用UUID() 作为 PK 时,您更“不对齐”您的 Btree 结构,因为UUID() 更随机意味着选择速度更快,而不是PRIMARY KEY AUTO_INCREMENT .. 也因为 InnoDB 将主键的副本存储在二级索引您的二级索引将变得比PRIMARY KEY AUTO_INCREMENT 大得多...
  • @Raymond Nijland - 这是很有价值的建议
  • “UUID - 想要安全的唯一标识符” 如果您不想将 PRIMARY KEY AUTO_INCREMENT 暴露给外界,这可能是很容易理解的,因为其他人可能知道您在一年中所做的客户/订单的数量作为一个有效的例子。您可以选择添加索引的UUID() 列(可能生成为Generated Column)来选择..:另外请确保除此之外还有一个PRIMARY KEY AUTO_INCREMENT,因为这在 InnoDB 引擎中非常重要..

标签: mysql triggers insert


【解决方案1】:

显然,NEW.pk 不为空,因此它没有得到UUID 的结果。如果您按照您的描述运行insert,而不指定pk 的值,那么它有一个default,这会导致重复问题。运行

show create table mytable;

了解更多信息。

编辑:

此外,您可以使用 auto_increment 代替触发器。

【讨论】:

  • 我曾希望如果使用默认值(NULL),那么这将是 if 块
  • @Datadimension 您可以编辑您的问题并添加 show create table mytable 的结果吗?这将是非常有用的。
【解决方案2】:

我意识到,由于主键是 varchar,它显然不能为空(尽管令人困惑的是 MySQL Workbench 允许在“alter table”中设置它,它会立即恢复为“”。这就是问题的原因。 因此,应该在 'if' 块中检查 ''。 我已按如下方式更改了触发器并按预期插入工作

CREATE DEFINER=`root`@`%` TRIGGER `mydb`.`mytable_BEFORE_INSERT` BEFORE INSERT ON `mytable` FOR EACH ROW
BEGIN
    if NEW.pk ='' then 
        SET NEW.pk = UUID();
    end if;
    set new.created_at=now();
END

补充评论: 作为讨论点,上面来自 Raymond Nijland 的 cmets 应该阅读有关数据库性能和设计的内容。好东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2016-10-13
    • 2010-09-24
    • 1970-01-01
    相关资源
    最近更新 更多