Sql Server 2005 introduce molte interessanti novità e migliorie nel linguaggio Transact-SQL. Tra queste la parola chiave OUTPUT o OUTPUT...INTO, la quale permette di restituire i valori di database aggiornati a seguito di operazioni di INSERT, UPDATE e DELETE. Questa funzionalità può essere d'aiuto al DBA (o se preferite DBD - DataBase Developer) in diversi situazioni, per esempio, il recupero del valore dei campi di tipo identity e di quelli calcolati. Vediamo degli esempi che adoperano una tabella [Books] che presenta un campo identity [BookID] e un campo calcolato [ProjectedSales].
/* Transact-SQL 2005 */ CREATE SCHEMA OutputSample AUTHORIZATION dbo CREATE TABLE Books ( BookID int IDENTITY, Title nvarchar(50) NOT NULL, Published datetime NOT NULL, CurrentSales money NOT NULL, ProjectedSales AS CurrentSales * 0.01 * DATEDIFF (day, Published, GetDate()), ModifiedBy sysname DEFAULT suser_name() NOT NULL ) GO Inseriremo un record utilizzando la parola chiave OUTPUT allo scopo di restituire al client il valore del campo identity [BookID], del campo calcolato [ProjectedSales] e di quello valorizzato dal default [ModifiedBy]. Per fare ciò, OUTPUT sfrutta le tabelle virtuali Inserted e Deleted, le stesse esposte nei Trigger: la tabella virtuale Inserted contiene i valori delle righe inserite mediante UPDATE o i nuovi valori delle righe aggiornate mediante UPDATE, mentre la Deleted contiene i valori delle righe cancellate mediante DELETE o i vecchi valori delle righe aggiornate mediante UPDATE.
/* Transact-SQL 2005 */ INSERT INTO OutputSample.Books (Title, Published, CurrentSales) OUTPUT inserted.BookID, inserted.ProjectedSales, inserted.ModifiedBy VALUES ('Inside Sql Server 2005', '01-04-2006', 100) GO Otterremo il risultato seguente:
BookID ProjectedSales ModifiedBy ----------- --------------------------------------- --------------- 1 49.000000 XPLAYN\FRANCESCO
(Righe interessate: 1)
Per la verità, già in Sql Server 2000 si disponeva di tre diversi metodi che garantivano un efficace recupero dell'ultimo valore Identity generato all'interno della sessione utente (mediante @@IDENTITY), all'interno dello scope corrente - stored procedure, user function, batch - (mediante SCOPE_IDENTITY()) e, infine, in una qualsiasi tabella del database indipendentemente da sessione e scope (mediante IDENT_CURRENT). In più rispetto a tali metodi, la OUTUPT keyword ci permette di ricavare tutti i valori identity generati in un'inserimento di massa. Ad esempio, supponiamo di voler popolare la tabella [Books] a partire da un'altra tabella chiamata [SourceBooks] che andiamo di seguito a creare e popolare:
/* Transact-SQL 2005 */ CREATE TABLE OutputSample.SourceBooks ( Title nvarchar(50) NOT NULL, Published datetime NOT NULL, CurrentSales money NOT NULL ) GO INSERT INTO OutputSample.SourceBooks VALUES ('Transact-SQL in Sql Server 2005', '10-02-2006', 500) INSERT INTO OutputSample.SourceBooks VALUES ('Algoritmi e Strutture Dati', '20-01-2005', 1200) INSERT INTO OutputSample.SourceBooks VALUES ('Basi di dati 2a Ed.', '01-01-2006', 1500) GO Quando popoliamo [Books] a partire da [SourceBooks] mediante la classica istruzione "INSERT INTO ... SELECT" utilizzando OUTPUT:
/* Transact-SQL 2005 */ INSERT INTO OutputSample.Books (Title, Published, CurrentSales) OUTPUT inserted.BookID, inserted.ProjectedSales, inserted.ModifiedBy SELECT Title, Published, CurrentSales FROM OutputSample.SourceBooks GO otteniamo come risultato: BookID ProjectedSales ModifiedBy ----------- --------------------------------------- ----------------- 1 495.000000 XPLAYN\FRANCESCO 2 5820.000000 XPLAYN\FRANCESCO 3 2085.000000 XPLAYN\FRANCESCO
(Righe interessate: 3)
I valori restituiti dalla OUTPUT keyword possono anche essere registrati in una variabile di tipo tabella oppure una tabella vera e propria. Per fare ciò basterà aggiungere la parola INTO seguita dalla tabella destinazione.
/* Transact-SQL 2005 */ DECLARE @BooksLog TABLE ( BookID int, Title nvarchar(50) NOT NULL, ModifiedBy sysname ) INSERT INTO OutputSample.Books (Title, Published, CurrentSales) OUTPUT inserted.BookID, inserted.ProjectedSales, inserted.ModifiedBy INTO @BooksLog VALUES ('.NET Inside', '01-10-2005', 100) SELECT * FROM @BooksLog GO E' facile immaginare un'utilizzo di questa funzionalità in ambito di logging delle operazioni (di cui è possibile vedere una soluzione per Sql Server 2000 nel mio articolo "Log delle transazioni mediante trigger").
|