关于流水号解决-自动编号方案

楼主
我是社区第82104位番薯,欢迎点我头像关注我哦~
之前使用“勤哲”开发办公以及erp系统,虽然它的设计以及应用框架的原因,不能像fine这样,但是还是能创建很多有趣的工作。
学习fine一段时间了,至于原先“勤哲”有的功能,fine没有,非常的不理解,一些属于基本工具,居然不提供,比如“自动编号”问题,这是“勤哲”自带工具的示例图。


为了流水号这个功能,查了很多的资料以及贴子,都没满意的结果,偶然看到其它人做了一个流水号的存储过程,经过整理和修正,现将代码公布如下。
特点:
1、支持多种配置以及结构的流水
2、通过配置,很容易对各个场景使用的流水进行定义,如订单流水,客户流水等。
3、代码容易修改,使用存储过程,我已经很多年没接触存储过程了,看到代码后,没一会就改了
4、支持并发,多人同时取数是没问题!
5、支持4种归零方式:1 不归零 2 按日归零 3 按月归零 4按年归零,以及指定归零时的却始值,如100.
数据库结构如下
  1. CREATE TABLE [dbo].[RUL_Sequence] (
  2. [SeqCode] varchar(60) NOT NULL ,  //编号规则代码
  3. [Descr] varchar(60) NULL ,  //描述
  4. [NowSeqValue] bigint NULL ,  //序号当前值
  5. [EditTime] datetime NULL ,  //取值日期
  6. [Length] int NULL ,  //序号长度,需和格式中的<XXX>位数配合
  7. [DataFormat] varchar(50) NULL ,  //规划格式,如<YY><MM><DD><XXX><ZZ>
  8. [DateMax] varchar(10) NULL , //日期最大值
  9. [Status] varchar(1) NULL , //是否可编辑(0-系统代码,不可编辑,1-可编辑)
  10. [InitValue] varchar(10) NULL , //归零值
  11. [ResetType] varchar(50) NULL , //归零方式(1不归零 2按日归零 3 按月归零 4按年归零)
  12. [IsRunning] char(1) NULL   //正在运行标记,控制并发(1-正在运行,2-没在运行)
  13. )
复制代码
示例

