Duplicazione Identificativo

martedì 21 ottobre 2008 - 15.51

4mane Profilo | Junior Member

Salve a tutti.
Ho un problema al quale davvero non so dare una soluzione. Di per sè lo scenario è molto semplice, e premetto che ho girato nel forum e web per trovare qualche soluzione, ma poiché sto nel panico, probabilmente mi sarà sfuggita.
In ogni modo eccomi al dunque.
Base dati: SQL 2005
Ho una tabella CodiciCom che contiene 3 campi: Codice int, Tipo nvarchar(20), Anno smallint.
Ho una stored procedure che qui vi posto che ritorna il nuovo numero di codice per l'anno corrente:
USE [Utenza] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[ADD_CodiciCom] ( @tipo nvarchar(20), @NumeroFinale int output, @Anno int output ) AS DECLARE @SelectTipo int DECLARE @Numero int SET @anno = Year(GetDate()) Begin Transaction NuovoCodiceCom; IF NOT EXISTS (SELECT Numero FROM CodiciCom Where Tipo = @tipo and Anno = @anno) begin SET @NumeroFinale = 1 INSERT INTO [dbo].[CodiciCom] ( [Anno] , [Tipo] , [Numero] ) VALUES ( @Anno, @Tipo, @NumeroFinale ) end ELSE begin SELECT @Numero = Numero FROM CodiciCom Where tipo = @tipo and Anno = @anno SET @NumeroFinale = @Numero + 1 UPDATE CodiciCom SET Numero = @NumeroFinale Where tipo = @tipo and Anno = @anno end commit transaction NuovoCodiceCom; return @NumeroFinale;

Il problema è che se questa viene chiamata in contemporanea da più utenti, nonostante sia presente una transaction, viene eseguita in contemporanea, con il risultato che più utenti ricevono il medesimo nuovo codice.
Potete aiutarmi?
Grazie a tutti come al solito per la vs. collaborazione


P.S.: ...l'avevo detto io che era meglio che facevo l'USCIIERE ;)

lbenaglia Profilo | Guru

>Il problema è che se questa viene chiamata in contemporanea da
>più utenti, nonostante sia presente una transaction, viene eseguita
>in contemporanea, con il risultato che più utenti ricevono il
>medesimo nuovo codice.
>Potete aiutarmi?

Ciao Mauro,

Prova a vedere se con questa procedura la situazione migliora:

USE tempdb; CREATE TABLE dbo.CodiciCom( Anno smallint NOT NULL, Tipo varchar(10) NOT NULL, Numero int NOT NULL ); GO CREATE PROCEDURE dbo.up_AddCodiciCom( @Tipo varchar(20), @NumeroFinale int output, @Anno smallint output ) AS SET @Anno = YEAR(CURRENT_TIMESTAMP); SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN TRY BEGIN TRAN; UPDATE dbo.CodiciCom SET @NumeroFinale = Numero = Numero + 1 WHERE Tipo = @Tipo AND Anno = @Anno; IF @@ROWCOUNT = 0 BEGIN SET @NumeroFinale = 1 INSERT dbo.CodiciCom VALUES (@Anno, @Tipo, @NumeroFinale); END COMMIT TRAN; END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; ROLLBACK TRAN; SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); RAISERROR (@ErrorMessage, -- Message text. @ErrorSeverity, -- Severity. @ErrorState -- State. ); END CATCH; GO DECLARE @Numero int, @Anno smallint; EXEC dbo.up_AddCodiciCom 'Tipo 1', @Numero OUTPUT, @Anno OUTPUT; SELECT @Numero AS Numero, @Anno AS Anno; EXEC dbo.up_AddCodiciCom 'Tipo 1', @Numero OUTPUT, @Anno OUTPUT; SELECT @Numero AS Numero, @Anno AS Anno; EXEC dbo.up_AddCodiciCom 'Tipo 1', @Numero OUTPUT, @Anno OUTPUT; SELECT @Numero AS Numero, @Anno AS Anno; EXEC dbo.up_AddCodiciCom 'Tipo 2', @Numero OUTPUT, @Anno OUTPUT; SELECT @Numero AS Numero, @Anno AS Anno; EXEC dbo.up_AddCodiciCom 'Tipo 2', @Numero OUTPUT, @Anno OUTPUT; SELECT @Numero AS Numero, @Anno AS Anno; /* Output: (0 row(s) affected) (1 row(s) affected) Numero Anno ----------- ------ 1 2008 (1 row(s) affected) (1 row(s) affected) Numero Anno ----------- ------ 2 2008 (1 row(s) affected) (1 row(s) affected) Numero Anno ----------- ------ 3 2008 (1 row(s) affected) (0 row(s) affected) (1 row(s) affected) Numero Anno ----------- ------ 1 2008 (1 row(s) affected) (1 row(s) affected) Numero Anno ----------- ------ 2 2008 (1 row(s) affected) */ SELECT * FROM dbo.CodiciCom; /* Output: Anno Tipo Numero ------ ---------- ----------- 2008 Tipo 1 3 2008 Tipo 2 2 (2 row(s) affected) */ DROP PROCEDURE dbo.up_AddCodiciCom; DROP TABLE dbo.CodiciCom;

>Grazie a tutti come al solito per la vs. collaborazione
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

4mane Profilo | Junior Member

Grazie Lorenzo!
Grande
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5