2012-02-23 17 views
0

穏やかに、私はSQL初心者です。SQL Serverで重複した自動番号が生成される

Prefix | AutoNumber 
SO  | 112320 
CA  | 3542 

A新しい販売行が作成されるたびに、ストアドプロシージャが「SO」の行から現在のオートナンバー型の値を読み込み、その呼ばれ、その後、番号をインクリメントし、更新する:私はこのような名前のテーブルautonumber_settingsを持っています同じ行に移動し、ストアドプロシージャから数値を戻します。ストアドプロシージャは、以下である:

ALTER PROCEDURE [dbo].[GetAutoNumber] 
(
    @type nvarchar(50) , 
    @out nvarchar(50) = '' OUTPUT 
) 
as 
set nocount on 

declare @currentvalue nvarchar(50) 
declare @prefix nvarchar(10) 

if exists (select * from autonumber_settings where lower(autonumber_type) = lower(@type)) 
begin 
    select @prefix = isnull(autonumber_prefix,''),@currentvalue=autonumber_currentvalue 
    from autonumber_settings 
    where lower(autonumber_type) = lower(@type) 

    set @currentvalue = @currentvalue + 1 

    update dbo.autonumber_settings set autonumber_currentvalue = @currentvalue where lower(autonumber_type) = lower(@type) 
    set @out = cast(@prefix as nvarchar(10)) + cast(@currentvalue as nvarchar(50)) 
    select @out as value 
end 
else 
    select '' as value 

次に、ヘッダと行の両方をコピーし、注文を複製同じテーブルにアクセスする別の手順があります。場合によっては、重複によって行番号が重複します。二つの手順は時折重複によって作成された線としてゼロから作成された同じ行番号を与え、一緒にうまくプレーしていないようだ理由について

BEGIN TRAN 

IF exists 
(
     SELECT * 
     FROM autonumber_settings 
     WHERE autonumber_type = 'SalesOrderDetail' 
) 
BEGIN 
     SELECT 
       @prefix = ISNULL(autonumber_prefix,'') 
       ,@current_value=CAST (autonumber_currentvalue AS INTEGER) 
     FROM autonumber_settings 
     WHERE autonumber_type = 'SalesOrderDetail' 

     SET @new_auto_number = @current_value + @number_of_lines 

     UPDATE dbo.autonumber_settings 
     SET autonumber_currentvalue = @new_auto_number 
     WHERE autonumber_type = 'SalesOrderDetail' 
END 
COMMIT TRAN 

任意のアイデア:ここではその手順の一部です。

+3

IDENTITYカラムを使用することを強くお勧めします。これは避けるように設計されています。 –

+0

'SELECT .../increase by one/UPDATE'サイクル全体が並行処理に対して安全ではありません。複数のプロセスが同じ開始値を取得し、1ずつ増加させてから新しい値を書き戻すことができます。 (b)SQL Server 2012が 'SEQUENCE'オブジェクトを取得するのを待つか、(c)単一の' UPDATE'に変更する必要があります。複数の呼び出し元によって複数回実行できない文。 –

+1

また、**なぜ@newvarchar(50) '変数として' @ currentvalue'を定義していますか?それは数値ではない?それが数字の場合 - 数値として宣言してください! –

答えて

0

これは競合状態または自律番号割り当てです。 2つの実行は、新しい値がデータベースに書き戻される前に同じ値を読み取る可能性があります。

これを解決する最善の方法は、ID列を使用して、SQLサーバーが自動番号割り当てを処理できるようにすることです。

sp_getapplockを使用して、autonumber_settingsへのアクセスをシリアル化することを禁止します。

+0

autonumber列の数値を常に考慮する数値は、本質的にその列をIDとして持つテーブルをリメイクして、現在の値でシードすることができますか?つまり、ストアドプロシージャのコードを変更する必要がありますか? – npeterson

+0

1つの表に複数のID列を持つことはできません。 procsが提示されるので、私はそれがあなたのために働くとは思わない。あなたはオートナンバーを使っているテーブルを見て、それらがIDカラムを持つことができるかどうかを調べなければならないでしょう。 – vickd

0

選択肢の繰り返し読み取りを使用できます。これは、行をロックし、値を更新してコミットするまで、他のプロシージャの選択をブロックします。

各選択に対してfrom句の後にWITH(REPEATABLEREAD、ROWLOCK)を挿入します。

+0

これは興味深いアイデアです。これを少し読んでみましょう。 – npeterson

関連する問題