使用者定義函數 (UDF) 是 SQL Server 2000 引入的重要可程式化物件,讓開發者將商務邏輯封裝為可重用的運算單元。UDF 可像系統函數一樣嵌入 SELECT、WHERE、CHECK、DEFAULT 等運算式,也能透過 EXECUTE 呼叫。依傳回值形式分為純量函數、內嵌資料表值函數、多陳述式資料表值函數 三類,各具適用場景與效能特徵。
| 類型 | 傳回值 | 函數主體 | 相當於 | 典型用途 |
|---|---|---|---|---|
| 純量函數 | 單一標量值(除 text/ntext/image/cursor/timestamp/table 外所有型別) | BEGIN ... END 區塊,含多條 T-SQL 陳述式,需 RETURN 回傳 | 延伸內建函數、複雜計算封裝 | 格式化字串、稅率計算、自訂日期運算 |
| 內嵌資料表值函數 | 單一資料表結果集 | 無 BEGIN/END,直接 RETURN (SELECT ...) | 參數化檢視表 | 依參數動態篩選資料、替代帶參數檢視表 |
| 多陳述式資料表值函數 | 資料表變數 | BEGIN ... END 區塊,宣告 @ret TABLE(...),多次 INSERT 後 RETURN | 複雜 ETL 轉換、多步驟篩選合併 | 分階段資料清洗、彙總多來源、遞迴階層查詢 |
CREATE FUNCTION dbo.fn_CalcTax (@Amount money, @Rate float)
RETURNS money
WITH SCHEMABINDING
AS
BEGIN
DECLARE @Tax money;
SET @Tax = ROUND(@Amount * @Rate, 2);
RETURN @Tax;
END
CREATE FUNCTION dbo.fn_GetOrdersByYear (@Year int)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN (
SELECT OrderID, CustomerID, OrderDate, TotalAmount
FROM dbo.Orders
WHERE YEAR(OrderDate) = @Year
);
CREATE FUNCTION dbo.fn_TopCustomersByRegion (@Region nvarchar(30), @TopN int)
RETURNS @Result TABLE (
CustomerID nchar(5),
CompanyName nvarchar(40),
TotalOrders int,
TotalAmount money
)
WITH SCHEMABINDING
AS
BEGIN
INSERT @Result
SELECT c.CustomerID, c.CompanyName,
COUNT(o.OrderID), SUM(od.UnitPrice * od.Quantity * (1 - od.Discount))
FROM dbo.Customers c
JOIN dbo.Orders o ON c.CustomerID = o.CustomerID
JOIN dbo.[Order Details] od ON o.OrderID = od.OrderID
WHERE c.Region = @Region
GROUP BY c.CustomerID, c.CompanyName
ORDER BY TotalAmount DESC;
-- 只保留前 N 筆
DELETE FROM @Result
WHERE CustomerID NOT IN (
SELECT TOP (@TopN) CustomerID FROM @Result ORDER BY TotalAmount DESC
);
RETURN;
END
CROSS APPLY 內嵌函數、或將邏輯內嵌查詢、或改為預存程序輸出結果集。ALTER TABLE t ADD Total AS dbo.fn_CalcLineTotal(Qty, Price, Discount)(需確定性+SCHEMABINDING)。CONSTRAINT chk_ValidDate CHECK (dbo.fn_IsBusinessDay(DateCol) = 1)。SELECT * FROM dbo.fn_GetOrdersByYear(2023) 替代動態 SQL。善用三類 UDF 的特性差異,配合 SCHEMABINDING、CROSS APPLY、確定性設計,即能在保持程式碼可維護性的同時,獲得接近內建函數的執行效能。