示例中有一个orderno的流水号,如果再增加一个customeno记录,即可支持另一个流水号规则。
存储过程:

  1. ALTER PROCEDURE [dbo].[Proc_GetSeqence]
  2. @SeqCode varchar(60),        -- 规则代码
  3. @NewValue varchar(60)=''
  4. AS
  5. /* Exec Proc_GetSeqence 'OrderNo','',''
  6. *****************************************************************
  7. 功能描述:        获取数据表的主键流水号(INV, ASN, SO...)

  8. 主要思路:        1.取得最新流水号信息
  9. 2.把所有固定的规则信息替换成具体值,其他保持不变
  10. eg:
  11. 规则为:        ASN<YYYY><YY><MM><XXX>ASN
  12. 当前日期为:        20170630
  13. 当前流水号为:12
  14. 最终流水号为:ASN201306013ASN

  15. ******************************************************************
  16. */


  17. /*
  18. * SET NOCOUNT ON 的作用:
  19. * 不返回受影响行数
  20. * 存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。
  21. * */
  22. SET NOCOUNT ON

  23. DECLARE @SeqNowNumStr VARCHAR(20)        --当前值字符类型        
  24. DECLARE @SeqNowNum BIGINT        --当前值        
  25. DECLARE @year CHAR(4)        --年 YYYY
  26. DECLARE @month CHAR(2)        --月 MM
  27. DECLARE @day CHAR(2)        --日 DD
  28. DECLARE @Length INT        --流水号长度
  29. DECLARE @DataFormat VARCHAR(50)        --流水号规则
  30. DECLARE @IniValue INT        --归零值
  31. DECLARE @ResetType VARCHAR(10)        --归零方式
  32. DECLARE @LastDate        CHAR(8)        --日期最大值        
  33. DECLARE @WorkFLowStr VARCHAR(20) --前一次调用流水号时的日期值
  34. DECLARE @DataNow CHAR(8)        --当前日期
  35. DECLARE @i INT        --转换变量,作用参照代码上下文
  36. DECLARE @ReturnNum Varchar(40)
  37. DECLARE @MessageCode varchar(800)


  38. /*
  39. * SET XACT_ABORT ON 的作用:
  40. * 存储中的某个地方出了问题,整个事务中的语句都会回滚
  41. * */
  42. SET XACT_ABORT ON
  43. BEGIN TRY

  44. /* 初始化变量 */
  45. SET @MessageCode='999'
  46. SET @ReturnNum = '0'
  47. SET @Length=0
  48. SET @SeqNowNum =0;
  49. SET @DataNow=CONVERT(CHAR(8),GETDATE(),112) --得到 20130704 的时间格式
  50. SET @year=SUBSTRING(@DataNow,1,4)
  51. SET @month =SUBSTRING(@DataNow,5,2)
  52. SET @day =SUBSTRING(@DataNow,7,2)

  53. Set @i=1

  54. /***********如果有并发的正在运行,最多等待0.06秒,然后继续运行 Start*******/
  55. BEGIN TRANSACTION
  56. wait:
  57. Update dbo.RUL_Sequence Set [IsRunning]='2' where SeqCode=@SeqCode and IsRunning='1'
  58. If @@Rowcount=0        
  59. Begin
  60. Waitfor Delay '00:00:01'
  61. Set @i=@i+1
  62. If @i<6 goto wait
  63. End

  64. COMMIT TRANSACTION
  65. /***********如果有并发的正在运行,最多等待0.06秒,然后继续运行 End*******/

  66. Select @Length = [Length],@SeqNowNum=NowSeqValue,@LastDate=DateMax,@DataFormat=DataFormat
  67. ,@ResetType=ResetType,@IniValue =InitValue
  68. From RUL_Sequence where SeqCode=@SeqCode
  69. if @SeqNowNum=0 --当前值正常情况下不可能是0
  70. begin
  71. Update dbo.RUL_Sequence Set [IsRunning]='1' where SeqCode=@SeqCode --新增处理并发问题,恢复时间***
  72. set @ReturnNum='-1'
  73. Set @MessageCode='100' --当前值 错误代码
  74. SELECT @ReturnNum as NumRetrun,@MessageCode as MessageCode
  75. return;
  76. END
  77. --@ResetType=1 不归零 2 按日归零 3 按月归零 4按年归零
  78. If (@ResetType=2 and @DataNow<>@LastDate AND @IniValue>0)
  79. OR (@ResetType=3 and @year+@month<>SUBSTRING(@LastDate,1,6) AND @IniValue>0)
  80. OR (@ResetType=4 and @year<>SUBSTRING(@LastDate,1,4) AND @IniValue>0 )
  81. BEGIN
  82. SET @SeqNowNum=@IniValue
  83. END
  84. SET @i=@Length --@i 此时表示流水号的总长度

  85. /***********拼流水号格式 Start*******/
  86. SET @WorkFLowStr='<'
  87. WHILE @Length>0
  88. BEGIN
  89. SET @WorkFLowStr=@WorkFLowStr+'X'
  90. SET @Length=@Length-1
  91. END
  92. SET @WorkFLowStr=@WorkFLowStr+'>'
  93. /***********拼流水号格式 End*******/

  94. set @SeqNowNumStr=CONVERT(VARCHAR(20),@SeqNowNum)
  95. SET @Length=@i-len(@SeqNowNumStr) --@Length 要补零的位数(eg:@SeqNowNumStr=148 当前流水号是五位,最后流水号为00148,00 就是需要补的两位)

  96. /***********补零操作 Start*******/
  97. WHILE @Length>0
  98. BEGIN
  99. SET @SeqNowNumStr='0'+@SeqNowNumStr
  100. SET @Length=@Length-1
  101. END
  102. /***********补零操作 End*******/

  103. SET @ReturnNum=REPLACE( @DataFormat,'<YYYY>',@year);        -- 把规则中<YYYY>替换成相应年
  104. SET @ReturnNum=REPLACE( @DataFormat,'<YY>',right(CONVERT(VARCHAR(4),@year),2));        -- 把规则中<YY>替换成相应年
  105. SET @ReturnNum=REPLACE( @ReturnNum,'<MM>',@month);        -- 把规则中<MM>替换成相应月
  106. SET @ReturnNum=REPLACE( @ReturnNum,'<DD>',@day);        -- 把规则中<DD>替换成相应日
  107. SET @ReturnNum=REPLACE( @ReturnNum,'<ZZ>',@NewValue);        -- 把规则中<ZZ>替换成相应变量值
  108. SET @ReturnNum=REPLACE( @ReturnNum,@WorkFLowStr,@SeqNowNumStr);-- 把规则中的形如<XXX>的替换成相应流水号,


  109. /***********更新当前流水值为最大流水号、上一个流水号生成时间和运行标记(运行标记置为"1"(没有运行) ) Start*******/
  110. Begin transaction

  111. UPDATE RUL_Sequence SET NowSeqValue=@SeqNowNum+1,DateMax=@DataNow,ISRUNNING='1', EditTime=Getdate()
  112. WHERE IsRunning='2' AND SeqCode=@SeqCode
  113. --SELECT * FROM RUL_Sequence WHERE IsRunning='2' AND SeqCode=@SeqCode
  114. -- PRINT @SeqNowNum+1
  115. Commit transaction
  116. /***********更新当前流水值为最大流水号、上一个流水号生成时间和运行标记(运行标记置为"1"(没有运行) ) End*******/
  117. select @ReturnNum as NumRetrun, @MessageCode as MessageCode;        
  118. END TRY


  119. --错误捕获
  120. BEGIN CATCH
  121. ROLLBACK TRANSACTION
  122. Set @ReturnNum='-2'
  123. set @MessageCode='行号='+cast(ERROR_LINE() as varchar(10))+'错误信息'+ERROR_MESSAGE()
  124. +'['+ERROR_PROCEDURE()+']'
  125. IF @@ROWcount<=0
  126. set @MessageCode='无此编号规则'+@MessageCode
  127. SELECT @ReturnNum as NumRetrun,@MessageCode as MessageCode
  128. END CATCH
