Qual é a melhor maneira de obter IDENTITY
da linha inserida?
Eu sei sobre @@IDENTITY
e IDENT_CURRENT
e SCOPE_IDENTITY
mas não entendo os prós e contras ligados a cada um.
Alguém pode explicar as diferenças e quando devo usá-las?
sql
sql-server
tsql
Oded
fonte
fonte
INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...)
, ou método mais antigo:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
você pode obtê-lo em c # usando ExecuteScalar ().OUTPUT
cláusula no SQL Server.Respostas:
@@IDENTITY
retorna o último valor de identidade gerado para qualquer tabela na sessão atual, em todos os escopos. Você precisa ter cuidado aqui , já que é através de escopos. Você pode obter um valor de um gatilho, em vez de sua declaração atual.SCOPE_IDENTITY()
retorna o último valor de identidade gerado para qualquer tabela na sessão atual e o escopo atual. Geralmente o que você deseja usar .IDENT_CURRENT('tableName')
retorna o último valor de identidade gerado para uma tabela específica em qualquer sessão e qualquer escopo. Isso permite especificar de qual tabela você deseja obter o valor, caso as duas acima não sejam exatamente o que você precisa ( muito raro ). Além disso, como @ Guy Starbuck mencionou, "Você pode usar isso se quiser obter o valor atual de IDENTITY para uma tabela na qual você não inseriu um registro".A
OUTPUT
cláusula daINSERT
instrução permitirá acessar todas as linhas que foram inseridas por meio dessa instrução. Como o escopo da declaração específica é mais direto do que as outras funções acima. No entanto, é um pouco mais detalhado (você precisará inserir em uma variável de tabela / tabela temporária e depois consultá-la) e fornece resultados mesmo em um cenário de erro em que a instrução é revertida. Dito isto, se sua consulta usar um plano de execução paralelo, este é o único método garantido para obter a identidade (exceto para desativar o paralelismo). No entanto, é executado antes dos acionadores e não pode ser usado para retornar valores gerados pelo acionador.fonte
output
você, você não precisa criar uma tabela temporária para armazenar e consultar os resultados. Apenas deixe de fora ainto
parte da cláusula de saída e ela será exibida em um conjunto de resultados.OUTPUT
é a "melhor", desde que você não esteja usando gatilhos e esteja lidando com erros, masSCOPE_IDENTITY
seja o mais simples e muito raramente tenha problemasAcredito que o método mais seguro e preciso de recuperar o ID inserido seria usar a cláusula de saída.
por exemplo (extraído do seguinte artigo do MSDN )
fonte
OUTPUT
no SQL Server 2005 , de modo que parece que é apenas SQL Server 2000 e anteriores que estão sem eleEstou dizendo a mesma coisa que os outros caras, então todo mundo está correto, só estou tentando deixar mais claro.
@@IDENTITY
retorna o ID da última coisa que foi inserida pela conexão do seu cliente com o banco de dados.Na maioria das vezes, isso funciona bem, mas às vezes um gatilho insere uma nova linha que você não conhece e você obtém o ID dessa nova linha, em vez da que deseja
SCOPE_IDENTITY()
resolve esse problema. Retorna o ID da última coisa que você inseriu no código SQL enviado ao banco de dados. Se os gatilhos criarem linhas extras, eles não farão com que o valor errado seja retornado. HoorayIDENT_CURRENT
retorna o último ID que foi inserido por qualquer pessoa. Se algum outro aplicativo inserir outra linha em um momento impreciso, você obterá o ID dessa linha em vez da sua.Se você quiser jogar pelo seguro, use sempre
SCOPE_IDENTITY()
. Se você continuar@@IDENTITY
e alguém decidir adicionar um gatilho mais tarde, todo o seu código será interrompido.fonte
A melhor (leia-se: mais segura) maneira de obter a identidade de uma linha recém-inserida é usando a
output
cláusula:fonte
scope_identity()
) obtenham planos paralelos de qualquer maneira. E esse bug foi corrigido mais de um ano antes desta resposta.output
vez descope_identity()
. Eu removi o FUD sobre o agrupamento na resposta.Adicionar
até o final de sua instrução sql de inserção,
irá recuperá-lo.
fonte
Quando você usa o Entity Framework, ele usa internamente a
OUTPUT
técnica para retornar o valor de ID recém-inseridoOs resultados da saída são armazenados em uma variável de tabela temporária, unidos de volta à tabela e retornam o valor da linha da tabela.
Nota: Não tenho idéia de por que a EF uniria a tabela efêmera de volta à tabela real (em que circunstâncias as duas não coincidiriam).
Mas é isso que a EF faz.
Essa técnica (
OUTPUT
) está disponível apenas no SQL Server 2008 ou mais recente.Editar - O motivo da associação
O motivo pelo qual o Entity Framework se une novamente à tabela original, em vez de simplesmente usar os
OUTPUT
valores, é porque o EF também usa essa técnica para obter o valorrowversion
linha recém-inserida.Você pode usar simultaneidade otimista em seus modelos de estrutura de entidade por usando o
Timestamp
atributo: 🕗Ao fazer isso, o Entity Framework precisará
rowversion
da linha recém-inserida:E para recuperar isso,
Timetsamp
você não pode usar umOUTPUT
cláusula.Isso porque se houver um gatilho na mesa, qualquer
Timestamp
OUTPUT que você estiver errado estará errado:O registro de data e hora retornado nunca estará correto se você tiver um gatilho na mesa. Então você deve usar um separado
SELECT
.E mesmo se você estava disposto a sofrer a conversão de linha incorreta, o outro motivo para realizar uma separação separada
SELECT
é que você não pode OUTPUT arowversion
em uma variável de tabela:A terceira razão para fazê-lo é por simetria. Ao executar uma
UPDATE
tabela com um gatilho, você não pode usar umaOUTPUT
cláusula. Tentando fazerUPDATE
com umOUTPUT
não é suportado e dará um erro:A única maneira de fazer isso é com uma
SELECT
declaração de acompanhamento :fonte
TurboEncabulators
:)MSDN
fonte
@@ IDENTITY é a última identidade inserida usando a conexão SQL atual. Esse é um bom valor para retornar de um procedimento armazenado de inserção, onde você só precisa da identidade inserida para o seu novo registro e não se importa se mais linhas foram adicionadas posteriormente.
SCOPE_IDENTITY é a última identidade inserida usando a Conexão SQL atual e, no escopo atual - ou seja, se houvesse uma segunda IDENTITY inserida com base em um gatilho após a inserção, ela não seria refletida em SCOPE_IDENTITY, apenas a inserção que você executou . Francamente, nunca tive um motivo para usar isso.
IDENT_CURRENT (nome da tabela) é a última identidade inserida, independentemente da conexão ou escopo. Você pode usar isso se desejar obter o valor atual de IDENTITY para uma tabela na qual você não inseriu um registro.
fonte
Não posso falar com outras versões do SQL Server, mas em 2012, a saída diretamente funciona muito bem. Você não precisa se preocupar com uma mesa temporária.
A propósito, essa técnica também funciona ao inserir várias linhas.
Resultado
fonte
OUTPUT
. Se você não precisa da tabela temporária, sua consulta acaba sendo muito mais simples.SEMPRE use scope_identity (), NUNCA há necessidade de mais nada.
fonte
Crie um
uuid
e também insira-o em uma coluna. Então você pode identificar facilmente sua linha com o uuid. Essa é a única solução 100% funcional que você pode implementar. Todas as outras soluções são muito complicadas ou não estão funcionando nos mesmos casos extremos. Por exemplo:1) Criar linha
2) Criar linha
fonte
uuid
no banco de dados. Portanto, a linha será encontrada mais rapidamente.https://www.npmjs.com/package/uuid
.const uuidv4 = require('uuid/v4'); const uuid = uuidv4()
Uma outra maneira de garantir a identidade das linhas inseridas é especificar os valores da identidade e usar the
SET IDENTITY_INSERT ON
e thenOFF
. Isso garante que você saiba exatamente quais são os valores de identidade! Desde que os valores não estejam em uso, você poderá inserir esses valores na coluna de identidade.Essa pode ser uma técnica muito útil se você estiver carregando dados de outra fonte ou mesclando dados de dois bancos de dados etc.
fonte
Mesmo sendo um segmento mais antigo, existe uma maneira mais recente de fazer isso, que evita algumas das armadilhas da coluna IDENTITY em versões mais antigas do SQL Server, como falhas nos valores de identidade após a reinicialização do servidor . As seqüências estão disponíveis no SQL Server 2016 e, a seguir, a maneira mais nova é criar um objeto SEQUENCE usando TSQL. Isso permite que você crie seu próprio objeto de sequência numérica no SQL Server e controle como ele é incrementado.
Aqui está um exemplo:
Em TSQL, você faria o seguinte para obter o próximo ID de sequência:
Aqui estão os links para CREATE SEQUENCE e NEXT VALUE FOR
fonte
Após a inserção da instrução, você precisará adicionar isso. Verifique se o nome da tabela em que os dados estão sendo inseridos. Você não obterá a linha atual no lugar onde a linha foi afetada agora pela sua instrução de inserção.
fonte