在插入触发器之前在MYSQL中使用自动增量值?

在插入触发器之前在MYSQL中使用自动增量值?,mysql,triggers,Mysql,Triggers,用户表: CREATE TABLE `users` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT, `email` varchar(45) DEFAULT NULL, `username` varchar(16) DEFAULT NULL, `salt` varchar(16) DEFAULT NULL, `password` varchar(128) DEFAULT NULL, `lastlogin` timestamp

用户表:

CREATE TABLE `users` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(45) DEFAULT NULL,
  `username` varchar(16) DEFAULT NULL,
  `salt` varchar(16) DEFAULT NULL,
  `password` varchar(128) DEFAULT NULL,
  `lastlogin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `joined` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `loggedin` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `sessionkey` varchar(60) DEFAULT NULL,
  `verifycode` varchar(16) DEFAULT NULL,
  `verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `banned` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `locked` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `ip_address` varchar(45) DEFAULT NULL,
  `failedattempts` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `unlocktime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` TRIGGER `before_create_user` BEFORE INSERT ON `users` FOR EACH ROW BEGIN
INSERT INTO user_records (action, userid, timestamp)
  VALUES ('CREATED', ID, NOW() );
END
用户记录表:

CREATE TABLE `user_records` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `userid` int(8) unsigned DEFAULT NULL,
  `action` varchar(100) DEFAULT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
用户表上的before insert触发器:

CREATE TABLE `users` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(45) DEFAULT NULL,
  `username` varchar(16) DEFAULT NULL,
  `salt` varchar(16) DEFAULT NULL,
  `password` varchar(128) DEFAULT NULL,
  `lastlogin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `joined` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `loggedin` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `sessionkey` varchar(60) DEFAULT NULL,
  `verifycode` varchar(16) DEFAULT NULL,
  `verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `banned` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `locked` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `ip_address` varchar(45) DEFAULT NULL,
  `failedattempts` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `unlocktime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` TRIGGER `before_create_user` BEFORE INSERT ON `users` FOR EACH ROW BEGIN
INSERT INTO user_records (action, userid, timestamp)
  VALUES ('CREATED', ID, NOW() );
END
基本上,我这里的问题是,在触发器上,当我尝试输入由MySQL自动分配的用户id(PK,NN,Auto Increment)时,它只是在user_records表中输入0作为userid。我该如何做才能让它选择SQL分配给用户的id,并将其作为用户id放在记录条目上(其中id位于“CREATED”之后)


此外,如果您看到可以对表进行的任何其他优化,请随时告诉我:D

将触发器更改为插入后的
,而不是插入前的
,并使用
新建
获取最后插入的id

USE `gknet`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` 
TRIGGER `after_create_user` AFTER INSERT ON `users` 
FOR EACH ROW 
BEGIN
INSERT INTO user_records (action, userid, timestamp)
  VALUES ('CREATED', NEW.ID, NOW() );
END; $$
OP评论:

我以前怎么做呢,你

您可以找到要分配给新记录的当前
auto_increment
值。
并在
before
触发器中将其用作
user\u记录
表的父用户id。
您必须查询
information\u schema.tables
table才能找到值

示例

use `gknet`;

delimiter $$

drop trigger if exists before_create_user; $$

create definer=`root`@`localhost` trigger `before_create_user` 
       before insert on `users` 
for each row begin
  declare fk_parent_user_id int default 0;

  select auto_increment into fk_parent_user_id
    from information_schema.tables
   where table_name = 'users'
     and table_schema = database();

  insert into user_records ( action, userid, timestamp )
         values ( 'created', fk_parent_user_id, now() );
end;

$$

delimiter ;
观察结果
根据,

“如果使用单个insert语句插入多行,
LAST\u INSERT\u ID()
仅限行。”

因此,依赖于批插入中的
last\u insert\u id()
auto\u increment
字段值似乎不可靠

请在插入和更新后使用


不要使任何要显式操作的列自动递增。这可能会混淆发动机并导致严重问题。如果没有用于主键的列是自动递增的,则可以通过触发器对它们执行任何操作。如果生成的值违反主键的强制唯一性,则肯定会被拒绝

也许这个解决方案可以

  BEGIN 
  DECLARE id int;
  SELECT MAX(table_id) 
         FROM table 
         INTO id;

     IF id IS NULL THEN 
        SET NEW.column=(CONCAT('KTG',1));
     ELSE
     SET NEW.column=(CONCAT('KTG',id+1));
    END IF;

   END

你知道,我以前该怎么做?使用before insert是没有意义的,一旦发生insert,只有你才能从user表中获取iduser。如果使用before insert,则需要从用户表中选择最后一个id,将其递增1,然后在表中插入,这不是正确的方法。“插入前”最适用于检查传入数据,然后在插入数据之前根据条件更改某些值的情况。@AbhikChakraborty:不,手动递增该值不是必需的。您可以通过读取下一个要分配的可用自动增量值来实现这一点。检查我的答案。@RavinderReddy在高负载系统和批量插入中,这是否准确?如果我正在运行大容量插入(比如插入到…从中选择),或者如果我正在运行一个高并发多线程应用程序,例如。@RichardAQuadling:在插入下一条记录之前,似乎已经对自动增量捕获的使用做了一些测试。建议在批处理过程中不要依赖。请阅读我的一个答案下的评论。当回答一个旧问题时,如果您包含一些上下文来解释您的答案如何有帮助,那么您的答案将对其他StackOverflow用户更有用,特别是对于已经有公认答案的问题。请看:。我不认为这个值是“事务性”的,这意味着在触发器触发时它可能不是最新的…@LukasEder:请用您的观察结果进行评论,并建议应该采用什么替代方案。我已经陈述了我的观察结果,我不知道什么是更好的选择approach@LukasEder:好的。我在回答中的最后一句话也是一个警告。