之前使用“勤哲”开发办公以及erp系统,虽然它的设计以及应用框架的原因,不能像fine这样,但是还是能创建很多有趣的工作。
学习fine一段时间了,至于原先“勤哲”有的功能,fine没有,非常的不理解,一些属于基本工具,居然不提供,比如“自动编号”问题,这是“勤哲”自带工具的示例图。
为了流水号这个功能,查了很多的资料以及贴子,都没满意的结果,偶然看到其它人做了一个流水号的存储过程,经过整理和修正,现将代码公布如下。
特点:
1、支持多种配置以及结构的流水
2、通过配置,很容易对各个场景使用的流水进行定义,如订单流水,客户流水等。
3、代码容易修改,使用存储过程,我已经很多年没接触存储过程了,看到代码后,没一会就改了
4、支持并发,多人同时取数是没问题!
5、支持4种归零方式:1 不归零 2 按日归零 3 按月归零 4按年归零,以及指定归零时的却始值,如100.
数据库结构如下
- CREATE TABLE [dbo].[RUL_Sequence] (
- [SeqCode] varchar(60) NOT NULL , //编号规则代码
- [Descr] varchar(60) NULL , //描述
- [NowSeqValue] bigint NULL , //序号当前值
- [EditTime] datetime NULL , //取值日期
- [Length] int NULL , //序号长度,需和格式中的<XXX>位数配合
- [DataFormat] varchar(50) NULL , //规划格式,如<YY><MM><DD><XXX><ZZ>
- [DateMax] varchar(10) NULL , //日期最大值
- [Status] varchar(1) NULL , //是否可编辑(0-系统代码,不可编辑,1-可编辑)
- [InitValue] varchar(10) NULL , //归零值
- [ResetType] varchar(50) NULL , //归零方式(1不归零 2按日归零 3 按月归零 4按年归零)
- [IsRunning] char(1) NULL //正在运行标记,控制并发(1-正在运行,2-没在运行)
- )
复制代码 示例
示例中有一个orderno的流水号,如果再增加一个customeno记录,即可支持另一个流水号规则。
存储过程:
- ALTER PROCEDURE [dbo].[Proc_GetSeqence]
- @SeqCode varchar(60), -- 规则代码
- @NewValue varchar(60)=''
- AS
- /* Exec Proc_GetSeqence 'OrderNo','',''
- *****************************************************************
- 功能描述: 获取数据表的主键流水号(INV, ASN, SO...)
- 主要思路: 1.取得最新流水号信息
- 2.把所有固定的规则信息替换成具体值,其他保持不变
- eg:
- 规则为: ASN<YYYY><YY><MM><XXX>ASN
- 当前日期为: 20170630
- 当前流水号为:12
- 最终流水号为:ASN201306013ASN
- ******************************************************************
- */
- /*
- * SET NOCOUNT ON 的作用:
- * 不返回受影响行数
- * 存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。
- * */
- SET NOCOUNT ON
- DECLARE @SeqNowNumStr VARCHAR(20) --当前值字符类型
- DECLARE @SeqNowNum BIGINT --当前值
- DECLARE @year CHAR(4) --年 YYYY
- DECLARE @month CHAR(2) --月 MM
- DECLARE @day CHAR(2) --日 DD
- DECLARE @Length INT --流水号长度
- DECLARE @DataFormat VARCHAR(50) --流水号规则
- DECLARE @IniValue INT --归零值
- DECLARE @ResetType VARCHAR(10) --归零方式
- DECLARE @LastDate CHAR(8) --日期最大值
- DECLARE @WorkFLowStr VARCHAR(20) --前一次调用流水号时的日期值
- DECLARE @DataNow CHAR(8) --当前日期
- DECLARE @i INT --转换变量,作用参照代码上下文
- DECLARE @ReturnNum Varchar(40)
- DECLARE @MessageCode varchar(800)
- /*
- * SET XACT_ABORT ON 的作用:
- * 存储中的某个地方出了问题,整个事务中的语句都会回滚
- * */
- SET XACT_ABORT ON
- BEGIN TRY
- /* 初始化变量 */
- SET @MessageCode='999'
- SET @ReturnNum = '0'
- SET @Length=0
- SET @SeqNowNum =0;
- SET @DataNow=CONVERT(CHAR(8),GETDATE(),112) --得到 20130704 的时间格式
- SET @year=SUBSTRING(@DataNow,1,4)
- SET @month =SUBSTRING(@DataNow,5,2)
- SET @day =SUBSTRING(@DataNow,7,2)
- Set @i=1
- /***********如果有并发的正在运行,最多等待0.06秒,然后继续运行 Start*******/
- BEGIN TRANSACTION
- wait:
- Update dbo.RUL_Sequence Set [IsRunning]='2' where SeqCode=@SeqCode and IsRunning='1'
- If @@Rowcount=0
- Begin
- Waitfor Delay '00:00:01'
- Set @i=@i+1
- If @i<6 goto wait
- End
- COMMIT TRANSACTION
- /***********如果有并发的正在运行,最多等待0.06秒,然后继续运行 End*******/
- Select @Length = [Length],@SeqNowNum=NowSeqValue,@LastDate=DateMax,@DataFormat=DataFormat
- ,@ResetType=ResetType,@IniValue =InitValue
- From RUL_Sequence where SeqCode=@SeqCode
- if @SeqNowNum=0 --当前值正常情况下不可能是0
- begin
- Update dbo.RUL_Sequence Set [IsRunning]='1' where SeqCode=@SeqCode --新增处理并发问题,恢复时间***
- set @ReturnNum='-1'
- Set @MessageCode='100' --当前值 错误代码
- SELECT @ReturnNum as NumRetrun,@MessageCode as MessageCode
- return;
- END
- --@ResetType=1 不归零 2 按日归零 3 按月归零 4按年归零
- If (@ResetType=2 and @DataNow<>@LastDate AND @IniValue>0)
- OR (@ResetType=3 and @year+@month<>SUBSTRING(@LastDate,1,6) AND @IniValue>0)
- OR (@ResetType=4 and @year<>SUBSTRING(@LastDate,1,4) AND @IniValue>0 )
- BEGIN
- SET @SeqNowNum=@IniValue
- END
- SET @i=@Length --@i 此时表示流水号的总长度
- /***********拼流水号格式 Start*******/
- SET @WorkFLowStr='<'
- WHILE @Length>0
- BEGIN
- SET @WorkFLowStr=@WorkFLowStr+'X'
- SET @Length=@Length-1
- END
- SET @WorkFLowStr=@WorkFLowStr+'>'
- /***********拼流水号格式 End*******/
- set @SeqNowNumStr=CONVERT(VARCHAR(20),@SeqNowNum)
- SET @Length=@i-len(@SeqNowNumStr) --@Length 要补零的位数(eg:@SeqNowNumStr=148 当前流水号是五位,最后流水号为00148,00 就是需要补的两位)
- /***********补零操作 Start*******/
- WHILE @Length>0
- BEGIN
- SET @SeqNowNumStr='0'+@SeqNowNumStr
- SET @Length=@Length-1
- END
- /***********补零操作 End*******/
- SET @ReturnNum=REPLACE( @DataFormat,'<YYYY>',@year); -- 把规则中<YYYY>替换成相应年
- SET @ReturnNum=REPLACE( @DataFormat,'<YY>',right(CONVERT(VARCHAR(4),@year),2)); -- 把规则中<YY>替换成相应年
- SET @ReturnNum=REPLACE( @ReturnNum,'<MM>',@month); -- 把规则中<MM>替换成相应月
- SET @ReturnNum=REPLACE( @ReturnNum,'<DD>',@day); -- 把规则中<DD>替换成相应日
- SET @ReturnNum=REPLACE( @ReturnNum,'<ZZ>',@NewValue); -- 把规则中<ZZ>替换成相应变量值
- SET @ReturnNum=REPLACE( @ReturnNum,@WorkFLowStr,@SeqNowNumStr);-- 把规则中的形如<XXX>的替换成相应流水号,
- /***********更新当前流水值为最大流水号、上一个流水号生成时间和运行标记(运行标记置为"1"(没有运行) ) Start*******/
- Begin transaction
- UPDATE RUL_Sequence SET NowSeqValue=@SeqNowNum+1,DateMax=@DataNow,ISRUNNING='1', EditTime=Getdate()
- WHERE IsRunning='2' AND SeqCode=@SeqCode
- --SELECT * FROM RUL_Sequence WHERE IsRunning='2' AND SeqCode=@SeqCode
- -- PRINT @SeqNowNum+1
- Commit transaction
- /***********更新当前流水值为最大流水号、上一个流水号生成时间和运行标记(运行标记置为"1"(没有运行) ) End*******/
- select @ReturnNum as NumRetrun, @MessageCode as MessageCode;
- END TRY
- --错误捕获
- BEGIN CATCH
- ROLLBACK TRANSACTION
- Set @ReturnNum='-2'
- set @MessageCode='行号='+cast(ERROR_LINE() as varchar(10))+'错误信息'+ERROR_MESSAGE()
- +'['+ERROR_PROCEDURE()+']'
- IF @@ROWcount<=0
- set @MessageCode='无此编号规则'+@MessageCode
- SELECT @ReturnNum as NumRetrun,@MessageCode as MessageCode
- END CATCH
复制代码 fine调用 方式:
- SQL("runserver","Exec Proc_GetSeqence 'OrderNo',''",1,1)
复制代码 结果如下:
170810001
说明:
<YYYY> 四位年
<YY> 两位年
<MM> 月份
<DD> 日
<XXXX> 序号
<ZZ> 固定的字符,可由存储过程第二个参数传入,用途:比如人员代码,在流水号基础上,用这个识别人员。调用如:SQL("runserver","Exec Proc_GetSeqence 'OrderNo','ok',1,1),结果就像是170810001ok
这几个组合顺序可以任意。
上述代码也是引用网上其它人的成果,我只是做了简单的修改,肯定是可以运行,大家如果有什么好办法也欢迎大家提供。
虽然这个功能可以使用,但离我之用使用的“勤哲”在功能还还是差距比较大的,如废号的自动回收等。
这里,希望fine能重视这些和设计相关的基础功能的集成工作,虽然fine具有很强大的功能,但一些基础类工具,还是能提供解决办法。
也有利于你们系统的推广。
编辑于 2017-8-10 15:01
|