问题:在实际业务处理中有些单号需要自动增长,但又不能用自增列代替
      eg:  P031106001   -- 第一位P表示采购单,031106表示日期,后三位是流水号。 /* 1:创建测试用的表结构 */
create table tablename(pono char(10),b int)
go
/* 2:创建一个得到当前日期的视图,为下面的自字义函数作准备 */
create view vGetdate
as
  select getdate() as today
go
/* 3:用自定义函数来得到单号(因自定函数内不能用getdate()来得到当前日期,要用到上面的视图) */
create function getDH()
returns char(10)
As
begin
    declare @dh1 char(10),@dh2 char(10)
    select @dh1 = max(pono) from  tableName 
    Set @dh1 = IsNull(@dh1,'P000000000')
    select @dh2 = Left(@dh1,1) + right(convert(varchar(8),today,112),6) + '001' from vGetdate
    if @dh1 >= @dh2
    begin
        set @dh2 = left(@dh1,7) + right('000'+ cast(cast(right(@dh1,3) as int)+1 as varchar),3)
    end    
    return(@dh2)
end
go
/* 4:在字段默认值中填入 dbo.getdh() */
alter table tablename add constraint df_tablename_1 default(dbo.getdh()) for pono
-/* 5:测试:*/
insert tablename(b) values(1)
insert tablename(b) values(2)
Select * from tablename
-- 测试结果
pono       b           
---------- ----------- 
P031115001 1
P031115002 2
总结:此方法运用到了一些小技巧
1:用字段默认值来实现单号自增
2:用自定义函数来得到字段的默认值
3:因在自定义函数中不能用getdate()之类非确定的函数,用视图来得到当前日期

解决方案 »

  1.   

    如果你的id是identity,那么可以用
    select @@identity获得,不会并发。
      

  2.   

    谢谢,那假如我写一个存储过程,这个存储过程功能就是插入一条记录,并取出pono或id作为返回值应该怎么写呢?因为我在存储过程中插入一条纪录后,用@@ROWCOUNT或@@IDENTITY来取的,但此时可能别的线程同样插入了一条记录,这时@@ROWCOUNT或@@IDENTITY可能就不对了!
      

  3.   

    declare @id int
    insert t ...
    select @id=@@identity
      

  4.   

    以前我就是在存储过程中插入语句后SELECT @@IDENTITY,但我的应用程序是多线程的,可能多个线程同时调用这个存储过程,结果发现存储过程返回值有些是重复的!
      

  5.   

    在每次插入数据前用select max(id)+1 from 表
    获得最大id。
      

  6.   

    CREATE PROCEDURE Insert_Log
    ...
    AS
    insert into log(price) valuesprice)select @Trans_Id= @@identityif @Trans_Id is not null
         return @Trans_Id
    else 
         return -1GO
    这样我是能正确插入数据,但得到的Trans_Id在多线程环境下会不会可能是别的线程调用存储过程插入的,会不会别的线程也刚好执行到insert into log(price) valuesprice)这句,望高手能不能解释清楚一下,谢谢!!
      

  7.   

    我觉得:
    你即然有IDEBTITY列.且又是根据IDEBTITY值生成CODE.
    就对代码列用DEFAULT约束.然后,不对它插入值.
    或:
    insert table(CODE,.......) values(default,......)
    让系统自动生成.
    就不用担心并发了.
      

  8.   

    缺省值用IDENTITY生成.绝对不会并发.其它方法并发的可能性都是有的.
      

  9.   

    可以用SCOPE_IDENTITY
    返回插入到同一作用域中的 IDENTITY 列内的最后一个 IDENTITY 值。
      

  10.   

    如果是用@@identity取identity字段值,肯定不会出现重复.因为@@identity总是返回最后一次的identity值,而SQL处理插入数据,不可能出来并发的情况.