现在商场需要一个销售单流水号生成器,该流水号的组成结构是这样的:
SA100323000001=SA+年的后2位+月+日+6位流水号
请写一个函数 FN_GEN_SANO(@DATE DATETIME,@COUNT)
其中,@DATE是完整的日期,@COUNT是个数。
例如,参数分别是‘2007-03-01’,2那么
EXEC DBO.FN_GEN_SANO(‘2007-03-01’,2)得出的结果是
SANO
SA070301000001
SA070301000002
SA100323000001=SA+年的后2位+月+日+6位流水号
请写一个函数 FN_GEN_SANO(@DATE DATETIME,@COUNT)
其中,@DATE是完整的日期,@COUNT是个数。
例如,参数分别是‘2007-03-01’,2那么
EXEC DBO.FN_GEN_SANO(‘2007-03-01’,2)得出的结果是
SANO
SA070301000001
SA070301000002
if object_id('tb') is not null drop table tb
drop function dbo.FC_Next
create function dbo.FC_Next()
returns char(8)
as
begin
return (select 'BH'+right(1000001+isnull(right(max(BH),6),0),6) from tb)
end
create table tb
(
BH char(8) primary key default dbo.FC_Next(),
col int
)
select * from tb
begin tran
insert into tb (col) values (1)
insert into tb (col) values (2)
insert into tb(BH,col) values (dbo.FC_Next(),14)
commit tran
select * from tb
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ws_hgo/archive/2009/02/10/3872714.aspx
CREATE TABLE tb_NO(
Name char(2) NOT NULL, --编号种类的名称
Days int NOT NULL, --保存的是该种编号那一天的当前编号
Head nvarchar(10) NOT NULL DEFAULT '', --编号的前缀
CurrentNo int NOT NULL DEFAULT 0, --当前编号
BHLen int NOT NULL DEFAULT 6, --编号数字部分长度
YearMoth int NOT NULL --上次生成编号的年月,格式YYYYMM
DEFAULT CONVERT(CHAR(6),GETDATE(),112),
DESCRIPTION NVARCHAR(50), --编号种类说明
TableName sysname NOT NULL, --当前编号对应的原始表名
KeyFieldName sysname NOT NULL, --当前编号对应的原始表编号字段名
PRIMARY KEY(Name,Days))--这里以一种单据的7天的资料来做测试
INSERT tb_NO SELECT 'CG',1,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
UNION ALL SELECT 'CG',2,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
UNION ALL SELECT 'CG',3,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
UNION ALL SELECT 'CG',4,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
UNION ALL SELECT 'CG',5,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
UNION ALL SELECT 'CG',6,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
UNION ALL SELECT 'CG',7,'CG',0,4,200501,N'采购订单',N'tb',N'bh'
GO--获取新编号的存储过程
CREATE PROC p_NextBH
@Name char(2), --编号种类
@Date datetime=NULL, --要获取的当前日期,不指定则为系统当前日期
@BH nvarchar(20) OUTPUT --新编号
AS
IF @Date IS NULL SET @Date=GETDATE()
BEGIN TRAN
--从编号表中获取新编号
UPDATE tb_NO SET
@BH=Head
+CONVERT(CHAR(6),@Date,12)
+RIGHT(POWER(10,BHLen)
+CASE
WHEN YearMoth=CONVERT(char(6),@Date,112)
THEN CurrentNo+1
ELSE 1 END
,BHLen),
CurrentNo=CASE
WHEN YearMoth=CONVERT(char(6),@Date,112)
THEN CurrentNo+1
ELSE 1 END,
YearMoth=CONVERT(char(6),@Date,112)
WHERE Name=@Name
AND Days=DAY(@Date)
AND YearMoth<=CONVERT(char(6),@Date,112) --如果要获取的编号在编号表中已经过期,则直接从原始表中取编号
IF @@ROWCOUNT=0
BEGIN
DECLARE @s nvarchar(4000)
SELECT @s=N'SELECT @BH='
+QUOTENAME(Head+CONVERT(CHAR(6),@Date,12),N'''')
+N'+RIGHT('+CAST(POWER(10,BHLen)+1 as varchar)
+N'+ISNULL(RIGHT(MAX('+QUOTENAME(KeyFieldName)
+N'),'+CAST(BHLen as varchar)
+N'),0),'+CAST(BHLen as varchar)
+N') FROM '+QUOTENAME(TableName)
+N' WITH(XLOCK,PAGLOCK) WHERE '
+QUOTENAME(KeyFieldName)
+N' like '+QUOTENAME(Head+CONVERT(CHAR(6),@Date,12)+N'%',N'''')
FROM tb_NO
WHERE Name=@Name
AND Days=DAY(@Date)
AND YearMoth>CONVERT(char(6),@Date,112)
IF @@ROWCOUNT>0
EXEC sp_executesql @s,N'@BH nvarchar(20) OUTPUT',@BH OUTPUT
END
COMMIT TRAN
GOCREATE TABLE tb(BH char(12))
--获取 CG 的新编号
DECLARE @bh char(12)
EXEC p_NextBH 'CG','2005-1-1',@bh OUT
SELECT @bh
--结果: CG0501010001EXEC p_NextBH 'CG','2005-1-1',@bh OUT
SELECT @bh
--结果: CG0501010002EXEC p_NextBH 'CG','2005-1-2',@bh OUT
SELECT @bh
--结果: CG0501020001EXEC p_NextBH 'CG','2005-2-2',@bh OUT
SELECT @bh
--结果: CG0402020001EXEC p_NextBH 'CG','2004-2-2',@bh OUT
SELECT @bh
--结果: CG0402020001
GO
--创建得到当前日期的视图
CREATE VIEW v_GetDate
AS
SELECT dt=CONVERT(CHAR(6),GETDATE(),12)
GO--得到新编号的函数
CREATE FUNCTION f_NextBH()
RETURNS char(12)
AS
BEGIN
DECLARE @dt CHAR(6)
SELECT @dt=dt FROM v_GetDate
RETURN(
SELECT @dt+RIGHT(1000001+ISNULL(RIGHT(MAX(BH),6),0),6)
FROM tb WITH(XLOCK,PAGLOCK)
WHERE BH like @dt+'%')
END
GO--在表中应用函数
CREATE TABLE tb(
BH char(12) PRIMARY KEY DEFAULT dbo.f_NextBH(),
col int)--插入资料
INSERT tb(col) VALUES(1)
INSERT tb(col) VALUES(2)
INSERT tb(col) VALUES(3)
DELETE tb WHERE col=3
INSERT tb(col) VALUES(4)
INSERT tb(BH,col) VALUES(dbo.f_NextBH(),14)--显示结果
SELECT * FROM tb
/*--结果
BH col
------------------- -----------
050405000001 1
050405000002 2
050405000003 4
050405000004 14
--*/
'sa'+right(year(@s),2)+'0'+ltrim(month(@s))+'0'+ltrim(day(@s))+RIGHT(1000001+ISNULL(RIGHT(MAX(col),6),0),6)
from
tb
drop table tb1
go
create table tb1
(
BH varchar(20)
)
insert into tb1 (bh) values ('SA201202000001')
godrop proc FN_GEN_SANO
go
create proc dbo.FN_GEN_SANO(@d datetime,@c int)
as
begin
declare @max varchar(20)
declare @i int
DECLARE @tmp TABLE (BH varchar(20)) set @i=1
select @max = max(BH) from tb1 where left(BH,8)='SA'+convert(varchar(6),@d,12)
if @max is null
begin
set @max='SA'+convert(varchar(6),@d,12)+'000000'
endwhile @i<=@c
begin
insert into @tmp(BH)
values( 'SA'+convert(varchar(6),@d,12)+convert(varchar(6),right((convert(numeric(6),right(@max,6))+100000000+@i),6)) )
set @i=@i+1
end
select * from @tmp
end
godeclare @d datetime
declare @c intset @d='2020-12-2'
set @c=5
exec dbo.FN_GEN_SANO @d,@c
(所影响的行数为 1 行)
(所影响的行数为 1 行)
(所影响的行数为 1 行)
(所影响的行数为 1 行)
(所影响的行数为 1 行)BH
--------------------
SA201202000002
SA201202000003
SA201202000004
SA201202000005
SA201202000006(所影响的行数为 5 行)