函数类型
SQL Server 2008 支持用户定义函数和内置系统函数。
标量函数
用户定义标量函数返回在 RETURNS 子句中定义的类型的单个数据值。对于内联标量函数,没有函数体;标量值是单个语句的结果。对于多语句标量函数,定义在 BEGIN...END 块中的函数体包含一系列返回单个值的 Transact-SQL 语句。返回类型可以是除 text、ntext、image、cursor 和 timestamp 外的任何数据类型。
以下示例创建了一个多语句标量函数。此函数输入一个值 ProductID,而返回一个单个数据值(指定库存产品的聚合量)。
USE AdventureWorks2008R2;
GO
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
下例使用 ufnGetInventoryStock 函数返回 ProductModelID 为 75 到 80 之间的产品的当前库存量。
USE AdventureWorks2008R2;
GO
SELECT ProductModelID, Name, dbo.ufnGetInventoryStock(ProductID)AS CurrentSupply
FROM Production.Product
WHERE ProductModelID BETWEEN 75 and 80;
GO
表值函数
用户定义表值函数返回 table 数据类型。对于内联表值函数,没有函数主体;表是单个 SELECT 语句的结果集。
以下示例创建了一个内联表值函数。此函数的输入参数为客户(商店)ID,而返回 ProductID、Name 以及 YTD Total(销售到商店的每种产品的本年度节截止到现在的销售总额)列。
USE AdventureWorks2008R2;
GO
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
);
GO
以下示例调用此函数并指定客户 ID 为 602。
SELECT * FROM Sales.ufn_SalesByStore (602);
对于多语句表值函数,在 BEGIN...END 语句块中定义的函数体包含一系列 Transact-SQL 语句,这些语句可生成行并将其插入将返回的表中。
以下示例创建了一个表值函数。此函数具有一个输入参数 EmployeeID 而返回直接或间接向指定员工报告的所有员工的列表。然后在指定雇员 ID 109 的情况下调用此函数。
USE AdventureWorks2008R2;
GO
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);
GO
内置函数
SQL Server 提供了内置函数帮助您执行各种操作。这些函数不能修改。可以在 Transact-SQL 语句中使用内置函数,完成以下操作:
从 SQL Server 系统表中访问信息而不直接访问系统表。有关详细信息,请参阅使用系统函数。
执行常见任务,例如 SUM、GETDATE 或 IDENTITY。有关详细信息,请参阅内置函数 (Transact-SQL)。
内置函数返回标量数据类型或 table 数据类型。例如,如果成功执行了最后一条 Transact-SQL 语句,@@ERROR 将返回 0。如果该语句生成错误,则 @@ERROR 将返回错误号。而函数 SUM(parameter) 将返回参数的所有值的和。