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))  

これがうまくいかない場合は、シーケンス テーブル (シーケンスごとに 1 つ) を作成してみてください。

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

次の ID を取得する手順を作成します。

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 に答える