SQL的序列也就是SEQUENCE,是数据库提供的一种可以生成连续唯一数值的数据库对象,常用于生成表的主键、业务流水号等需要唯一标识的场景,不需要依赖表就能独立存在,不同数据库对序列的支持语法略有差异。

序列的核心作用
序列最主要的作用是生成不重复的连续数值,避免多个会话同时插入数据时主键冲突的问题。和自增主键相比,序列可以跨表使用,也能在插入数据前就获取到生成的数值,适用场景更灵活。
不同数据库中序列的创建方法
Oracle数据库创建序列
Oracle原生支持序列,创建语法如下:
-- 创建名为user_id_seq的序列,起始值1,每次递增1,无最大值,缓存20个值提升性能 CREATE SEQUENCE user_id_seq START WITH 1 INCREMENT BY 1 NOMAXVALUE CACHE 20;
PostgreSQL数据库创建序列
PostgreSQL同样原生支持序列,创建语法和Oracle类似:
-- 创建名为order_no_seq的序列,起始值1000,每次递增2,最大值为9999,达到最大值后循环 CREATE SEQUENCE order_no_seq START WITH 1000 INCREMENT BY 2 MAXVALUE 9999 CYCLE;
MySQL数据库创建序列
MySQL8.0之前没有原生的序列语法,通常可以通过创建序列表模拟实现,8.0及以上版本可以通过自定义函数配合变量实现类似效果,以下是通过序列表模拟的示例:
-- 创建序列表
CREATE TABLE seq_table (
seq_name VARCHAR(50) PRIMARY KEY,
current_val BIGINT NOT NULL,
increment_val INT NOT NULL DEFAULT 1
);
-- 插入序列初始值
INSERT INTO seq_table (seq_name, current_val, increment_val) VALUES ('product_id_seq', 1, 1);
-- 创建获取下一个序列值的函数
DELIMITER //
CREATE FUNCTION next_seq_val(seq_name VARCHAR(50))
RETURNS BIGINT
BEGIN
DECLARE val BIGINT;
UPDATE seq_table SET current_val = current_val + increment_val WHERE seq_name = seq_name;
SELECT current_val INTO val FROM seq_table WHERE seq_name = seq_name;
RETURN val;
END //
DELIMITER ;
序列的常见使用方法
获取下一个序列值
不同数据库获取下一个序列值的语法不同:
- Oracle使用
NEXTVAL伪列:SELECT user_id_seq.NEXTVAL FROM DUAL; - PostgreSQL使用
nextval函数:SELECT nextval('order_no_seq'); - MySQL使用上面定义的函数:
SELECT next_seq_val('product_id_seq');
获取当前序列值
如果需要获取序列当前已经生成的值,不需要递增,不同数据库的语法如下:
- Oracle使用
CURRVAL伪列,注意需要先调用过一次NEXTVAL才能使用:SELECT user_id_seq.CURRVAL FROM DUAL; - PostgreSQL使用
currval函数:SELECT currval('order_no_seq'); - MySQL直接查询序列表的当前值:
SELECT current_val FROM seq_table WHERE seq_name = 'product_id_seq';
在插入语句中使用序列
最常见的场景是在插入数据时直接用序列生成主键值,以下是Oracle的示例:
-- 插入用户数据,主键使用序列生成 INSERT INTO user_info (id, user_name, age) VALUES (user_id_seq.NEXTVAL, '张三', 25);
序列的修改与删除
如果已经创建的序列不符合需求,可以修改序列的属性,以Oracle为例:
-- 修改序列的递增步长为2,最大值为10000 ALTER SEQUENCE user_id_seq INCREMENT BY 2 MAXVALUE 10000;
如果序列不再使用,可以执行删除操作:
-- 删除序列 DROP SEQUENCE user_id_seq;
使用序列的注意事项
- 序列生成的值是连续的,但如果事务回滚,已经生成的序列值不会回退,会出现数值不连续的情况,这是正常现象。
- 创建序列时如果设置了缓存,数据库重启后缓存的序列值会丢失,可能导致序列值跳号。
- 不同数据库对序列语法的支持差异较大,跨数据库开发时需要注意语法适配。