Sintomi
Quando si usano funzioni SCOPE_IDENTITY() o @@IDENTITYper recuperare i valori inseriti in una colonna Identity, è possibile notare che queste funzioni a volte restituiscono valori non corretti. Il problema si verifica solo quando le query usano piani di esecuzione paralleli. Per altre informazioni su come determinare se le query useranno piani di esecuzione parallela, vedere la sezione Parallelismo tra query nell'articolo tecnico seguente su Microsoft Downloads:
Causa
Microsoft ha confermato che questo problema si verifica con i prodotti elencati alla fine del presente articolo.
Risoluzione
Informazioni sull'aggiornamento cumulativo
SQL Server 2008 R2 Service Pack 1
La correzione per questo problema è stata rilasciata per la prima volta nell'aggiornamento cumulativo 5 per SQL Server 2008 R2 Service Pack 1. Per altre informazioni su come ottenere questo pacchetto di aggiornamento cumulativo, fare clic sul numero dell'articolo seguente per visualizzare l'articolo della Microsoft Knowledge Base:
2659694Pacchetto di aggiornamento cumulativo 5 per SQL Server 2008 R2 Service Pack 1
Nota Poiché le build sono cumulative, ogni nuova correzione contiene tutti gli aggiornamenti rapidi e tutte le correzioni di sicurezza incluse nella versione precedente di SQL Server 2008 R2. È consigliabile applicare la versione più recente delle correzioni che contiene questo aggiornamento rapido. Per ulteriori informazioni, fare clic sul numero dell'articolo seguente per visualizzare l'articolo nella Microsoft Knowledge Base:
2567616Le SQL Server 2008 R2 rilasciate dopo il rilascio SQL Server 2008 R2 Service Pack 1
Soluzione alternativa
Microsoft consiglia di non usare una di queste funzioni nelle query quando sono coinvolti piani paralleli in quanto non sempre affidabili. Usare invece la clausola OUTPUT dell'istruzione INSERT per recuperare il valore identity, come illustrato nell'esempio seguente.
Esempio di utilizzo della clausola OUTPUT:
DECLARE @MyNewIdentityValues tabella(myidvalues int)
dichiarare @A tabella (ID int chiave primaria)
inserisci in @A valori (1)
dichiarare @B tabella (ID int primary key identity(1;1), B int not Null)
inserire in @B valori (1)
selezionare
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY()
impostare il profilo delle statistiche
inserire in _ddr_T
output inserted.ID in @MyNewIdentityValues
selezionare
b.ID
da @A a
left join @B b on b.ID = 1
left join @B b2 on b2. B = -1
left join _ddr_T t on t.T = -1
where not exists (select * from _ddr_T t2 where t2.ID = -1)
impostare il profilo delle statistiche disattivato
selezionare
[RowCount] = @@RowCount,
[@@IDENTITY] = @@IDENTITY,
[SCOPE_IDENTITY] = SCOPE_IDENTITY(),
[IDENT_CURRENT] = IDENT_CURRENT('_ddr_T')
selezionare * da @MyNewIdentityValues
vai
Se la situazione richiede l'uso di una di queste funzioni, è possibile usare uno dei metodi seguenti per risolvere il problema.
Metodo 1:
Includere l'opzione seguente nella query
OPZIONE (MAXDOP 1)
Nota:questa operazione può danneggiare le prestazioni della parte SELECT della query.
Metodo 2:
Leggere il valore della parte SELECT in un set di variabili (o una singola variabile di tabella) e quindi inserirlo nella tabella di destinazione con MAXDOP=1. Poiché il piano INSERT non sarà parallelo, si otterrà la semantica giusta, ma il piano SELECT sarà parallelo per ottenere le prestazioni desiderate.
Metodo 3:
Eseguire l'istruzione seguente per impostare l'opzione max degree of parallelism su 1:
sp_configure 'massimo grado di parallelismo', 1
vai
riconfigurare con override
vai
Nota:questo metodo può causare una riduzione delle prestazioni nel server. Non è consigliabile usare questo metodo a meno che non sia stato valutato in un ambiente di testing o gestione temporanea.