通过存储过程自动生成编号,先做个基础通用类型的,再根据需求场景修改输入参数:
先创建示例表:
CREATE TABLE [dbo].[T_BASE_BILLNO](
[FTable_Name] [varchar](500) NULL,
[FBillNo] [varchar](500) NULL
) ON [PRIMARY]
1.基础存储过程:
USE [eFrameWork]
GO
-- 创建「生成单据编号」存储过程
CREATE PROCEDURE [dbo].[生成单据编号]
@表名 NVARCHAR(128), -- 目标表名(如:Z_TM_PLAN)
@编号字段名 NVARCHAR(128), -- 存储单据编号的列名(如:FBILLNO)
@前缀 NVARCHAR(32), -- 单据前缀(如:SCRW)
@后缀 NVARCHAR(16) = '-', -- 编号分隔符(默认:-,可省略)
@流水号长度 INT, -- 流水号固定位数(如:4 → 0001)
@生成的单据编号 NVARCHAR(256) OUTPUT -- 输出的最终单据编号(如:SCRW20241001-0001)
AS
BEGIN
SET NOCOUNT ON; -- 关闭无关的行计数输出
-- 1. 自动获取「当日日期字符串」(格式:YYYYMMDD,如:20241001)
DECLARE @当日日期 NVARCHAR(8) = CONVERT(NVARCHAR(8), GETDATE(), 112); -- 112是SQL Server的YYYYMMDD格式码
-- 2. 构造「编号前缀组合」(例:SCRW + 20241001 + - → SCRW20241001-)
DECLARE @前缀组合 NVARCHAR(256) = @前缀 + @当日日期 + @后缀;
-- 3. 定义动态SQL变量(用于查询当前前缀下的最大流水号)
DECLARE @动态SQL NVARCHAR(MAX); -- 动态执行的SQL语句
DECLARE @当前最大流水号 INT; -- 临时存储查询到的最大流水号
-- 拼接动态SQL:提取「前缀组合后的流水号部分」,取最大值(无记录时返回0)
-- 关键修正:SUBSTRING 强制传递 3 个参数(字段名, 起始位置, 截取长度)
-- 逻辑:1. 截取编号字段中「前缀组合」之后的内容 → 2. 转成整数 → 3. 取最大值
SET @动态SQL = N'
SELECT @tmp_max = ISNULL(MAX(CAST(
SUBSTRING(' + QUOTENAME(@编号字段名) + N', -- 字段名
LEN(''' + @前缀组合 + N''') + 1, -- 起始位置:前缀组合长度+1(跳过前缀)
LEN(' + QUOTENAME(@编号字段名) + N') -- 截取长度:字段总长度(到末尾)
) AS INT)), 0)
FROM ' + QUOTENAME(@表名) + N'
WHERE ' + QUOTENAME(@编号字段名) + N' LIKE ''' + @前缀组合 + N'%''';
-- 4. 执行动态SQL,获取当前最大流水号
DECLARE @tmp_max INT;
EXEC sp_executesql
@动态SQL,
N'@tmp_max INT OUTPUT', -- 定义动态SQL的输出参数
@tmp_max OUTPUT; -- 接收动态SQL的输出值
SET @当前最大流水号 = @tmp_max;
-- 5. 生成最终单据编号:前缀组合 + 补零后的新流水号(最大流水号+1)
SET @生成的单据编号 = @前缀组合 +
RIGHT(
REPLICATE(N'0', @流水号长度) + -- 生成指定位数的零(如:0000)
CAST(@当前最大流水号 + 1 AS NVARCHAR(20)), -- 流水号+1(如:1 → 1)
@流水号长度 -- 截取到指定位数(如:4 → 0001)
);
DELETE FROM T_BASE_BILLNO WHERE FTable_Name=@表名
insert into T_BASE_BILLNO(FTable_Name,FBillNo)
SELECT @表名,@生成的单据编号
END;
2.调用存储过程(无参数,可用于加载的时候执行):(这里以日工单示例,实际请替换成自己需要的表和字段)
USE [eFrameWork]
GO
CREATE PROC [dbo].[日工单自动生成编号]
as
DECLARE @输出编号 NVARCHAR(256)
EXEC 生成单据编号
@表名 = N'Z_TM_PLAN', -- 目标表名
@编号字段名 = N'FBILLNO', -- 编号列名
@前缀 = N'SCRW', -- 前缀
@后缀 = N'-', -- 分隔符(可选,省略则默认-)
@流水号长度 = 4, -- 流水号4位
@生成的单据编号 = @输出编号 OUTPUT; -- 输出参数
-- 查看结果(例:SCRW20241001-0001)
SELECT @输出编号 AS 生成的单据编号;
3.调用存储过程(有参数,用于保存或更新的时候执行)
USE [eFrameWork]
GO
CREATE PROC [dbo].[日工单自动编号] @ID INT AS
DECLARE @输出编号 NVARCHAR(256)
-- 执行存储过程(生成Z_TM_PLAN表的下一个单据编号)
EXEC 生成单据编号
@表名 = N'Z_TM_PLAN', -- 目标表名
@编号字段名 = N'FBILLNO', -- 编号列名
@前缀 = N'SCRW', -- 前缀
@后缀 = N'-', -- 分隔符(可选,省略则默认-)
@流水号长度 = 4, -- 流水号4位
@生成的单据编号 = @输出编号 OUTPUT; -- 输出参数
-- 查看结果(例:SCRW20241001-0001)
SELECT @输出编号 AS 生成的单据编号;
update z_tm_plan set fbillno=@输出编号 where id=@id and fbillno is null
update z_tm_plan set FStatus=1 where id=@id and FStatus is null
update z_tm_plan set FSTOCKQTY=0 where id=@id and FSTOCKQTY is null
4.框架调用,找到对应的表,按图示添加动作

5.设置默认值

6.设置完毕,可以看到自动编号已生成