Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo argomento descrive come creare una funzione definita dall'utente in SQL Server usando Transact-SQL.
Contenuto dell'articolo
Prima di iniziare:
Per creare una funzione definita dall'utente:
Prima di iniziare
Limitazioni e restrizioni
Le funzioni definite dall'utente non possono essere usate per eseguire azioni che modificano lo stato del database.
Le funzioni definite dall'utente non possono contenere una clausola OUTPUT INTO con una tabella come destinazione.
Le funzioni definite dall'utente non possono restituire più set di risultati. Si consiglia di utilizzare una stored procedure se è necessario restituire più set di risultati.
La gestione degli errori è limitata in una funzione definita dall'utente. Una funzione definita dall'utente non supporta TRY...CATCH, @ERROR o RAISERROR.
Le funzioni definite dall'utente non possono chiamare una procedura archiviata, ma possono chiamare una procedura archiviata estesa.
Le funzioni definite dall'utente non possono usare tabelle SQL o temporanee dinamiche. Le variabili di tabella sono consentite.
Le istruzioni SET non sono consentite in una funzione definita dall'utente.
La clausola FOR XML non è consentita
Le funzioni definite dall'utente possono essere annidate; ovvero una funzione definita dall'utente può chiamare un'altra. Il livello di annidamento viene incrementato all'avvio dell'esecuzione della funzione chiamata e decrementato al termine dell'esecuzione della funzione chiamata. Le funzioni definite dall'utente possono essere annidate fino a 32 livelli. Il superamento dei livelli massimi di annidamento causa l'esito negativo dell'intera catena di funzioni chiamanti. Qualsiasi riferimento al codice gestito da una funzione definita dall'utente Transact-SQL viene conteggiato come un livello rispetto al limite di annidamento di 32 livelli. I metodi richiamati da codice gestito non vengono inclusi nel conteggio per questo limite.
Non è possibile includere le istruzioni di Service Broker seguenti nella definizione di una funzione Transact-SQL definita dall'utente:
AVVIA CONVERSAZIONE DI DIALOGO
TERMINA CONVERSAZIONE
OTTIENI GRUPPO DI CONVERSAZIONE
sposta la conversazione
RICEVERE
INVIA
Sicurezza
Autorizzazioni
È richiesta l'autorizzazione CREATE FUNCTION nel database e l'autorizzazione ALTER per lo schema in cui viene creata la funzione. Se per la funzione viene specificato un tipo definito dall'utente, è necessario disporre dell'autorizzazione EXECUTE per tale tipo.
Funzioni scalari
Nell'esempio seguente viene creata una funzione scalare multistatement nel database AdventureWorks2012. La funzione accetta un valore di input, un ProductIDe restituisce un singolo valore di dati, la quantità aggregata del prodotto specificato nell'inventario.
IF OBJECT_ID (N'dbo.ufnGetInventoryStock', N'FN') IS NOT NULL
DROP FUNCTION ufnGetInventoryStock;
GO
CREATE FUNCTION dbo.ufnGetInventoryStock(@ProductID int)
RETURNS int
AS
-- Returns the stock level for the product.
BEGIN
DECLARE @ret int;
SELECT @ret = SUM(p.Quantity)
FROM Production.ProductInventory p
WHERE p.ProductID = @ProductID
AND p.LocationID = '6';
IF (@ret IS NULL)
SET @ret = 0;
RETURN @ret;
END;
GO
Nell'esempio seguente viene utilizzata la ufnGetInventoryStock funzione per restituire la quantità di inventario corrente per i prodotti con un ProductModelID valore compreso tra 75 e 80.
SELECT ProductModelID, Name, dbo.ufnGetInventoryStock(ProductID)AS CurrentSupply
FROM Production.Product
WHERE ProductModelID BETWEEN 75 and 80;
Funzioni Table-Valued
Nell'esempio seguente viene creata una funzione inline con valori di tabella nel database AdventureWorks2012. La funzione accetta un parametro di input, un ID cliente (store) e restituisce le colonne ProductID, Namee l'aggregazione delle vendite da inizio anno come YTD Total per ogni prodotto venduto al negozio.
IF OBJECT_ID (N'Sales.ufn_SalesByStore', N'IF') IS NOT NULL
DROP FUNCTION Sales.ufn_SalesByStore;
GO
CREATE FUNCTION Sales.ufn_SalesByStore (@storeid int)
RETURNS TABLE
AS
RETURN
(
SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS 'Total'
FROM Production.Product AS P
JOIN Sales.SalesOrderDetail AS SD ON SD.ProductID = P.ProductID
JOIN Sales.SalesOrderHeader AS SH ON SH.SalesOrderID = SD.SalesOrderID
JOIN Sales.Customer AS C ON SH.CustomerID = C.CustomerID
WHERE C.StoreID = @storeid
GROUP BY P.ProductID, P.Name
);
Nell'esempio seguente viene richiamata la funzione e viene specificato l'ID cliente 602.
SELECT * FROM Sales.ufn_SalesByStore (602);
Nell'esempio seguente viene creata una funzione con valori di tabella nel database AdventureWorks2012. La funzione accetta un singolo parametro di input, un EmployeeID e restituisce un elenco di tutti i dipendenti che segnalano direttamente o indirettamente al dipendente specificato. La funzione viene quindi richiamata specificando l'ID dipendente 109.
IF OBJECT_ID (N'dbo.ufn_FindReports', N'TF') IS NOT NULL
DROP FUNCTION dbo.ufn_FindReports;
GO
CREATE FUNCTION dbo.ufn_FindReports (@InEmpID INTEGER)
RETURNS @retFindReports TABLE
(
EmployeeID int primary key NOT NULL,
FirstName nvarchar(255) NOT NULL,
LastName nvarchar(255) NOT NULL,
JobTitle nvarchar(50) NOT NULL,
RecursionLevel int NOT NULL
)
--Returns a result set that lists all the employees who report to the
--specific employee directly or indirectly.*/
AS
BEGIN
WITH EMP_cte(EmployeeID, OrganizationNode, FirstName, LastName, JobTitle, RecursionLevel) -- CTE name and columns
AS (
SELECT e.BusinessEntityID, e.OrganizationNode, p.FirstName, p.LastName, e.JobTitle, 0 -- Get the initial list of Employees for Manager n
FROM HumanResources.Employee e
INNER JOIN Person.Person p
ON p.BusinessEntityID = e.BusinessEntityID
WHERE e.BusinessEntityID = @InEmpID
UNION ALL
SELECT e.BusinessEntityID, e.OrganizationNode, p.FirstName, p.LastName, e.JobTitle, RecursionLevel + 1 -- Join recursive member to anchor
FROM HumanResources.Employee e
INNER JOIN EMP_cte
ON e.OrganizationNode.GetAncestor(1) = EMP_cte.OrganizationNode
INNER JOIN Person.Person p
ON p.BusinessEntityID = e.BusinessEntityID
)
-- copy the required columns to the result of the function
INSERT @retFindReports
SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel
FROM EMP_cte
RETURN
END;
GO
-- Example invocation
SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel
FROM dbo.ufn_FindReports(1);
Vedere anche
Funzioni definite dall'utente
CREATE FUNCTION (Transact-SQL)