【问题标题】:MySQL - Trigger - Before Insert and using the SK (Auto Increment)MySQL - 触发器 - 在插入之前并使用 SK(自动增量)
【发布时间】:2015-04-14 20:17:54
【问题描述】:

我在 MySQL 中有一个简单的帖子表,它有一个 POST_ID 作为 SK(代理键)。 对原始帖子 ID 的回复存储在同一个表的 PARENT_POST_ID 列中,但我想执行以下逻辑:

插入前(我认为...)

如果在 INSERT 上没有定义 PARENT_POST_ID ,则将行值默认为新生成的 POST_ID(来自 auto-int 序列)

如果在 INSERT 上定义了 PARENT_POST_ID ,则将其设置为已传递的任何内容。

示例

post_id | parent_post_id | date_time        | message
     12               12   2015-04-14 21:10   A new post (start of a thread)
     13               12   2015-04-14 21:12   A reply to the post ID 12

这里的答案:https://stackoverflow.com/a/11061766/1266457 看起来可能是我需要做的,虽然我不确定它在做什么。

谢谢。

【问题讨论】:

    标签: mysql triggers surrogate-key


    【解决方案1】:

    对于在插入触发器之前,您无法获取最后插入的主键,另一种方法是从表中获取最大值并增加它。

    这是一种方法

    delimiter //
    create trigger posts_before_ins before insert on posts
    for each row 
    begin
      declare last_id int; 
      if new.parent_post_id is null then
        select max(post_id) into last_id from posts ;
        if last_id is null then
          set new.parent_post_id = 1 ;
        else
          set new.parent_post_id = last_id+1 ;
        end if ;
       end if ;
    end ;//
    
    delimiter ;
    

    因此触发器将检查插入查询中是否没有parent_post_id 的值,它将获得最大值post_id。对于第一个条目,它将为空,因此我们将其设置为 1,即在每个条目之后最大 post_id + 1

    这是一个在mysql中的测试用例

    mysql> select * from test ;
    Empty set (0.00 sec)
    
    mysql> delimiter //
    mysql> create trigger test_is before insert on test
        -> for each row 
        -> begin
        ->   declare last_id int; 
        ->   if new.parent_id is null then
        ->     SELECT auto_increment into last_id
        ->     FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 'test'
        ->     and TABLE_SCHEMA = 'test';
        ->     set new.parent_id = last_id ;
        ->    end if ;
        -> end ;//
    Query OK, 0 rows affected (0.12 sec)
    
    mysql> 
    mysql> delimiter ;
    
    mysql> insert into test (val) values ('aa');
    Query OK, 1 row affected (0.10 sec)
    
    mysql> insert into test (val) values ('bb');
    Query OK, 1 row affected (0.04 sec)
    
    mysql> select * from test ;
    +---------+-----------+------+
    | post_id | parent_id | val  |
    +---------+-----------+------+
    |       1 |         1 | aa   |
    |       2 |         2 | bb   |
    +---------+-----------+------+
    2 rows in set (0.00 sec)
    

    【讨论】:

    • 谢谢阿比克。我希望它可以获取序列 ID 并使用它。使用 MAX(post_id) + 1 可以工作,但它可靠吗?例如 - 假设他们当前的序列是 42,然后一些未提交的东西进来,下一个序列现在是 48 - 我可能会将它存储为 43(如果有意义的话)。
    • 好吧,如果事务未提交,那么理论上表将被锁定,并且在事务复杂之前不会发生新的插入。但是,您可以使用以下命令获取下一个 id 为 SELECT auto_increment FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 'tablename' 这比使用 max 好得多
    • 我已经使用了这个 - 但它仍然将 parent_post_id 设置为 0:BEGIN DECLARE prev_post_id INT; IF NEW.parent_post_id IS NULL THEN SELECT auto_increment INTO prev_post_id FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 'posts'; SET NEW.parent_post_id = prev_post_id; END IF; END
    • 刚刚意识到 - 这是因为我没有在我的 INSERT 查询中将其设置为 NULL。 (默认为 0)- doh!
    • 如果您使用的是INFORMATION_SCHEMA.TABLES,则不需要进行空检查。检查我更新的测试用例。您也可以将数据库名称与表名一起添加到查询中,以便它在指定的数据库中查找该表。
    猜你喜欢
    • 2023-04-11
    • 2011-08-24
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多