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

SQL Server 動態 SQL 實戰:sp_executesql 與 EXECUTE 選型、參數化、輸出參數完整指南

     編輯:關於SqlServer

動態 SQL 在運行時構建語句,適用於查詢條件、欄位列表、表名等不可預知的場景。但它引入 SQL 注入風險、除錯困難、計畫快取汙染等問題。本文通過實例演示如何安全、高效地使用動態 SQL。

核心場景:將 WHERE 條件傳遞給存儲過程

錯誤嘗試:

DECLARE @WhereClause NVARCHAR(2000) = 'Product=''Computer'''
SELECT * FROM SalesHistory WHERE @WhereClause  -- 語法錯誤,無法直接變數作條件

正確模式:構建完整語句字符串 + sp_executesql

CREATE PROCEDURE usp_GetSalesHistory
    @WhereClause NVARCHAR(2000) = NULL
AS
BEGIN
    DECLARE @SelectStmt NVARCHAR(2000) = 'SELECT TOP 5 * FROM SalesHistory'
    DECLARE @FullStmt NVARCHAR(4000) = @SelectStmt + ISNULL(@WhereClause, '')
    PRINT @FullStmt  -- 除錯用
    EXECUTE sp_executesql @FullStmt
END

sp_executesql vs EXECUTE():為何首選前者?

進階:獲取動態查詢的輸出參數(如總行數)

CREATE PROCEDURE usp_GetSalesHistory
    @WhereClause NVARCHAR(2000) = NULL,
    @TotalRowsReturned INT OUTPUT
AS
BEGIN
    DECLARE @SelectStmt NVARCHAR(2000) = 'SELECT @TotalRowsReturned = COUNT(*) FROM SalesHistory'
    DECLARE @FullStmt NVARCHAR(4000) = @SelectStmt + ISNULL(@WhereClause, '')
    DECLARE @ParamList NVARCHAR(500) = '@TotalRowsReturned INT OUTPUT'

    PRINT @FullStmt
    EXECUTE sp_executesql @FullStmt, @ParamList, @TotalRowsReturned = @TotalRowsReturned OUTPUT
END

-- 調用示例
DECLARE @Where NVARCHAR(2000) = 'WHERE Product = ''Computer'''
DECLARE @Total INT
EXEC usp_GetSalesHistory @WhereClause = @Where, @TotalRowsReturned = @Total OUTPUT
SELECT @Total

安全與效能黃金法則

  1. 永不 直接拼接用戶輸入,必須使用參數化(sp_executesql @stmt, @params, @p1=@v1...)。
  2. 動態 SQL 僅用於「結構動態」(表名、欄位名、運算子),「值動態」一律走參數。
  3. 對識別符(表/欄位名)使用 QUOTENAME() 包裹。
  4. 嚴格控制權限:執行動態 SQL 的模組簽名憑證/非對稱金鑰,授予最小權限。
  5. 監控計畫快取:SELECT objtype, usecounts, text FROM sys.dm_exec_cached_plans cp CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) WHERE objtype = 'Prepared' OR objtype = 'Adhoc' 觀察 Adhoc 佔比。

調試技巧

  • 開發階段保留 PRINT @FullStmt,上線前註釋或改為條件編譯。
  • 使用 TRY...CATCH 包裹 sp_executesql 捕獲運行時錯誤並記錄完整語句。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性sp_executesqlEXECUTE()
參數化支援支援輸入/輸出參數不支援,需字符串拼接
SQL 注入防護參數化機制天然防注入字符串拼接極易注入
計畫快取複用參數化語句易產生可複用計畫每次拼接產生新計畫,汙染快取
代碼可讀性結構清晰,參數列表分離字符串拼接雜亂難維護