In questo articolo parleremo della nuova clausola WITH RESULT SETS che sarà possibile utilizzate con il comando EXECUTE (T-SQL) a partire dalla prossima versione di SQL Server, oggi in CTP1 con il Code-Name "Denali".
La nuova clausola WITH RESULT SETS, applicabile al comando EXECUTE, permette di ri-definire (cambiare) il nome e il tipo di dato per ogni colonna presente nel result set del comando EXECUTE (che ha invocato ad esempio una stored procedure).
Vediamo la nuova clausola WITH RESULT SETS in azione, negli esempi che abbiamo preparato, utilizzeremo la tabella dbo.Product creata nel database di sistema [tempdb]. La tabella dbo.Product è acceduta dalla stored procedure dbo.usp_get_product_for_sell() che restituisce in output la lista dei prodotti vendibili in determinato momento.
Il seguente frammento di codice T-SQL esegue la creazione della tabella dbo.Product (sul [tempdb]) e l’inserimento di alcuni prodotti di test commercializzati ad un’ipotetica azienda alimentare.
use [tempdb];
go
————————————————————————
— Setup table
————————————————————————
if OBJECT_ID(‘dbo.Product’, ‘U’) is not null
drop table dbo.Product;
go
create table dbo.Product
(
ProductID sysname not null primary key
,SellStartDate date not null
,SellEndDate date not null
,ProductNote varchar(40) null
,ListPrice decimal(8, 2) not null
,SafetyStockLevel integer not null
);
go
— Insert some test data
insert into dbo.Product
(ProductID, SellStartDate, SellEndDate, ProductNote, ListPrice, SafetyStockLevel)
values
(‘seattle crab’, ‘20101206’, ‘99991231’, ‘1 kg’, 16.2 , 4),
(‘king salmon’, ‘20101206’, ‘20111231’, ‘2 kg’, 11.5, 10),
(‘coffee’, ‘20101208’, ‘20110630’, null, 5.0, 80),
(‘blueberry scone’, ‘20101210’, ‘20110630’, ‘0.1 kg’, 1.30, 8),
(‘blueberry muffin’, ‘20101211’, ‘20110630’, ‘0.1 kg’, 1.40, 15);
go
Visualizziamo il contenuto della tabella dbo.Product per familiarizzare con i dati.
go
Figura 1 – Dati di test contenuti nella tabella dbo.Product
Definiamo ora la stored procedure dbo.usp_get_product_for_sell() utilizzata dagli operatori commerciali per conoscere i prodotti vendibili (dall’azienda) in un determinato momento. La stored procedure accetta in input due parametri: @vDate che rappresenta il giorno per il quale si desidera conoscere i prodotti vendibili e @vPrice che rappresenta il parametro di filtro sulla colonna ListPrice.
Il seguente frammento di codice T-SQL permette di creare la stored procedure dbo.usp_get_product_for_sell() nel database [tempdb]:
————————————————————————
— Setup stored procedure
————————————————————————
use [tempdb];
go
if OBJECT_ID(‘dbo.usp_get_product_for_sell’, ‘P’) is not null
drop procedure dbo.usp_get_product_for_sell;
go
create procedure dbo.usp_get_product_for_sell
(
@vDate as date
,@vPrice as decimal (8, 2) = 0
)
as
begin
/*
Name: dbo.usp_get_product_for_sell()
*/
if (isnull(@vDate, ”) = ”)
begin
print (‘Error dbo.usp_get_product_for_sell(): invalid value for parameter @vDate’);
return;
end;
— …
— …
select
ProductID
,ProductNote
,SellStartDate
,SellEndDate
from
dbo.Product
where
(@vDate between SellStartDate and SellEndDate);
— …
— …
if (ISNULL(@vPrice, 0) > 0)
begin
select
ProductID
,ListPrice
from
dbo.Product
where
(ListPrice <= @vPrice)
and (@vDate between SellStartDate and SellEndDate);
end;
end;
go
Eseguiamo ora la stored procedure dbo.usp_get_product_for_sell() per ottenere in output gli articoli vendibili in data 06/12/2010, utilizzeremo quindi il comando EXECUTE specificando la clausola WITH RESULT SETS per assegnare un nome ed un tipo (di dato) specifico ad ogni colonna presente nel result set.
exec dbo.usp_get_product_for_sell @vDate = ‘20101206’
with result sets
(
— First result sets
— Column name and data type
(
ProductName varchar(20)
,Note varchar(40)
,SellBy date
,SellEnd date
)
);
go
L’output ottenuto è illustrato in figura 2, osserviamo come le colonne del result set estratto all’interno della stored procedure siano state rinominate, come specificato nella clausola WITH RESULT SETS.
Figura 2 – EXECUTE statement con clausola WITH RESULT SETS
Oltre agli articoli vendibili a una certa data, nel prossimo esempio desideriamo ricevere in output un result set aggiuntivo che deve contenere, come nel caso del primo result set, gli articoli vendibili alla data passata (nel parametro @vDate), ma che hanno anche prezzo di listino minore o uguale a un determinato valore, passato alla stored procedure nel parametro @vPrice.
Nel seguente frammento di codice T-SQL illustriamo come sia possibile definire il nome delle colonne e il tipo, anche per il secondo result set (con la stessa logica mutuata per il primo).
— Multiple WITH RESULT SETS
exec dbo.usp_get_product_for_sell
@vDate = ‘20101208’
,@vPrice = 5
with result sets
(
— First result sets
— Column name and data type
(
ProductName varchar(20)
,Note varchar(40)
,SellBy date
,SellEnd date
),
— Second result sets
— Column name and data type, again
(
ProductName varchar(20)
,ListPrice decimal(8, 2)
)
);
go
L’output ottenuto è illustrato in figura 3.
Figura 3 – EXECUTE statement con clausola WITH RESULT SETS (multiplo)
Nel prossimo esempio vedremo come sia possibile definire, per un comando EXECUTE, un result set di tipo XML, da utilizzare in presenza di comandi SELECT che includono la clausola FOR XML. Per proseguire con l’esempio, sarà quindi necessario modificare la stored procedure dbo.usp_get_product_for_sell() per aggiungere la clausola FOR XML nel comando SELECT, di estrazione degli articoli vendibili ad una certa data, con prezzo di listino minore o uguale al valore specificato nel parametro @vPrice. Tale selezione è ora restituita nel secondo result set della stored procedure.
Il seguente frammento di codice T-SQL contiene il comando ALTER PROCEDURE con cui modifichiamo l’oggetto dbo.usp_get_product_for_sell() aggiungendo la clausola FOR XML come in precedenza descritto:
— WITH RESULT SETS as FOR XML
use [tempdb];
go
alter procedure dbo.usp_get_product_for_sell
(
@vDate as date
,@vPrice as decimal (8, 2) = 0
)
as
begin
/*
Name: dbo.usp_get_product_for_sell()
*/
if (isnull(@vDate, ”) = ”)
begin
print (‘Error dbo.usp_get_product_for_sell(): invalid value for parameter @vDate’);
return;
end;
— …
— …
select
ProductID
,ProductNote
,SellStartDate
,SellEndDate
from
dbo.Product
where
(@vDate between SellStartDate and SellEndDate);
— …
— …
if (ISNULL(@vPrice, 0) > 0)
begin
select
ProductID
,ListPrice
from
dbo.Product
where
(ListPrice <= @vPrice)
and (@vDate between SellStartDate and SellEndDate)
for xml path(‘root’);
end;
end;
go
Eseguiamo ora la nuova versione della stored procedure, prestando particolare attenzione alla definizione del secondo result set; nella clausola WITH RESULT SETS compare, infatti, l’opzione AS FOR XML:
exec dbo.usp_get_product_for_sell
@vDate = ‘20101208’
,@vPrice = 5
with result sets
(
— First result sets
— Column name and data type
(
ProductName varchar(20)
,Note varchar(40)
,SellBy date
,SellEnd date
),
— Second result sets
— as XML
as for xml
);
go
L’output è illustrato in figura 4:
Figura 4 – EXECUTE statement con clausola WITH RESULT SETS (multiplo) e opzione AS FOR XML
Conclusioni
In SQL Server “Denali”, la clausola WITH RESULT SETS permette di definire i metadati restituiti da uno statement EXECUTE.
Pulizia DB
————————————————————————
— Pulizia DB
————————————————————————
use [tempdb];
go
if OBJECT_ID(‘dbo.usp_get_product_for_sell’, ‘P’) is not null
drop procedure dbo.usp_get_product_for_sell;
go
if OBJECT_ID(‘dbo.Product’, ‘U’) is not null
drop table dbo.Product;
go