Mysql 仅当自动增量id不等于6时插入(例如)?
我有一个包含3个字段的表:Id(PK,AI)、Name(varchar(36))、LName(varchar(36))。 我必须插入名字和姓氏,Id自动插入,因为它的限制 有没有办法在id自动递增值达到6时跳转 例如,这样做7次: 在表(Name,LName)中插入值('name1','lname1'),如果它将是6,则将id跳转到7 这样做听起来可能很愚蠢,但我对此表示怀疑 同时跳转,不记录id 6。 仅记录,1-5、7、8、9等 我想要实现的目标始于一个联盟:Mysql 仅当自动增量id不等于6时插入(例如)?,mysql,sql,sql-server-2008,Mysql,Sql,Sql Server 2008,我有一个包含3个字段的表:Id(PK,AI)、Name(varchar(36))、LName(varchar(36))。 我必须插入名字和姓氏,Id自动插入,因为它的限制 有没有办法在id自动递增值达到6时跳转 例如,这样做7次: 在表(Name,LName)中插入值('name1','lname1'),如果它将是6,则将id跳转到7 这样做听起来可能很愚蠢,但我对此表示怀疑 同时跳转,不记录id 6。 仅记录,1-5、7、8、9等 我想要实现的目标始于一个联盟: Select * From T
Select * From TableNames
Union All
Select * From TableNames_general
在TableNames_general中,我指定了它的第一个值,这样当用户第一次看到表时,它将显示我插入的记录
当用户插入一条新记录时会出现问题,如果插入的记录的Id与我插入的记录的Id相同,它将被复制,这就是为什么我希望在用户插入一条记录时实现,如果最后一个插入Id已经存在,只需跳转该记录即可。这是因为由于子表之间的关系,我必须具有不同的ID。如果查询数据库以获取最后插入的ID,则可以通过使用查询中的参数设置正确的ID来检查是否需要增加ID。如果查询数据库以获取最后插入的ID,然后,您可以通过使用查询中的参数来设置正确的ID来检查是否需要增加它。无法直接影响自动增加以“跳过”特定值或特定条件下的值 我认为您必须在插入后的
触发器中处理此问题。INSERT后的触发器不能更新刚插入的行的值,我认为它不能对受触发触发器的语句影响的表进行任何修改
插入之前的触发器也不起作用,因为在插入之前的触发器中,分配给自动增量
列的值不可用
我认为也没有办法让SQLServerIDENTITY
跳过某个特定值
更新
如果您需要两个表之间的“唯一”id值,MySQL有一个相当难看的解决方法:使用触发器和单独的表滚动您自己的自动增量行为。不要使用AUTO_INCREMENT属性定义表,而是在插入前使用触发器获取值
如果提供了一个id
值,并且该值大于虚拟auto_increment_seq表中auto_increment列的当前最大值,我们需要更新该行,或者插入一个新行
大致来说:
CREATE TABLE auto_increment_seq
(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=MyISAM;
DELIMITER $$
CREATE TRIGGER TableNames_bi
BEFORE INSERT ON TableNames
FOR EACH ROW
BEGIN
DECLARE li_new_id INT UNSIGNED;
IF ( NEW.id = 0 OR NEW.id IS NULL ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NULL);
SELECT LAST_INSERT_ID() INTO li_new_id;
SET NEW.id = li_new_id;
ELSE
SELECT MAX(id) INTO li_max_seq FROM auto_increment_seq;
IF ( NEW.id > li_max_seq ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NEW.id);
END IF;
END IF;
END$$
CREATE TRIGGER TableNames_ai
AFTER INSERT ON TableNames
FOR EACH ROW BEGIN
DECLARE li_max_seq INT UNSIGNED;
SELECT MAX(id) INTO li_max_seq FROM auto_increment_seq;
IF ( NEW.id > li_max_seq ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NEW.id);
END IF;
END;
DELIMITER ;
表中的id列可以定义如下:
TableNames
( id INT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY
COMMENT 'populated from auto_increment_seq.id'
, ...
您也可以为另一个表创建相同的触发器,因此这两个表实际上共享相同的自动增量序列。(效率和并发性低于OracleSEQUENCE
对象提供的效率和并发性。)
重要注意事项
这并不能确保表之间的id
值实际上保持唯一。这实际上需要查询另一个表以查看id值是否存在;如果使用InnoDB引擎运行,在某些事务隔离级别的上下文中,我们可能会查询另一个表的过时版本(如中所示,与事务开始时的时间点一致)
如果没有一些额外的(并发终止)锁定,上面的方法大纲将受制于一个小的机会窗口,即并发插入的“竞争”条件。。。伪seq表中的SELECT MAX()后跟INSERT,允许另一个事务的小窗口也运行SELECT MAX(),并返回相同的值。我们所能期望的(我认为)最好是由于重复密钥异常而引发错误
这种方法需要虚拟的“seq”表来使用MyISAM引擎,因此我们可以获得类似Oracle的自治事务行为;如果在可重复读取或可序列化事务隔离级别的上下文中执行对实际表的插入,则从seq表读取MAX(id)将与事务开始时的快照一致,我们将无法获得新插入(或更新)的值
我们还需要考虑行更新的边缘情况来改变ID值;要处理这种情况,我们还需要更新前/更新后触发器。
没有直接方法影响自动增量“跳过”特定值或特定条件下的值
我认为您必须在插入后的触发器中处理此问题。INSERT后的触发器不能更新刚插入的行的值,我认为它不能对受触发触发器的语句影响的表进行任何修改
插入之前的触发器也不起作用,因为在插入之前的触发器中,分配给自动增量
列的值不可用
我认为也没有办法让SQLServerIDENTITY
跳过某个特定值
更新
如果您需要两个表之间的“唯一”id值,MySQL有一个相当难看的解决方法:使用触发器和单独的表滚动您自己的自动增量行为。不要使用AUTO_INCREMENT属性定义表,而是在插入前使用触发器获取值
如果提供了一个id
值,并且该值大于虚拟auto_increment_seq表中auto_increment列的当前最大值,我们需要更新该行,或者插入一个新行
大致来说:
CREATE TABLE auto_increment_seq
(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=MyISAM;
DELIMITER $$
CREATE TRIGGER TableNames_bi
BEFORE INSERT ON TableNames
FOR EACH ROW
BEGIN
DECLARE li_new_id INT UNSIGNED;
IF ( NEW.id = 0 OR NEW.id IS NULL ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NULL);
SELECT LAST_INSERT_ID() INTO li_new_id;
SET NEW.id = li_new_id;
ELSE
SELECT MAX(id) INTO li_max_seq FROM auto_increment_seq;
IF ( NEW.id > li_max_seq ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NEW.id);
END IF;
END IF;
END$$
CREATE TRIGGER TableNames_ai
AFTER INSERT ON TableNames
FOR EACH ROW BEGIN
DECLARE li_max_seq INT UNSIGNED;
SELECT MAX(id) INTO li_max_seq FROM auto_increment_seq;
IF ( NEW.id > li_max_seq ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NEW.id);
END IF;
END;
DELIMITER ;
t中的id列