1

我有一个表,其中包含交易的标题信息。交易属于不同的项目。

在标题中我有列:

rhguid - uniqueidentifier
rhserial - int
rh_projectID - int

首先我插入行(还有更多列)

然后我计算该项目的序列号:

update responseheader 
set rhSerial = 1 + (select isnull(max(rhSerial), 0) 
                    from responseheader 
                    where (rhstatus = 0) AND (rh_projectID = 1234)) 
where 
   (rhGUID = <preassignedGUID>);

但是,当一个项目同时发生许多事务时,我会发现重复rhserial值。

我在带有 SQL Server 2008 的经典 ASP 中执行此操作。

有没有更好的办法?

4

1 回答 1

1

从您的示例来看,您似乎没有使用交易。我的猜测是语句的 SELECT 部分作为READ UNCOMMITTED运行,否则您将看不到重复项。有多种方法可以使用 ADO 启动事务,但我更喜欢使用存储过程。

尝试实现这样的事情:

CREATE PROC dbo.ResponseHeader_Insert
  <more data to insert>,
  @ProjectID INT,
  @Status SMALLINT
as

insert responseheader (column names here)
select <param values here>, isnull(max(rhSerial), 0) + 1
from responseheader  
where (rhstatus = @Status) AND (rh_projectID = @ProjectID))  

如果这对你不起作用,请尝试创建序列表(每个序列一个)。

create table <tablename> (
      SeqID int identity(1,1) primary key,
      SeqVal varchar(1)
)

创建一个获取下一个身份的过程:

create procedure GetNewSeqVal_<tablename>
as
begin
      declare @NewSeqValue int

      set NOCOUNT ON

      insert into <tablename> (SeqVal) values ('a')
      set @NewSeqValue = scope_identity()
      delete from <tablename> WITH (READPAST)
return @NewSeqValue
end

如果需要创建的序列表太多,或者您想即时创建序列,请尝试以下方法:

Create table AllSequences (
      SeqName nvarchar(255) primary key, -- name of the sequence
      Seed int not null default(1), -- seed value
      Incr int not null default(1), -- incremental
      Currval int 
)
Go

create procedure usp_CreateNewSeq
      @SeqName nvarchar(255),
      @seed int = 0,
      @incr int = 1
as

begin

      declare @currval int
      if exists (
            select 1 from AllSequences
            where SeqName = @SeqName )

      begin
            print 'Sequence already exists.'
            return 1    
      end

      if @seed is null set @seed = 1
      if @incr is null set @incr = 1
      set @currval = @seed

      insert into AllSequences (SeqName, Seed, Incr, CurrVal)
      values (@SeqName, @Seed, @Incr, @CurrVal)
end
go


create procedure usp_GetNewSeqVal

      @SeqName nvarchar(255)
as

begin
      declare @NewSeqVal int
      set NOCOUNT ON

      update AllSequences
      set @NewSeqVal = CurrVal = CurrVal+Incr
      where SeqName = @SeqName

      if @@rowcount = 0 begin
            print 'Sequence does not exist'
            return
      end
      return @NewSeqVal
end
go
于 2012-04-22T14:01:30.497 回答