Quando si crea una funzione con valori di tabella (TVF) in SQL Server, è possibile renderla una funzione con valori di tabella in linea (ITVF) o una funzione con valori di tabella con istruzioni multiple (MSTVF). Esistono differenze tra questi tipi di funzione e di conseguenza utilizzano una sintassi diversa.
Questo articolo copre la differenza tra MSTVF e ITVF.
Le differenze
Ecco le principali differenze tra MSTVF e ITVF.
| ITVF | MSTVF | |
|---|---|---|
| La sintassi RETURNS | Dichiari semplicemente RETURNS TABLE e la definizione della tabella di ritorno sarà basata sul SELECT della funzione dichiarazione. Non è necessario specificare la struttura della tabella di ritorno. | Il tuo RETURNS la sintassi specifica in modo esplicito la struttura della tabella di ritorno. Questo viene fatto dichiarando una variabile TABLE che verrà utilizzata per archiviare e accumulare le righe restituite come valore della funzione. |
| La sintassi BEGIN/END | Gli ITVF non usano il BEGIN /END sintassi. | Gli MSTVF usano il BEGIN /END sintassi. |
| Prestazioni | Generalmente più veloce degli MTSVF. | Generalmente più lento degli ITVF. |
| Aggiornamenti dei dati | In alcuni casi è possibile aggiornare i dati nelle tabelle sottostanti utilizzando un ITFV. | Non è possibile aggiornare i dati nelle tabelle sottostanti utilizzando un MSTVF. |
Sintassi
Diamo un'occhiata alle differenze nella sintassi di ciascun tipo di funzione.
Funzione con valori di tabella in linea
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [ READONLY ] }
[ ,...n ]
]
)
RETURNS TABLE
[ WITH <function_option> [ ,...n ] ]
[ AS ]
RETURN [ ( ] select_stmt [ ) ]
[ ; ]
Funzione con valori di tabella a più istruzioni
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [READONLY] }
[ ,...n ]
]
)
RETURNS @return_variable TABLE <table_type_definition>
[ WITH <function_option> [ ,...n ] ]
[ AS ]
BEGIN
function_body
RETURN
END
[ ; ]
Si noti che MSTVF inizia con una definizione di tabella, ma ITVF non ha tale definizione.
Il MSTVF inizia con RETURNS @return_variable TABLE seguito dalla definizione della tabella. Qui, @return_variable è una variabile TABLE, utilizzata per memorizzare e accumulare le righe che devono essere restituite come valore della funzione.
Esempio 1 – Funzione inline con valori di tabella
Ecco un esempio di un semplice ITVF.
CREATE FUNCTION udf_PetsByName_ITVF( @PetName varchar(70))
RETURNS TABLE
AS
RETURN (
SELECT
CONCAT('Cat', ' ', CatId) AS PetId,
CatName
FROM dbo.Cats
WHERE CatName = @PetName
UNION ALL
SELECT
CONCAT('Dog', ' ', DogId) AS PetId,
DogName
FROM dbo.Dogs
WHERE DogName = @PetName
);
GO
Qui, seleziono da due tabelle usando UNION ALL e la funzione restituisce semplicemente il risultato.
Esempio 2 – Funzione con valori di tabella a più istruzioni
Ecco un esempio di utilizzo di un MSTVF per fare la stessa cosa, ma in un modo diverso.
CREATE FUNCTION udf_PetsByName_MSTVF( @PetName varchar(70))
RETURNS @pets TABLE (
PetId varchar(20),
PetName varchar(70)
)
AS
BEGIN
INSERT INTO @pets
SELECT
CONCAT('Cat', ' ', CatId),
CatName
FROM dbo.Cats
WHERE CatName = @PetName;
INSERT INTO @pets
SELECT
CONCAT('Dog', ' ', DogId),
DogName
FROM dbo.Dogs
WHERE DogName = @PetName;
RETURN;
END;
GO
La funzione inizia con la dichiarazione di una variabile TABLE chiamata @pets . In questo modo, specifichiamo esplicitamente la struttura della tabella di ritorno.
Le query all'interno di BEGIN /END blocco vengono salvati nella variabile TABLE chiamata @pets .
In questo caso, ho scelto di non utilizzare UNION ALL . Invece, ho eseguito le istruzioni separatamente e ho salvato i risultati di ciascuna in @pets variabile.
Esempio 3:aggiungere un'altra dichiarazione al MSTVF
Per dimostrare ulteriormente l'aspetto "multi-istruzione" degli MSTVF, possiamo aggiungere più istruzioni al MSTVF sopra e salvare i risultati nella stessa variabile di ritorno.
Esempio:
CREATE FUNCTION udf_PetsByName_MSTVF( @PetName varchar(70))
RETURNS @pets TABLE (
PetId varchar(20),
PetName varchar(70)
)
AS
BEGIN
INSERT INTO @pets
SELECT
CONCAT('Cat', ' ', CatId),
CatName
FROM dbo.Cats
WHERE CatName = @PetName;
INSERT INTO @pets
SELECT
CONCAT('Dog', ' ', DogId),
DogName
FROM dbo.Dogs
WHERE DogName = @PetName;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO @pets
VALUES (
'',
'There are no pets of that name.'
)
END
RETURN;
END;
GO
In questo caso ho aggiunto del codice per restituire un messaggio speciale ogni volta che la query non restituisce righe.