怎么从Sql Server里搞到序列值,取序列那块到底咋弄啊
- 问答
- 2026-01-21 22:37:05
- 3
你说想从 SQL Server 里搞到序列值,想知道取序列那块到底咋弄,这事儿说白了,就是想弄出一种能自动、按顺序增长的数字,比如订单号要生成 ORD001, ORD002,或者给表格里的每一行一个唯一的、好看的序号,在 SQL Server 里,干这事儿主要有两大招,你得根据你的具体情况选。
第一招:用 IDENTITY 标识列,这招最简单,也最常用。
这就像是给表格里的一个列(比如叫 ID 列)打上标记,跟它说你不用管,数据库自己会往这个列里填数字,每次加一行,数字就自动加 1(或者按你设定的步长增加)。
具体怎么弄呢? 大部分时候你是在建新表的时候就直接搞定了,比如你想建一个“订单表”,里面要有个自动增长的订单ID,你的建表语句会这么写:
CREATE TABLE 订单表 (
订单ID int IDENTITY(1,1) PRIMARY KEY,
客户名称 nvarchar(50),
订单金额 decimal(10,2)
);
这里的关键就是 IDENTITY(1,1),括号里第一个数叫“种子”,意思是序列从几开始,这里是从 1 开始,第二个数叫“增量”,意思是每次增加几,这里是每次加 1,所以插进去的第一行,订单ID 1,第二行就是 2,依此类推。
那插数据的时候怎么办? 正因为这个列是数据库自动帮你填的,所以你往表里插数据的时候,压根就不用管这个列,你的插入语句应该是这样的:
INSERT INTO 订单表 (客户名称, 订单金额) VALUES ('张三', 100.50);
INSERT INTO 订单表 (客户名称, 订单金额) VALUES ('李四', 200.00);
执行完这两句,你去看“订单表”,会发现“订单ID”列自己就有了 1 和 2 这两个值。
怎么拿到我刚插进去的那个序列值?
这是个非常常见的需求,比如你下了个订单,需要立刻知道这个新订单的ID是多少,SQL Server 提供了几个方法让你能抓到刚刚生成的那个ID值,最常用的就是 SCOPE_IDENTITY() 这个函数,你可以在插入语句后面紧接着用它:
INSERT INTO 订单表 (客户名称, 订单金额) VALUES ('王五', 300.00);
SELECT SCOPE_IDENTITY() AS 新订单ID;
这样,查询结果就会返回刚刚为王五这条记录生成的“订单ID”,比如是 3。SCOPE_IDENTITY() 的好处是它非常精准,只返回当前你这次操作(在当前作用域内)生成的最后一个标识值,不会受到其他人同时操作数据库的干扰。
IDENTITY 这招的优缺点:
- 优点:超级简单,数据库全自动管理,性能也好,非常适合用来做那种没有业务含义的、纯粹的主键。
- 缺点:不够灵活,一旦表建好了,这个种子和增量就很难改了,如果中途有人手动插了一个很大的数进去,或者删掉了一些行,序列可能会不连续,出现“跳号”的情况(1, 2, 5, 6...),有时候业务上要求号码必须连续,这就成问题了。
第二招:用 SEQUENCE 序列对象,这招更灵活,是 SQL Server 2012 版本之后才有的高级货。
你可以把 SEQUENCE 理解成一个独立于任何表的、专门生产号码的“号码机”,这个号码机有自己的规则(从几开始、每次加几、有没有上限等),哪个表需要序号了,就来这个号码机里取一个。
怎么创建这个“号码机”?
用 CREATE SEQUENCE 语句来造一个,比如你想创建一个从 1000 开始,每次增加 10 的序列:
CREATE SEQUENCE 订单号序列
START WITH 1000
INCREMENT BY 10;
这样就创建好了一个名叫“订单号序列”的号码机。
怎么用它来取号?
取号的核心是 NEXT VALUE FOR 这个关键字,它不像 IDENTITY 那样自动填充,而是需要你显式地去“领取”下一个号码,插数据的时候,你得主动调用它:
INSERT INTO 订单表 (订单ID, 客户名称, 订单金额) VALUES (NEXT VALUE FOR 订单号序列, '赵六', 400.00);
这样,赵六这条记录的“订单ID”字段值就会被赋值为 1000,下一条再用 NEXT VALUE FOR 订单号序列,拿到的就是 1010。
SEQUENCE 这招的优缺点:
- 优点:非常灵活,一个序列可以被多个表共用;可以随时用
ALTER SEQUENCE修改它的规则(比如重置起始值);可以控制循环(比如从1到100,满了再回到1);获取号码和插入数据可以分开操作,给你更大的控制权。 - 缺点:比 IDENTITY 稍微麻烦一点,需要你手动去获取值,而且如果获取了号码但最终没用(比如事务回滚了),这个号码就被“消耗”掉了,也会造成序列不连续。
到底该用哪一招?
- 如果你的需求很简单,就是给表一个自增的主键,不关心号码连不连续,也不需要在表之外控制它,那用 IDENTITY 最省事。
- 如果你需要更复杂的控制,比如号码要有特定的起点和步长、要在多个表之间共享一套序号、或者需要事先知道下一个号码是多少(比如在生成订单号时先显示给用户看),那就用 SEQUENCE。
最后提一嘴,网上很多老教程可能会提到用 @@IDENTITY 或者 IDENT_CURRENT('表名') 来获取标识值,但这两个没有 SCOPE_IDENTITY() 靠谱。@@IDENTITY 可能会被触发器干扰,拿到不对的值;IDENT_CURRENT 会拿到这个表在任何情况下最后生成的标识值,不管是不是你生成的,保险起见,优先用 SCOPE_IDENTITY()。
希望这些大实话能帮你把“取序列那块”彻底弄明白。

本文由凤伟才于2026-01-21发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/84231.html
