- 純量值函數(Scalar Function)
- 資料表值函數(Table-Valued Function)
- 內嵌資料表值函數(Inline Table-Valued Function)
- 多種陳述式資料表值函數(MultiStatement Table-Valued Function)
純量值函數(SF)
使用自定函數來進行字串連結
USE [AdventureWorks2012]
GO
IF OBJECT_ID(N'dbo.getCommaString', N'FN') IS NOT NULL
DROP FUNCTION dbo.getCommaString
GO
-- 建立 FUNCTION
CREATE FUNCTION getCommaString(@SalesOrderID int)
RETURNS varchar(500) -- 500若不夠,請加大
BEGIN
DECLARE @string varchar(500) -- 500若不夠,請加大
SET @string = ''
SELECT @string = @string + CAST(ProductID AS VARCHAR(50)) + ','
FROM [Sales].[SalesOrderDetail]
WHERE SalesOrderID = @SalesOrderID
ORDER BY ProductID
SET @string = LEFT(@string,LEN(@string)-1) -- 把最後面的逗號後刪除
RETURN @string
END
GO
-- 使用自定函數來進行字串連結
SELECT
SalesOrderID ,
dbo.getCommaString(SalesOrderID) AS Lists
FROM [Sales].[SalesOrderHeader]
WHERE OrderDate = '20050701'
使用自定函數來計算訂單平均
USE [AdventureWorks2012]
GO
IF OBJECT_ID(N'dbo.ProdAVGUnitPrice', N'FN') IS NOT NULL
DROP FUNCTION dbo.ProdAVGUnitPrice
GO
CREATE FUNCTION dbo.ProdAVGUnitPrice(@ProductID int)
RETURNS smallmoney
BEGIN
RETURN
(
SELECT ISNULL(AVG(UnitPrice * (1 - UnitPriceDiscount)),0) AS AVGUnitPrice
FROM [Sales].[SalesOrderDetail]
WHERE ProductID = @ProductID
)
END
GO
SELECT
ProductID ,
Name ,
dbo.ProdAVGUnitPrice(ProductID) AS AVGUnitPrice
FROM [Production].[Product]
ORDER BY AVGUnitPrice DESC
內嵌資料表值函數(ITVF)
內嵌資料表值函數像是帶有參數的 VIEW
USE [AdventureWorks2012]
GO
IF OBJECT_ID(N'dbo.CustomerOrder') IS NOT NULL
DROP FUNCTION dbo.CustomerOrder
GO
CREATE FUNCTION dbo.CustomerOrder(@customerid int,@year int)
RETURNS TABLE
AS
RETURN
(
SELECT
SOH.CustomerID AS 客戶編號,
YEAR(SOH.OrderDate) AS 年份,
SUM(ROUND(SOD.OrderQty * SOD.UnitPrice * (1 - SOD.UnitPriceDiscount),0)) AS 總金額
FROM [Sales].[SalesOrderHeader] AS SOH
JOIN [Sales].[SalesOrderDetail] AS SOD ON SOH.SalesOrderID = SOD.SalesOrderID
WHERE SOH.CustomerID = @customerid
AND YEAR(OrderDate) = @year
GROUP BY SOH.CustomerID,YEAR(OrderDate)
)
GO
SELECT * FROM dbo.CustomerOrder(30117,2005)
GO
多種陳述式資料表值函數(MSTVF)
利用 Table-Valued Parameter (TVP) 來當成回傳值,可以建立 Clustered Index,SQL Server 2014 開始可以在 TVP 上建立 nonclustered index
USE [AdventureWorks2012]
GO
IF OBJECT_ID('dbo.EmployLists') IS NOT NULL
DROP FUNCTION dbo.EmployLists
GO
CREATE FUNCTION dbo.EmployLists (@type varchar(30))
RETURNS @TVP TABLE
(
EmpID int Primary key ,
EmpNameName nvarchar(100)
)
AS
BEGIN
IF @type = 'LongName'
INSERT INTO @TVP (EmpID,EmpNameName)
SELECT
E.BusinessEntityID ,
CONCAT(P.LastName,'-',P.FirstName)
FROM [HumanResources].[Employee] AS E
JOIN [Person].[Person] P ON E.[BusinessEntityID] = P.[BusinessEntityID]
ELSE
INSERT INTO @TVP (EmpID,EmpNameName)
SELECT
E.BusinessEntityID ,
P.LastName
FROM [HumanResources].[Employee] AS E
JOIN [Person].[Person] P ON E.[BusinessEntityID] = P.[BusinessEntityID]
RETURN
END
GO
SELECT * FROM dbo.EmployLists('LongName')
三者整理
SF | ITVF | MTVF | |
---|---|---|---|
宣告回傳值 | RETURNS 資料型別 | RETURNS TABLE | RETURNS TVP |
程式 | BEGIN...END | AS | BEGIN...END |
回傳值 | RETURN 值 | RETURN(SELECT 指令) | RETURN |
- 參考資料
- 論壇問題 1、2、3、4、5
- 使用者定義函數
- 內嵌使用者定義函數
- 資料表值使用者定義函數
- CREATE FUNCTION
- SQL Server 2005 - 如何在使用者自訂函數中叫用 GetDate() 函數
- 網路討論 - Function 參數預設值
- [SQL Server] Parameter sniffing occurs with Multi-Statement Table-Valued Function
- [SQL Server] Multi-Statement Table-Valued Function have a fixed Cardinality Estimation value
- [SQL Server] Interleaved execution for multi-statement table valued functions
- [SQL Server] Execution plan of Inline TVF is the same as Ad hoc Query
- 了解多重陳述式資料表值函式MTVF效能改善
沒有留言:
張貼留言