Cláusula de Saída do SQL Server em uma variável escalar

134

Existe alguma maneira "simples" de fazer isso ou eu preciso passar por uma variável de tabela com a sintaxe "OUTPUT ... INTO"?

DECLARE @someInt int

INSERT INTO MyTable2(AIntColumn)
OUTPUT @SomeInt = Inserted.AIntColumn
VALUES(12)
Benoittr
fonte

Respostas:

161

Você precisa de uma variável de tabela e pode ser assim tão simples.

declare @ID table (ID int)

insert into MyTable2(ID)
output inserted.ID into @ID
values (1)
Mikael Eriksson
fonte
45
Mas então eu teria que "SELECT @someInt = ID FROM @ID". Eu queria saber se é possível pular essa etapa extra (e variável de tabela intermediária) se tudo o que preciso é do int resultante.
Benoittr 5/04
@Benoittr - Depende de como você usará o valor, pode não ser necessário, você pode usar a tabela na cláusula from de uma instrução select. Ao atribuir uma variável, você também precisa ter certeza de que a inserção inseriu apenas uma linha. E se a inserção inseriu apenas uma linha, talvez seja mais fácil entender o que é usado diretamente na cláusula values, em vez de usar output?
Mikael Eriksson
4
No caso de valor gerado automaticamente, nem sempre é possível conhecer os valores antes do tempo (identidade, colunas computadas). Entendo que existem muitas soluções alternativas. Ainda assim, você me deu a resposta que estava procurando. Obrigado
Benoittr 06/04
Precisa de uma variável regular? DECLARE @InsertedIDResults TABLE (ID int); INSERT INTO MyTable (Name, Age) OUTPUT INSERTED.ID INTO @InsertedIDResults VALUES('My Name', 30); DECLARE @InsertedID int = (SELECT TOP 1 ID FROM @InsertedIDResults);
Arvo Bowen
30

Mais de um ano depois ... se o que você precisa é obter o ID gerado automaticamente de uma tabela, basta

SELECT @ReportOptionId = SCOPE_IDENTITY()

Caso contrário, parece que você está preso ao usar uma tabela.

Alejandro B.
fonte
6
A variável que eu estava procurando realmente era outra coisa que a coluna de identidade. Ainda assim, obrigado pela resposta.
Benoittr
26
Aparentemente, isso tem problemas em um plano paralelo de multiprocessador e OUTPUT é o único método sempre confiável.
andrewb
6
SCOPE_IDENTITY () pode retornar algo mesmo que o último INSERT não tenha inserido nada, certo? Isso tornaria inutilizável em alguns casos.
Patrick Honorez 28/01
2
melhor usar a cláusula de saída
Clay Smith
1
O bug que @andrewb refere é corrigido no 2008 R2 SP1 .
adam0101 21/04
6

Muito mais tarde, mas ainda vale a pena mencionar, você também pode usar variáveis ​​para gerar valores na cláusula SET de um UPDATE ou nos campos de um SELECT;

DECLARE @val1 int;
DECLARE @val2 int;
UPDATE [dbo].[PortalCounters_TEST]
SET @val1 = NextNum, @val2 = NextNum = NextNum + 1
WHERE [Condition] = 'unique value'
SELECT @val1, @val2

No exemplo acima, @ val1 tem o valor antes e @ val2 tem o valor depois, embora eu suspeite que alguma alteração de um gatilho não esteja no val2, portanto, você teria que ir com a tabela de saída nesse caso. Para qualquer coisa, menos o caso mais simples, acho que a tabela de saída também será mais legível no seu código.

Um lugar em que isso é muito útil é se você deseja transformar uma coluna em uma lista separada por vírgula;

DECLARE @list varchar(max) = '';
DECLARE @comma varchar(2) = '';
SELECT @list = @list + @comma + County, @comma = ', ' FROM County
print @list
Jay13
fonte
Obrigado! Esta foi a informação que eu precisava
Wizou
1
UAU! Eu não sabia que você pode fazer SET @val2 = NextNum = NextNum + 1.
Sam