首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 表值函數完整指南:內嵌 vs 多陳述式、參數化、效能優勢

     編輯:關於SqlServer

類型一:內嵌表值函數 (Inline TVF)

單一 RETURN (SELECT ...),無 BEGIN/END,最佳化器可展開合併至外層查詢計畫,**效能最佳**。


CREATE FUNCTION Fun_GetReportNews(@type VARCHAR(10))
RETURNS TABLE
AS
RETURN (
    SELECT TPR_ID, TPR_Title, TPR_Date
    FROM TP_ReportNews
    WHERE TPR_Type = @type
);
GO

-- 呼叫
SELECT * FROM Fun_GetReportNews('News');

類型二:多陳述式表值函數 (Multi-statement TVF)

需宣告 RETURNS @Table TABLE (...),函數體用 BEGIN/END,可包含變數、流程控制、多步驟邏輯,**最佳化器視為黑盒**,效能較差。


CREATE FUNCTION FUN_GetInfoList(@type VARCHAR(10))
RETURNS @Table TABLE (TPR_ID INT, TPR_Title NVARCHAR(100), TPR_PubDate DATETIME)
AS
BEGIN
    DECLARE @a VARCHAR(10);
    SELECT @a = xx FROM XX WHERE xx = @type;
    INSERT @Table SELECT XX, XX, XX FROM TableName WHERE XX = @a;
    RETURN;
END;
GO

關鍵限制

  • 函數內**不可建立暫存表** (#temp),只能用**表變數** (@Table)。
  • 不可執行副作用操作 (INSERT/UPDATE/DELETE 針對永久表) — 僅限修改表變數。
  • 不可呼叫非確定性函數 (如 GETDATE(), NEWID()) — 內嵌 TVF 亦同。

標量值函數 (Scalar UDF) 對照


CREATE FUNCTION FUN_DataFormat(@strDate DATETIME)
RETURNS VARCHAR(20)
AS
BEGIN
    DECLARE @date VARCHAR(20);
    SET @date = DATENAME(YY, @strDate) + '年' + CONVERT(VARCHAR, MONTH(@strDate)) + '月' + CONVERT(VARCHAR, DAY(@strDate)) + '日';
    RETURN @date;
END;
GO

-- 呼叫需加 dbo 前綴,避免誤判為系統函數
SELECT dbo.FUN_DataFormat(GETDATE());

效能比較與選擇建議

類型適用場景效能最佳化器行為
內嵌 TVF單一 SELECT、參數化視圖替代極佳 (計畫合併)展開合併
多陳述式 TVF需變數、IF/ELSE、多步驟邏輯較差 (黑盒、估計列數固定 100)獨立計畫
標量 UDF單值轉換、計算極差 (逐列呼叫、阻礙平行)黑盒

現代替代方案 (SQL 2017+)

  • 內嵌 TVF → 仍為首選。
  • 多陳述式 TVF → 改用 **內嵌 TVF + CTE** 或 **預存程序 + INSERT EXEC**。
  • 標量 UDF → 改用 **內嵌 TVF (單欄)** 或 **計算欄位** / **檢視**。
  • SQL 2019 SCALAR UDF INLINING 可自動將符合條件的標量 UDF 內嵌化。

最佳實務

  1. 能用內嵌 TVF 就不用多陳述式。
  2. 避免在高頻查詢中呼叫標量 UDF。
  3. 表值函數命名建議 fn_ 或 tvf_ 前綴。
  4. 大量資料跨函數傳遞時,考慮 READONLY 表值參數 (TVP)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved