Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2534935
  • 博文数量: 308
  • 博客积分: 5547
  • 博客等级: 大校
  • 技术积分: 3782
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-24 09:47
个人简介

hello world.

文章分类

全部博文(308)

分类: SQLServer

2014-08-18 00:10:49

    当我们设计系统时,特别是涉及到主从表的时候,一般都会碰到从表的ID,要和主表的ID一致的情况。还有单据的流水号问题,要保证在并发请求时,流水号不能重复的现象。网上也有很多解决类似问题的代码,参照网上的方法,结合自己的理解,在SqlServer 2005下,设计相关的表,存储过程,实现这样的功能。
    我将一个流水号,分为四部分:头部、中间1、中间2,尾部。其中四部分类型,分成三种类型,固定值(fixed),日期类型(yyyyMMdd... ...),流水类型(sync)。
    固定值类型,值保持不变;日期类型,根据格式不同,值也就相应的不同;流水类型很容易理解,就是从1一直递增下去。
    其中流水号的中间1,中间2,部分。是为了处理以下的这种情况设计的。比如说,当天的流水号从1,第二天又要从1进行。如果想要这样的流水号,则将中间1类型设置为日期类型,中间2类型设置为流水类型即可。
    另外流水的四部分,中的每个部分,还有长度的定义,该长度用于当该部分为流水类型时,可以设置流水号的长度,不够长度则前面补充0;
     表设计如下:

点击(此处)折叠或打开

  1. /****** 对象: Table [dbo].[sys_sequence_info] 脚本日期: 08/17/2014 23:47:10 ******/
  2. SET ANSI_NULLS ON
  3. GO
  4. SET QUOTED_IDENTIFIER ON
  5. GO
  6. SET ANSI_PADDING ON
  7. GO
  8. CREATE TABLE [dbo].[sys_sequence_info](
  9.     [sync_id] [decimal](8, 0) NOT NULL,
  10.     [sync_code] [varchar](200) COLLATE Chinese_PRC_CI_AS NOT NULL,
  11.     [sync_name] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
  12.     [sync_value] [varchar](400) COLLATE Chinese_PRC_CI_AS NULL,
  13.     [sync_head_type] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  14.     [sync_head_value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  15.     [sync_head_len] [numeric](2, 0) NULL CONSTRAINT [DF__sys_seque__sync___07F6335A] DEFAULT ((0)),
  16.     [sync_middle_type1] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  17.     [sync_middle_value1] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  18.     [sync_middle1_len] [numeric](2, 0) NULL CONSTRAINT [DF__sys_seque__sync___09DE7BCC] DEFAULT ((0)),
  19.     [sync_middle_type2] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  20.     [sync_middle_value2] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  21.     [sync_middle2_len] [numeric](2, 0) NULL CONSTRAINT [DF__sys_seque__sync___0BC6C43E] DEFAULT ((0)),
  22.     [sync_end_type] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  23.     [sync_end_value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  24.     [sync_end_len] [numeric](2, 0) NULL CONSTRAINT [DF__sys_seque__sync___0DAF0CB0] DEFAULT ((0)),
  25.     [sync_split_value] [varchar](10) COLLATE Chinese_PRC_CI_AS NULL,
  26.     [sync_update_time] [datetime] NULL,
  27.     [sync_ctrl] [varchar](1) COLLATE Chinese_PRC_CI_AS NULL,
  28.     [row_id] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  29.     [sync_remark] [varchar](500) COLLATE Chinese_PRC_CI_AS NULL,
  30.  CONSTRAINT [PK_SYS_SEQUENCE_INFO] PRIMARY KEY CLUSTERED
  31. (
  32.     [sync_id] ASC
  33. )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
  34. ) ON [PRIMARY]

  35. GO
  36. SET ANSI_PADDING OFF
  37. GO
  38. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'当配置类为sync时,此字段记录流水的长度,如果长度不够,前面补充''0''' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'sys_sequence_info', @level2type=N'COLUMN', @level2name=N'sync_head_len'

  39. GO
  40. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'当配置类为sync时,此字段记录流水的长度,如果长度不够,前面补充''0''' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'sys_sequence_info', @level2type=N'COLUMN', @level2name=N'sync_middle1_len'

  41. GO
  42. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'当sync_middle_type1为日期类型,而sync_middle_type2为sync类型时,则sync_middle_value2值为当天的序列号' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'sys_sequence_info', @level2type=N'COLUMN', @level2name=N'sync_middle_type2'

  43. GO
  44. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'当配置类为sync时,此字段记录流水的长度,如果长度不够,前面补充''0''' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'sys_sequence_info', @level2type=N'COLUMN', @level2name=N'sync_middle2_len'

  45. GO
  46. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'当配置类为sync时,此字段记录流水的长度,如果长度不够,前面补充''0''' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'sys_sequence_info', @level2type=N'COLUMN', @level2name=N'sync_end_len'

  47. GO
  48. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'流水信息表,方便生成流水编码。' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'sys_sequence_info'

  49. GO
  50. USE [my_jxc]
  51. GO
  52. ALTER TABLE [dbo].[sys_sequence_info] WITH CHECK ADD CONSTRAINT [CKC_SYNC_END_TYPE_SYS_SEQU] CHECK (([sync_end_type] IS NULL OR ([sync_end_type]='sync' OR [sync_end_type]='yyMMdd' OR [sync_end_type]='yy-MM-dd' OR [sync_end_type]='yyyyMMdd' OR [sync_end_type]='yyyy-MM-dd' OR [sync_end_type]='yyMM' OR [sync_end_type]='yy-MM' OR [sync_end_type]='yyyyMM' OR [sync_end_type]='yyyy-MM' OR [sync_end_type]='fixed')))
  53. GO
  54. ALTER TABLE [dbo].[sys_sequence_info] WITH CHECK ADD CONSTRAINT [CKC_SYNC_HEAD_TYPE_SYS_SEQU] CHECK (([sync_head_type] IS NULL OR ([sync_head_type]='sync' OR [sync_head_type]='yyMMdd' OR [sync_head_type]='yy-MM-dd' OR [sync_head_type]='yyyyMMdd' OR [sync_head_type]='yyyy-MM-dd' OR [sync_head_type]='yyMM' OR [sync_head_type]='yy-MM' OR [sync_head_type]='yyyyMM' OR [sync_head_type]='yyyy-MM' OR [sync_head_type]='fixed')))
  55. GO
  56. ALTER TABLE [dbo].[sys_sequence_info] WITH CHECK ADD CONSTRAINT [CKC_SYNC_MIDDLE_TYPE1_SYS_SEQU] CHECK (([sync_middle_type1] IS NULL OR ([sync_middle_type1]='sync' OR [sync_middle_type1]='yyMMdd' OR [sync_middle_type1]='yy-MM-dd' OR [sync_middle_type1]='yyyyMMdd' OR [sync_middle_type1]='yyyy-MM-dd' OR [sync_middle_type1]='yyMM' OR [sync_middle_type1]='yy-MM' OR [sync_middle_type1]='yyyyMM' OR [sync_middle_type1]='yyyy-MM' OR [sync_middle_type1]='fixed')))
  57. GO
  58. ALTER TABLE [dbo].[sys_sequence_info] WITH CHECK ADD CONSTRAINT [CKC_SYNC_MIDDLE_TYPE2_SYS_SEQU] CHECK (([sync_middle_type2] IS NULL OR ([sync_middle_type2]='sync' OR [sync_middle_type2]='yyMMdd' OR [sync_middle_type2]='yy-MM-dd' OR [sync_middle_type2]='yyyyMMdd' OR [sync_middle_type2]='yyyy-MM-dd' OR [sync_middle_type2]='yyMM' OR [sync_middle_type2]='yy-MM' OR [sync_middle_type2]='yyyyMM' OR [sync_middle_type2]='yyyy-MM' OR [sync_middle_type2]='fixed')))
  59. GO
    而,如果想在并行环境下,获取唯一的流水号,经过思考,采用存储过程完成。
    其原理是:当一个请求过来时,先使用一个guid,判断流水表的数据字段sync_ctrl是否被预占(0:未预占,1:已预占);如果没有被预占,则当前请求,进行预占操作。然后计算流水号。计算完毕后,将预占位取消。将流水号返回。具体请参考存储过程:P_SeqStr
    相关代码如下:

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO

  5. --获取当前日期的格式化字符串
  6. --author:程晓鹏
  7. --date:2014.8.3
  8. CREATE function [dbo].[FormatDate](@dateType varchar(20))
  9. returns varchar(50)
  10. as
  11. begin;
  12.   declare @result varchar(50); --定义返回值
  13.   declare @strYY varchar(4); --年份yyyy
  14.   declare @strYY2 varchar(2); --年份yy
  15.   declare @strMM varchar(2); --月份MM
  16.   declare @strDD varchar(2); --天数dd
  17.   declare @strDateType varchar(20);
  18.   
  19.   set @strDateType = upper(@dateType); --全部变为大写,进行判断
  20.   set @strYY = dbo.TrimString(year(getdate())); --4位数字的年份字符串
  21.   set @strYY2 = substring(@strYY, 3, 2); --4为年份数字的最后两位
  22.   set @strMM = dbo.FormatString(dbo.TrimString(month(getdate())), 'H', '0', 2); --月份两位数据
  23.   set @strDD = dbo.FormatString(dbo.TrimString(day(getdate())), 'H', '0', 2); --日,两位数表示
  24.   set @result = '';
  25.   
  26.   --根据入参,进行返回值的赋值
  27.   if (@strDateType = 'YYYYMMDD')
  28.     begin;
  29.       set @result = @strYY + @strMM + @strDD;
  30.     end;
  31.   else if (@strDateType = 'YYYY-MM-DD')
  32.     begin;
  33.       set @result = @strYY + '-' + @strMM + '-' + @strDD;
  34.     end;
  35.   else if (@strDateType = 'YYMMDD')
  36.     begin;
  37.       set @result = @strYY2 + @strMM + @strDD;
  38.     end;
  39.   else if (@strDateType = 'YY-MM-DD')
  40.     begin;
  41.       set @result = @strYY2 + '-' + @strMM + '-' + @strDD;
  42.     end;
  43.   else if (@strDateType = 'YYMM')
  44.     begin;
  45.       set @result = @strYY2 + @strMM;
  46.     end;
  47.   else if (@strDateType = 'YY-MM')
  48.     begin;
  49.       set @result = @strYY2 + '-' + @strMM;
  50.     end;
  51.   else if (@strDateType = 'YYYYMM')
  52.     begin;
  53.       set @result = @strYY + @strMM;
  54.     end;
  55.   else if (@strDateType = 'YYYY-MM')
  56.     begin;
  57.       set @result = @strYY + '-' + @strMM;
  58.     end;
  59.   else if (@strDateType = 'YYYY')
  60.     begin;
  61.       set @result = @strYY;
  62.     end;
  63.   else if (@strDateType = 'YY')
  64.     begin;
  65.       set @result = @strYY2;
  66.     end;
  67.   else
  68.     begin;
  69.       set @result = @strYY + '-' + @strMM + '-' + @strDD; --默认值
  70.     end;
  71.  
  72.   return @result; --返回结果
  73. end;

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO

  5. --格式化字符串,如果原字符串str长度,没有达到入参length,规定的长度,则使用fileChar,进行字符填充。
  6. --其中填充位置fillPosition如果为'H',则在原字符串前;若为'E',则在原字符串后。
  7. --author:程晓鹏
  8. --date:2014.8.3
  9. CREATE function [dbo].[FormatString](
  10.   @str varchar(8000), --原始字符串
  11.   @fillPosition varchar(1), --填充位置;H:在原字符串前面;E:在原字符串的后面
  12.   @fillChar varchar(1), --填充的字符串
  13.   @length int --返回结果的字符串长度
  14. )
  15. returns varchar(8000)
  16. as
  17. begin;
  18.   declare @result varchar(8000); --定义返回值
  19.   declare @strFillTmp varchar(8000); --临时填充字符串
  20.   declare @strFileTmpLen int; --临时填充的长度
  21.   declare @strLen int; --输入字符串的长度
  22.   declare @strFillChar varchar(1); --填充字符
  23.   declare @i int; --循环变量
  24.   
  25.   set @strFillChar = ''; --设置默认填充字符为空格
  26.   set @strFillTmp = ''; --临时填充字符串,默认为空
  27.   set @strLen = len(@str);
  28.   set @i = 0;
  29.   
  30.   --判断入参,设置填充字符
  31.   if(len(@fillChar) > 0)
  32.     begin;
  33.       set @strFillChar = @fillChar;
  34.     end;
  35.   else
  36.     begin;
  37.        set @strFillChar = ' ';
  38.     end;
  39.   
  40.   --判断是否需要进行字符串填充
  41.   if(@strLen < @length)
  42.     begin;
  43.       set @strFileTmpLen = @length - @strLen; --计算差异的长度
  44.       while(@i < @strFileTmpLen)
  45.       begin;
  46.         set @strFillTmp = @strFillTmp + @strFillChar; --进行差异字符串填充
  47.         set @i = @i + 1;
  48.       end;
  49.     end;
  50.   else
  51.     begin;
  52.       set @result = @str;
  53.     end;

  54.   --根据填充的位置,进行返回字符串的处理
  55.   if(@fillPosition = 'H')
  56.     begin;
  57.       set @result = @strFillTmp + @str;
  58.     end;
  59.   else if(@fillPosition = 'E')
  60.     begin;
  61.       set @result = @str + @strFillTmp
  62.     end;
  63.   
  64.   --返回结果
  65.   return @result;
  66. end;

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO

  5. --删除字符串左右两侧的空格
  6. --author:程晓鹏
  7. --date:2014.8.3
  8. create function [dbo].[TrimString](@str varchar(8000))
  9. returns varchar(8000)
  10. as
  11. begin;
  12.   declare @result varchar(8000); --定义返回值
  13.   set @result = ltrim(rtrim(@str));

  14.   return @result;
  15. end;

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO
  5. --判断类型是否是日期类型参数
  6. --author:程晓鹏
  7. --date:2014.8.11
  8. create function [dbo].[ValidDate](@strType varchar(20))
  9. returns varchar(1)
  10. as
  11. begin;
  12.   declare @result varchar(1); --定义返回值
  13.   declare @strDateType varchar(20);
  14.   
  15.   set @strDateType = upper(@strType); --全部变为大写,进行判断
  16.   set @result = '0';
  17.   
  18.   --根据入参,进行返回值的赋值
  19.   if (@strDateType = 'YYYYMMDD')
  20.     begin;
  21.       set @result = '1';
  22.     end;
  23.   else if (@strDateType = 'YYYY-MM-DD')
  24.     begin;
  25.       set @result = '1';
  26.     end;
  27.   else if (@strDateType = 'YYMMDD')
  28.     begin;
  29.       set @result = '1';
  30.     end;
  31.   else if (@strDateType = 'YY-MM-DD')
  32.     begin;
  33.       set @result = '1';
  34.     end;
  35.   else if (@strDateType = 'YYMM')
  36.     begin;
  37.       set @result = '1';
  38.     end;
  39.   else if (@strDateType = 'YY-MM')
  40.     begin;
  41.       set @result = '1';
  42.     end;
  43.   else if (@strDateType = 'YYYYMM')
  44.     begin;
  45.       set @result = '1';
  46.     end;
  47.   else if (@strDateType = 'YYYY-MM')
  48.     begin;
  49.       set @result = '1';
  50.     end;
  51.   else if (@strDateType = 'YYYY')
  52.     begin;
  53.       set @result = '1';
  54.     end;
  55.   else if (@strDateType = 'YY')
  56.     begin;
  57.       set @result = '1';
  58.     end;
  59.   else
  60.     begin;
  61.       set @result = '0'; --默认值
  62.     end;
  63.  
  64.   return @result; --返回结果
  65. end;

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO

  5. --获取流水号
  6. --author:程晓鹏
  7. --date:2014.8.14
  8. CREATE proc [dbo].[P_SeqStr](@syncCode varchar(200), @result varchar(400) output)
  9. as
  10. begin;
  11.   --开始事务
  12.   set xact_abort on;
  13.   begin transaction;

  14.   --以下定义的是查询后,各个字段的值
  15.   declare @strHeadType varchar(50);
  16.   declare @strHeadValue varchar(50);
  17.   declare @intHeadLen numeric(2,0);
  18.   
  19.   declare @strMiddleType1 varchar(50);
  20.   declare @strMiddleValue1 varchar(50);
  21.   declare @strMiddleValue1_new varchar(50);
  22.   declare @intMiddleLen1 numeric(2,0);
  23.   
  24.   declare @strMiddleType2 varchar(50);
  25.   declare @strMiddleValue2 varchar(50);
  26.   declare @intMiddleLen2 numeric(2,0);
  27.   
  28.   declare @strEndType varchar(50);
  29.   declare @strEndValue varchar(50);
  30.   declare @intEndLen numeric(2,0);
  31.   
  32.   declare @strSplitValue varchar(10);
  33.   declare @updateTime datetime;

  34.   --最终结果各个节点的数据值
  35.   declare @str_HeadValue varchar(50);
  36.   declare @str_MiddleValue1 varchar(50);
  37.   declare @str_MiddleValue2 varchar(50);
  38.   declare @str_EndValue varchar(50);

  39.   --定义行id,避免存储过程,并发执行,出现返回的流水重复的现象
  40.   declare @strNewID varchar(50);
  41.   declare @intCtrl int;

  42.   --设置返回值为空字符串
  43.   set @result = '';
  44.   set @strNewID = newid();
  45.   
  46.   --当sync_ctrl = '0',用当前的row_id,进行预占操作,这样可以防止并行运行造成流水重复现象
  47.   update dbo.sys_sequence_info set
  48.     row_id = @strNewID,
  49.     sync_ctrl = '1'
  50.   where sync_ctrl = '0' and sync_code = @syncCode;
  51.   commit;
  52.   
  53.   
  54.   --判断当前rowid,是否预占成功,如果没有预占成功,则返回1。否则继续执行,直到计算出流水ID
  55.   select @intCtrl = count(1)
  56.   from dbo.sys_sequence_info
  57.   where row_id = @strNewID and sync_code = @syncCode;

  58.   if (@intCtrl = 0) --当没有占用时,返回值1
  59.     begin;
  60.       return 1;
  61.     end;

  62.   --执行查询操作
  63.   select @strHeadType = upper(isnull(sync_head_type, 'fixed')),
  64.          @strHeadValue = isnull(sync_head_value, ''),
  65.          @intHeadLen = isnull(sync_head_len, 0),
  66.          @strMiddleType1 = upper(isnull(sync_middle_type1, 'fixed')),
  67.          @strMiddleValue1 = isnull(sync_middle_value1, ''),
  68.          @intMiddleLen1 = isnull(sync_middle1_len, 0),
  69.          @strMiddleType2 = upper(isnull(sync_middle_type2, 'fixed')),
  70.          @strMiddleValue2 = isnull(sync_middle_value2, ''),
  71.          @intMiddleLen2 = isnull(sync_middle2_len, 0),
  72.          @strEndType = upper(isnull(sync_end_type, 'fixed')),
  73.          @strEndValue = isnull(sync_end_value, ''),
  74.          @intEndLen = isnull(sync_end_len, 0),
  75.          @strSplitValue = isnull(sync_split_value, ''),
  76.          @updateTime = sync_update_time
  77.   from dbo.sys_sequence_info
  78.   where sync_ctrl = '1' and row_id =@strNewID and sync_code = @syncCode;

  79.   --对headType进行处理,当为日期类型时,将当前日期字符串进行赋值;
  80.   --若为sync类型时,则在原有值得基础上自增1
  81.   if (dbo.ValidDate(@strHeadType) = '1')
  82.     begin;
  83.       set @strHeadValue = dbo.FormatDate(@strHeadType);
  84.     end;
  85.   else if (@strHeadType = upper('sync'))
  86.     begin;
  87.       if (@strHeadValue = '')
  88.         begin;
  89.           set @strHeadValue = '1'; --当为空时,则值为'1'
  90.         end;
  91.       else
  92.         begin;
  93.          set @strHeadValue = convert(varchar, convert(int,@strHeadValue + 1));
  94.         end;
  95.     end;

  96.   --对MiddleType1进行处理,当为日期类型时,将当前日期字符串进行赋值;
  97.   --若为sync类型时,则在原有值得基础上自增1
  98.   if (dbo.ValidDate(@strMiddleType1) = '1')
  99.     begin;
  100.       set @strMiddleValue1_new = dbo.FormatDate(@strMiddleType1);
  101.     end;
  102.   else if (@strMiddleType1 = upper('sync'))
  103.     begin;
  104.       if (@strMiddleValue1 = '')
  105.         begin;
  106.           set @strMiddleValue1_new = '1'; --当为空时,则值为'1'
  107.         end;
  108.       else
  109.         begin;
  110.          set @strMiddleValue1_new = convert(varchar, convert(int,@strMiddleValue1 + 1));
  111.         end;
  112.     end;
  113.   else
  114.     begin;
  115.       set @strMiddleValue1_new = @strMiddleValue1;
  116.     end;

  117.   --对MiddleType2进行处理:
  118.   --当MiddleType1为日期类型,并且MiddleType2为sync类型时,则MiddleValue2的值为当前的流水号,流水号默认从1,进行累加计算
  119.   --若MiddleType2为日期类型时,将当前日期字符串进行赋值;
  120.   if (dbo.ValidDate(@strMiddleType1) = '1' and @strMiddleType2 = upper('sync'))
  121.     begin;
  122.       if (@strMiddleValue1 = dbo.FormatDate(@strMiddleType1))
  123.         begin;
  124.           set @strMiddleValue2 = convert(varchar, convert(int,@strMiddleValue2 + 1));
  125.         end;
  126.       else
  127.         begin;
  128.           set @strMiddleValue2 = '1'; --MiddleType1不是当天,则从'1',进行重新计数
  129.         end;
  130.     end;
  131.   else if (dbo.ValidDate(@strMiddleType2) = '1')
  132.     begin;
  133.       set @strMiddleValue2 = dbo.FormatDate(@strMiddleType2);
  134.     end;

  135.   --对EndType进行处理,当为日期类型时,将当前日期字符串进行赋值;
  136.   --若为sync类型时,则在原有值得基础上自增1
  137.   if (dbo.ValidDate(@strEndType) = '1')
  138.     begin;
  139.       set @strEndValue = dbo.FormatDate(@strEndType);
  140.     end;
  141.   else if (@strEndType = upper('sync'))
  142.     begin;
  143.       if (@strEndValue = '')
  144.         begin;
  145.           set @strEndValue = '1'; --当为空时,则值为'1'
  146.         end;
  147.       else
  148.         begin;
  149.          set @strEndValue = convert(varchar, convert(int,@strEndValue + 1));
  150.         end;
  151.     end;

  152.   --计算各个节点的返回值
  153.   --HeadType
  154.   if (@strHeadType = upper('sync'))
  155.     begin;
  156.       set @str_HeadValue = dbo.FormatString(@strHeadValue, 'H', '0', @intHeadLen);
  157.     end;
  158.   else if (len(@strHeadValue) > 0)
  159.     begin;
  160.       set @str_HeadValue = @strHeadValue;
  161.     end;
  162.   else
  163.     begin;
  164.       set @str_HeadValue = '';
  165.     end;

  166.   --MiddleType1
  167.   if (@strMiddleType1 = upper('sync'))
  168.     begin;
  169.       set @str_MiddleValue1 = dbo.FormatString(@strMiddleValue1_new, 'H', '0', @intMiddleLen1);
  170.     end;
  171.   else if (len(@strMiddleValue1) > 0)
  172.     begin;
  173.       set @str_MiddleValue1 = @strMiddleValue1_new;
  174.     end;
  175.   else
  176.     begin;
  177.       set @str_MiddleValue1 = '';
  178.     end;

  179.   --MiddleType2
  180.   if (@strMiddleType2 = upper('sync'))
  181.     begin;
  182.       set @str_MiddleValue2 = dbo.FormatString(@strMiddleValue2, 'H', '0', @intMiddleLen2);
  183.     end;
  184.   else if (len(@strMiddleValue2) > 0)
  185.     begin;
  186.       set @str_MiddleValue2 = @strMiddleValue2;
  187.     end;
  188.   else
  189.     begin;
  190.       set @str_MiddleValue2 = '';
  191.     end;

  192.   --EndType
  193.   if (@strEndType = upper('sync'))
  194.     begin;
  195.       set @str_EndValue = dbo.FormatString(@strEndValue, 'H', '0', @intEndLen);
  196.     end;
  197.   else if (len(@strEndValue) > 0)
  198.     begin;
  199.       set @str_EndValue = @strEndValue;
  200.     end;
  201.   else
  202.     begin;
  203.       set @str_EndValue = '';
  204.     end;

  205.   --计算,最后要返回的字符串
  206.   if (len(@str_HeadValue) > 0) --当HeadValue含有字符串时,添加进去
  207.     begin;
  208.       set @result = @result + @str_HeadValue;
  209.     end;

  210.   if (len(@str_MiddleValue1) > 0)
  211.     begin;
  212.        if (len(@str_HeadValue) > 0) --当HeadValue有数据时,添加分割字符串
  213.         begin;
  214.           set @result = @result + @strSplitValue;
  215.         end;
  216.        set @result = @result + @str_MiddleValue1;
  217.     end;

  218.   if (len(@str_MiddleValue2) > 0)
  219.     begin;
  220.       if (len(@str_MiddleValue1) > 0) --当MiddleValue1有数据时,添加分割符
  221.         begin;
  222.           set @result = @result + @strSplitValue;
  223.         end;
  224.       else if (len(@str_HeadValue) > 0) --当MiddleValue1为空,而HeadValue不为空,则添加分割字符串
  225.         begin;
  226.           set @result = @result + @strSplitValue;
  227.         end;
  228.       set @result = @result + @str_MiddleValue2;
  229.     end;

  230.   if(len(@str_EndValue) > 0)
  231.     begin;
  232.       if (len(@str_MiddleValue2) > 0) --当MiddleValue2有数据时,添加分割符
  233.         begin;
  234.           set @result = @result + @strSplitValue;
  235.         end;
  236.       else if (len(@str_HeadValue) > 0 or len(@str_MiddleValue1) > 0) --当MiddleValue2没有数据,而HeadValue或者MiddleValue有数据,则添加分割字符串
  237.         begin;
  238.           set @result = @result + @strSplitValue;
  239.         end;
  240.       set @result = @result + @str_EndValue;
  241.     end;

  242.   --更新数据库中的数据,为下次计算做准备
  243.   update dbo.sys_sequence_info set
  244.     sync_value = @result,
  245.     sync_head_value = @strHeadValue,
  246.     sync_middle_value1 = @strMiddleValue1_new,
  247.     sync_middle_value2 = @strMiddleValue2,
  248.     sync_end_value = @strEndValue,
  249.     sync_update_time = getdate(),
  250.     sync_ctrl = '0'
  251.   where sync_ctrl = '1' and row_id =@strNewID and sync_code = @syncCode;

  252.   return 0; --正常返回
  253.   commit transaction; --提交事务
  254. end;

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO

  5. --获取流水号
  6. --author:程晓鹏
  7. --date:2014.8.15
  8. CREATE proc [dbo].[P_Get_SeqStr](@syncCode varchar(200), @syncStr varchar(400) output)
  9. as
  10. begin;
  11.   declare @i int;
  12.   declare @p_return_value int; --定义存储过程返回值
  13.   declare @maxcount int; --定义获取流水号时,如果失败,重试的次数
  14.   declare @strResult varchar(400); --返回的字符串
  15.   declare @intCount int; --记录syncCode是否存在
  16.   
  17.   --状态值; 0:正常返回流水号;1:获取流水号超时;2:入参在配置流水表不存在
  18.   declare @state int;
  19.   set @state = 0;
  20.   set @i = 0;
  21.   set @maxcount = 500;
  22.   set @SyncStr = '';
  23.   set @strResult = ''; --要返回的字符串


  24.   --判断入参@syncCode,在数据库,是否配置的有
  25.   select @intCount = count(1)
  26.   from dbo.sys_sequence_info
  27.   where sync_code = @syncCode;

  28.   if (@intCount = 0) --当入参@syncCode,在数据库不存在时,返回值2
  29.     begin;
  30.       set @state = 2;
  31.       set @SyncStr = '错误:入参在配置表sys_sequence_info不存在。[@syncCode = ' + dbo.TrimString(@syncCode) + ']';
  32.       return @state;
  33.     end;

  34. while (@i<@maxcount)
  35.   begin;
  36.     EXEC @p_return_value = [dbo].[P_SeqStr]
  37.          @syncCode = @syncCode,
  38.          @result = @strResult OUTPUT;
  39.         set @i = @i + 1; --自加一
  40.         if (@p_return_value = 0)
  41.           begin;
  42.             set @state = 0;
  43.             set @syncStr = @strResult; --对返回的字符串进行赋值
  44.             break;
  45.           end;
  46.         else if (@i + 1 = @maxcount and @p_return_value = 1)
  47.           begin;
  48.             set @state = 1;
  49.             set @syncStr = '错误:获取流水号超时。[共尝试了' + dbo.TrimString(str(@maxcount)) + '次]';
  50.           end;
  51.   end;
  52.   return @state;
  53. end;
=========================================================
为了方便,进行并行执行,获取流水号的测试,可以创建如下的测试表,进行测试。

点击(此处)折叠或打开

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO
  5. SET ANSI_PADDING ON
  6. GO
  7. CREATE TABLE [dbo].[sync_test](
  8.     [id] [varchar](500) COLLATE Chinese_PRC_CI_AS NULL,
  9.     [user_name] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
  10.     [write_date] [datetime] NULL
  11. ) ON [PRIMARY]

  12. GO
测试脚本如下:

点击(此处)折叠或打开

  1. declare    @result varchar(400);
  2. declare @i int;
  3. declare @return_value int;
  4. set @i=0;
  5. while @i<10000
  6.   begin
  7.     EXEC @return_value = [dbo].[P_Get_SeqStr]
  8.         @syncCode = N'test_1',
  9.         @syncStr = @result OUTPUT;
  10.         if (@return_value = 0)
  11.         begin;
  12.           insert into sync_test(id,user_name, write_date) values(@result, 'test_2', getdate());
  13.           set @i=@i+1;
  14.         end;
  15.   end;
测试结果,截图如下:

完整的脚本文件如下:
SqlServer流水号管理.rar




阅读(9712) | 评论(0) | 转发(0) |
0

上一篇:文件切割

下一篇:shell与sqlplus的交互

给主人留下些什么吧!~~