在插入时获取下一个数字,在新的一年重置为0

时间:2012-03-21 13:42:40

标签: asp.net sql-server-2005 tsql .net-4.0 identity

我将文档保存到数据库,每个文档都必须有一个格式为YYYY-00000的id:

  • 前4个字符是当前年份
  • 后五个字符是数字。他们每年从1开始然后递增。

例如,我可以在我的数据库中包含这些文件:2011-00001,2011-00002,2011-00003,2012-00001,2012-00002,......

我在想这样的事情:

  • 向表格文档(年份和数字)添加两列
  • 年份是计算列,类似于year(getdate()
  • Number是计算列,它从函数GetNextNumberForCurrentYear
  • 获取值
  • GetNextNumberForCurrentYear返回当前年份的下一个数字(例如select max(Number) + 1 from Documents where Year = year(getdate()),有些是无效检查)

但我担心,两个用户可能希望同时保存文档,并且他们会收到相同的号码。这可能吗?有更好的想法吗?

它是一个ASP.NET C#Web应用程序,.NET 4.0,MSSQL 2005,我可以控制应用程序的所有部分。

PS:插入后我想将新文档的Id返回给用户,所以我可能需要做类似的事情:select Id from Documents where SomeId = scope_identity(),所以我想在某处应该有一个标识列。 ?

编辑(最终解决方案):我从存储过程中获取下一个数字,在.NET中构建文档的Id(格式为YYYY-00001),将整个文档保存到数据库中(使用TransactionScope进行整个过程)和然后将Id返回给用户。

create table DocumentNumbers ([Year] int not null, Number int not null default 1)
insert into DocumentNumbers ([Year], Number)
select 2012, 1 -- and more...

create procedure GetNextDocumentNumber
    @year int
as
begin
    declare @myResult table (nextNumber int) 

    update DocumentNumbers 
    set Number = isnull(Number, 0) + 1 
    output inserted.Number into @myResult 
    where [Year] = @year

    select top 1 nextNumber from @myResult
end

1 个答案:

答案 0 :(得分:2)

您可以创建一个表NumberSeries,其中包含一列Year和一列CurrentNo以及一个返回下一个数字的函数,如下所示:

DECLARE @myResult TABLE (nextNumber INT)

UPDATE NumberSeries
OUTPUT INSERTED.NextNo INTO @myResult
SET
    CurrentNo = ISNULL(CurrentNo, 0) + 1
WHERE
    Year = Year(GetDate())

DECLARE @result INT
@result = (SELECT TOP 1 nextNumber FROM @myResult)

RETURN @result

以原子方式更新NumberSeries表,并将新值插入@myResult表变量中。之后,它返回@myResult表变量中的第一个(也是唯一的)值。

其他所有内容,例如SCOPE_IDENTITY()等,在使用触发器时可能会导致错误,或者在其他情况下 - 使用OUTPUT子句的解决方案是安全的。

修改
至于返回插入文档的ID:这基本上是一样的。

DECLARE @myDocId TABLE (yr int, no int)

INSERT INTO Documents
OUTPUT INSERTED.Year , INSERTED.YearID INTO @myDocID
...

SELECT TOP 1
    CAST(yr AS NVARCHAR) + 
    '_' + 
    RIGHT(REPLICATE('0', 5) + CAST(no AS NVARCHAR), 5) AS NewID