MySQL相当于Oracle的SEQUENCE.NEXTVAL

zig*_*ggy 14 mysql sql database oracle spring

我需要能够生成运行查询,该查询将返回下表中的下一个ID值:

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)

在Oracle中,您可以在序列上调用NEXTVAL,它会为您提供下一个序列(注意:无需在表上插入).

谷歌搜索后,我发现你可以使用以下查询找到auto_increment的当前值:

SELECT Auto_increment 
FROM information_schema.tables 
WHERE table_name='animals';
Run Code Online (Sandbox Code Playgroud)

问题是我希望每次查询值时增加值.在Oracle中,当您调用nextval时,即使您没有在表中插入行,序列的值也会增加.

有什么方法可以修改上面的查询,以便返回的值总是与上次调用查询时不同?即每次检查时Auto_increment都会递增,当在查询中使用时,它将使用新值.

我正在使用Spring JDBCTemplate,所以如果可以在一个查询中完成,那就更好了.

小智 12

http://docs.oracle.com/cd/E17952_01/refman-5.5-en/example-auto-increment.html

3.6.9.使用AUTO_INCREMENT

AUTO_INCREMENT属性可用于为新行生成唯一标识:

CREATE TABLE animals (
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
);

INSERT INTO animals (name) VALUES
    ('dog'),('cat'),('penguin'),
    ('lax'),('whale'),('ostrich');

SELECT * FROM animals;
Which returns:

+----+---------+
| id | name    |
+----+---------+
|  1 | dog     |
|  2 | cat     |
|  3 | penguin |
|  4 | lax     |
|  5 | whale   |
|  6 | ostrich |
+----+---------+
Run Code Online (Sandbox Code Playgroud)

没有为AUTO_INCREMENT列指定值,因此MySQL会自动分配序列号.您还可以显式为列分配NULL或0以生成序列号.

您可以使用LAST_INSERT_ID()SQL函数或mysql_insert_id()C API函数检索最新的AUTO_INCREMENT值.这些函数是特定于连接的,因此它们的返回值不受另一个也执行插入的连接的影响.

使用AUTO_INCREMENT列的最小整数数据类型,该列足够大以容纳您将需要的最大序列值.当列达到数据类型的上限时,下一次生成序列号的尝试将失败.如果可能,请使用UNSIGNED属性以允许更大的范围.例如,如果使用TINYINT,则允许的最大序列号为127.对于TINYINT UNSIGNED,最大值为255.请参见第11.2.1节"整数类型(精确值) - INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT "对于所有整数类型的范围.

注意对于多行插入,LAST_INSERT_ID()和mysql_insert_id()实际上从第一个插入的行返回AUTO_INCREMENT键.这使得多行插入可以在复制设置中的其他服务器上正确再现.

如果AUTO_INCREMENT列是多个索引的一部分,则MySQL使用以AUTO_INCREMENT列开头的索引(如果有)生成序列值.例如,如果animals表包含索引PRIMARY KEY(grp,id)和INDEX(id),则MySQL将忽略PRIMARY KEY以生成序列值.因此,该表将包含单个序列,而不是每个grp值的序列.

要以除1以外的AUTO_INCREMENT值开始,请使用CREATE TABLE或ALTER TABLE设置该值,如下所示:

mysql> ALTER TABLE tbl AUTO_INCREMENT = 100; InnoDB备注

对于InnoDB表,如果在INSERT语句序列的中间修改包含自动增量值的列,请务必小心.例如,如果使用UPDATE语句在自动增量列中放入一个新的较大值,则后续INSERT可能会遇到"重复条目"错误.如果执行DELETE后跟更多INSERT语句,或者执行COMMIT事务,而不是在UPDATE语句之后,则会测试是否已存在自动增量值.

MyISAM笔记

对于MyISAM表,可以在多列索引的辅助列上指定AUTO_INCREMENT.在这种情况下,AUTO_INCREMENT列的生成值计算为MAX(auto_increment_column)+ 1 WHERE prefix = given-prefix.当您想要将数据放入有序组时,这非常有用.

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+
Run Code Online (Sandbox Code Playgroud)

在这种情况下(当AUTO_INCREMENT列是多列索引的一部分时),如果删除任何组中具有最大AUTO_INCREMENT值的行,则重用AUTO_INCREMENT值.即使对于MyISAM表也会发生这种情况,因为通常不会重复使用AUTO_INCREMENT值.

进一步阅读

有关AUTO_INCREMENT的更多信息,请访问:

如何将AUTO_INCREMENT属性分配给列:第13.1.17节"CREATE TABLE语法"和第13.1.7节"ALTER TABLE语法".

AUTO_INCREMENT的行为取决于NO_AUTO_VALUE_ON_ZERO SQL模式:第5.1.7节"服务器SQL模式".

如何使用LAST_INSERT_ID()函数查找包含最新AUTO_INCREMENT值的行:第12.14节"信息函数".

设置要使用的AUTO_INCREMENT值:第5.1.4节"服务器系统变量".

AUTO_INCREMENT和复制:第16.4.1.1节"复制和AUTO_INCREMENT".

与AUTO_INCREMENT(auto_increment_increment和auto_increment_offset)相关的服务器系统变量,可用于复制:第5.1.4节"服务器系统变量".

http://search.oracle.com/search/search?q=auto_increment&group=Documentation&x=0&y=0


Sam*_*Sam 6

使用InnoDB的这个示例演示了使用互锁查询实现自己的计数器的方法:

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

你需要什么来创造一个差距?要保留ID?我宁愿"不惜一切代价"修复设计并更新其他模块而不是触及序列.

我不是只显式地增加序列,而是通过为每个id插入一个默认行(标记为无效)来分配并返回id.这种方法是一致和便携的.稍后,您可以使用匹配的序列值更新这些默认行,而不是使用显式序列值强制插入.这需要更多内存但没有锁.过期行上的垃圾收集可以在这里提供帮助.'insert或update'语句可以重新创建垃圾收集行,但我不会这样做.

  • 不惜一切代价?真的吗? (2认同)

zie*_*mer 5

您可以添加自己的 MySQL 函数 - 如http://www.microshell.com/database/mysql/emulating-nextval-function-to-get-sequence-in-mysql/ 所示- 允许您执行以下操作:

SELECT nextval('sq_my_sequence') as next_sequence;
Run Code Online (Sandbox Code Playgroud)