Clausola di output di SQL Server in una variabile scalare


134

C'è un modo "semplice" per farlo o devo passare da una variabile di tabella con la sintassi "OUTPUT ... INTO"?

DECLARE @someInt int

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

Risposte:


161

Hai bisogno di una variabile di tabella e può essere così semplice.

declare @ID table (ID int)

insert into MyTable2(ID)
output inserted.ID into @ID
values (1)

45
Ma poi dovrei "SELEZIONARE @someInt = ID FROM @ID". Volevo sapere se è possibile saltare quel passaggio aggiuntivo (e la variabile della tabella intermedia) se tutto ciò di cui ho bisogno è l'int risultante.
Benoittr,

@Benoittr - Dipende da come si utilizzerà il valore, potrebbe non essere necessario, è possibile utilizzare la tabella in una clausola from di un'istruzione select. Quando assegni una variabile devi anche essere sicuro che l'inserto abbia inserito solo una riga. E se l'inserto ha inserito solo una riga, forse è più facile ottenere ciò che viene utilizzato direttamente nella clausola dei valori invece di usarlo output?
Mikael Eriksson,

4
Nel caso del valore generato automaticamente non è sempre possibile conoscere i valori in anticipo (identità, colonne calcolate). Capisco che ci sono molte soluzioni alternative. Tuttavia, mi hai dato la risposta che stavo cercando. Grazie
Benoittr,

Ne hai bisogno in una variabile normale? 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

Più di un anno dopo ... se ciò di cui hai bisogno è ottenere l'id generato automaticamente di una tabella, puoi semplicemente

SELECT @ReportOptionId = SCOPE_IDENTITY()

Altrimenti, sembra che tu sia bloccato con l'uso di una tabella.


6
La variabile che stavo cercando era davvero qualcos'altro che la colonna identità. Comunque, grazie per la risposta.
Benoittr,

26
Apparentemente questo ha dei problemi in un piano parallelo multiprocessore e OUTPUT è l'unico metodo sempre affidabile.
Andrew

6
SCOPE_IDENTITY () potrebbe restituire qualcosa anche se l' ultimo INSERT non ha inserito nulla, giusto? Ciò lo renderebbe inutilizzabile in alcuni casi.
Patrick Honorez,

2
meglio usare la clausola di output
Clay Smith

1
Il bug a cui fa riferimento @andrewb è stato corretto in 2008 R2 SP1 .
adam0101,

6

Molto più avanti, ma vale la pena ricordare che è anche possibile utilizzare le variabili per generare valori nella clausola SET di un UPDATE o nei campi di un 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

Nell'esempio sopra @ val1 ha il valore precedente e @ val2 ha il valore dopo anche se sospetto che eventuali modifiche da un trigger non siano in val2, quindi in questo caso dovresti andare con la tabella di output. Per tutto tranne che nel caso più semplice, penso che la tabella di output sia più leggibile anche nel tuo codice.

Un posto molto utile è se si desidera trasformare una colonna in un elenco separato da virgole;

DECLARE @list varchar(max) = '';
DECLARE @comma varchar(2) = '';
SELECT @list = @list + @comma + County, @comma = ', ' FROM County
print @list

Grazie! Questa era l'informazione di cui avevo bisogno
Wizou,

1
WOW! Non sapevo che tu potessi fare SET @val2 = NextNum = NextNum + 1.
Sam,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.