复制代码
fine调用 方式:

  1. 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  
分享扩散:
参与人数 +2 F豆 +166 理由
葛智 + 100 太棒了,给你32个赞,么么哒
兔子酱 + 66 感谢分享

查看全部评分

沙发
发表于 2017-8-10 13:42:57
板凳
发表于 2017-8-10 14:38:59
感谢投稿,已提名精华帖,待论坛运营委员会评分后可评为精华帖,帆软论坛精华帖奖励计划http://bbs.fanruan.com/thread-91079-1-1.html
地板
发表于 2017-8-11 07:55:05
5楼
发表于 2017-8-11 18:45:35
希望能把     自动编号    引起帆软的重视  确实需求很大  

帆软  应该引起重视
6楼
发表于 2017-8-12 17:37:03
橙子君 发表于 2017-8-10 14:38
感谢投稿,已提名精华帖,待论坛运营委员会评分后可评为精华帖,帆软论坛精华帖奖励计划http://bbs.fanruan ...

希望能把     自动编号    引起帆软的重视  确实需求很大  

帆软  应该引起重视
7楼
发表于 2017-8-14 11:02:55
8楼
发表于 2019-8-15 23:11:46
2017年提出的建议,到2019年了,fine report 10竟然也没有改进
9楼
发表于 2020-12-29 09:04:59
是啊         希望尽快改进
10楼
发表于 2021-2-16 09:55:58
到了2021年
帆軟的長官還是沒看見
11楼
发表于 2021-4-19 23:42:56
到了2021年
帆軟的長官還是沒看見
12楼
发表于 2021-4-27 10:12:41

到了2021年
帆軟的長官還是沒看見
13楼
发表于 2021-4-27 21:52:10
到了2021年
帆軟的長官還是沒看見
14楼
发表于 2022-4-30 00:13:40

CONCATENATE('LGCGHT-',供应商简称,'-',TEXT(DATE(签订日期),'yyMMdd'),RIGHT('0000'+TEXT(MAPX("COUNT",TEXT(DATE(签订日期),'yyyy'),年份,年份)+1),4))

  1. 设置一个“年份”文本辅助字段,从“签订日期”字段来取,这样只需要对“年份”进行统计就行了,新的一年就有了新的一年从新开始的编码尾部;
  2. 如果要按照月份来进行也可以采取类似的思路,只是设置辅助字段时要用“年+月”的文本辅助字段。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

14回帖数 13关注人数 24885浏览人数
最后回复于:2022-11-11 17:40

返回顶部 返回列表