Sintomas
Quando você usa funções SCOPE_IDENTITY() ou @@IDENTITYpara recuperar os valores inseridos em uma coluna de identidade, você pode notar que essas funções às vezes retornam valores incorretos. O problema ocorre somente quando suas consultas usam planos de execução paralelas. Para obter mais informações sobre como determinar se suas consultas usarão planos de execução paralelas, consulte a seção Paralelismo Intra-query no artigo técnico a seguir sobre Downloads da Microsoft:
Causa
A Microsoft confirmou que esse é um problema que ocorre nos produtos Microsoft listados no início deste artigo.
Resolução
Informações sobre a atualização cumulativa
SQL Server 2008 R2 Service Pack 1
A correção desse problema foi lançada pela primeira vez na Atualização Cumulativa 5 para SQL Server 2008 R2 Service Pack 1. Para obter mais informações sobre como obter esse pacote de atualização cumulativa, clique no seguinte número de artigo para exibir o artigo na Base de Dados de Conhecimento da Microsoft:
2659694Pacote de Atualização Cumulativa 5 para SQL Server 2008 R2 Service Pack 1
Observação Como as builds são cumulativas, cada nova versão de correção contém todos os hotfixes e todas as correções de segurança que foram incluídas na versão de correção do SQL Server 2008 R2 anterior. Recomendamos que você considere aplicar a versão de correção mais recente que contém esse hotfix. Para obter mais informações, clique no número abaixo para ler os artigos na Base de Dados de Conhecimento Microsoft:
2567616As SQL Server 2008 R2 que foram lançadas após SQL Server 2008 R2 Service Pack 1 foi lançado
Solução alternativa
A Microsoft recomenda que você não use nenhuma dessas funções em suas consultas quando os planos paralelos estão envolvidos, pois nem sempre são confiáveis. Em vez disso, use a cláusula OUTPUT da instrução INSERT para recuperar o valor de identidade, conforme mostrado no exemplo abaixo.
Exemplo de uso da cláusula OUTPUT:
DECLARE @MyNewIdentityValues table(myidvalues int) declare @A tabela (ID int primary key) inserir em @A valores (1) declare @B tabela (ID int primary key identity(1,1), B int not null) inserir em @B valores (1) select [RowCount] = @@RowCount, [@@IDENTITY] = @@IDENTITY, [SCOPE_IDENTITY] = SCOPE_IDENTITY() definir o perfil de estatísticas em inserir no _ddr_T saída inserted.ID em @MyNewIdentityValues select b.ID de @A um 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 onde não existe (selecione * de _ddr_T t2 onde t2.ID = -1) definir o perfil de estatísticas desligado select [RowCount] = @@RowCount, [@@IDENTITY] = @@IDENTITY, [SCOPE_IDENTITY] = SCOPE_IDENTITY(), [IDENT_CURRENT] = IDENT_CURRENT('_ddr_T') select * from @MyNewIdentityValues go
Se a sua situação exigir que você precise usar uma dessas funções, você poderá usar um dos seguintes métodos para contornar o problema.
Método 1:
Inclua a seguinte opção em sua consulta
OPÇÃO (MAXDOP 1)
Observação: isso pode prejudicar o desempenho da parte SELECT da consulta.
Método 2:
Leia o valor da parte SELECT em um conjunto de variáveis (ou uma única variável de tabela) e insira na tabela de destino com MAXDOP=1. Como o plano INSERT não será paralelo, você obterá a semântica correta, mas seu SELECT será paralelo para atingir o desempenho desejado.
Método 3:
Execute a seguinte instrução para definir o grau máximo da opção de paralelismo como 1:
sp_configure "grau máximo de paralelismo", 1
go
reconfigurar com substituição
go
Observação: esse método pode causar degradação de desempenho no servidor. Você não deve usar esse método, a menos que o tenha avaliado em um ambiente de teste ou preparação.