2012-04-22 2 views
1

트랜잭션에 대한 헤더 정보가 들어있는 테이블이 있습니다. 트랜잭션은 다른 프로젝트에 속합니다. 내가 열이 헤더에 테이블의 행을 직렬화

그러나

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

: 나는 행을 삽입

rhguid - uniqueidentifier 
rhserial - int 
rh_projectID - int 

먼저 내가 그 프로젝트에 대한 일련 번호를 계산 다음

(더 열이있다) 프로젝트를 위해 동시에 많은 트랜잭션이 발생하면 rhserial 중복 값을 찾습니다.

내가 SQL Server와 고전적인 ASP에서이 일을하고있어 2008 년

는 더 좋은 방법이 있나요?

+0

'rhserial' 컬럼을'INT IDENTITY' 컬럼으로 만들고 순차 번호를 SQL 서버로 늘리면 안 될까요? 이것이 가장 좋은 방법입니다 - 번거롭고 번거롭지 않습니다. SQL 서버가 –

+0

으로 작업하게하십시오. 각 프로젝트마다 고유 한 일련 번호가 필요하기 때문입니다. 따라서 프로젝트 1234는 1에서 위로 rhserial을가집니다. 그리고 1235 프로젝트는 1에서 위로 rhserial을 가질 것입니다. rhserial은 테이블에서 고유하지 않습니다. – derekcohen

+1

그런 경우, (1) 각 프로젝트의 현재 일련 번호가있는 테이블과 (2) 각 프로젝트의 다음 유효한 번호를 가져 오는 스레드 및 동시성 안전 메소드 (예 : 저장 프로 시저)가 있어야합니다. 그 "serial-no table". 'SELECT MAX() + 1'을 사용하는 것만으로도 ** 안전하지 않습니다 **. [이렇게 다른 방법을 보여주는 Remus Rusanu의 다른 질문을 참조하십시오] (http://stackoverflow.com/questions/5083846/sql-server-2005-using-generated-sequences-instead-of-identity-columns) –

답변

1

예를 들어 볼 때 거래가 사용중인 것처럼 보이지 않습니다. 내 생각 엔 성명의 SELECT 부분이 로 표시되어 있습니다. 읽지 않은 경우을 읽으십시오. 그렇지 않으면 중복이 표시되지 않습니다. 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 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 <tablename> (
     SeqID int identity(1,1) primary key, 
     SeqVal varchar(1) 
) 

다음 정체성을받을 수있는 프로 시저를 작성

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 
+0

알 수없는 길이의 수천 개의 독립 시퀀스가 ​​있으므로 첫 번째 저장 프로 시저 메서드가 가장 잘 작동 할 수 있습니다. SP는 삽입이 아닌 삽입 (아마도 전체 행)을 사용합니다. SP에서 거래 문제를 극복하고 있습니까? 감사합니다 – derekcohen

+0

@derekcohen, 그 자체로는 아니지만, 그것은 쉽습니다. Tran/Commit Tran 시작을보십시오. 첫 번째 저장된 proc 파일에 begin/commit tran을 추가하지 않은 이유는 insert 문이 하나뿐이기 때문입니다. ADO를 사용하여 동일한 작업을 수행 할 수 있으며 트랜잭션 생성에 대해 걱정하지 않아도됩니다. 원래 쿼리는 삽입/업데이트 (2 문장)였습니다. 단일 트랜잭션에서 트랜잭션을 실행하려면 begin/commit tran을 사용하거나 ADO를 사용하여 트랜잭션을 시작해야합니다. –

+0

감사합니다. 매우 도움이되었습니다. – derekcohen

관련 문제