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

SQL 動態 SQL 中使用變數替換物件名稱:EXEC 與 sp_executesql 實作比較

     編輯:關於SqlServer

當資料表名、欄位名、資料庫名等識別碼需在執行期由變數決定時,必須使用動態 SQL。本文比較 EXEC (@SQL) 與 sp_executesql 兩種執行方式,說明變數作用域限制、參數化優勢與安全實作模式。

場景:動態決定 UPDATE 目標欄位

DECLARE @Week INT = 3;
DECLARE @User NVARCHAR(50) = N'User001';
DECLARE @SQL NVARCHAR(MAX);

-- 構建動態欄位名:[Week3]
SET @SQL = N'UPDATE WeekCount SET [' + QUOTENAME(N'Week' + CAST(@Week AS NVARCHAR(10))) + N'] = [' 
    + QUOTENAME(N'Week' + CAST(@Week AS NVARCHAR(10))) + N'] + 1 WHERE UserID = @User';

-- 執行並傳入參數
EXEC SP_EXECUTESQL @SQL, N'@User NVARCHAR(50)', @User = @User;

EXEC vs sp_executesql 差異對照

特性EXEC (@Str)SP_EXECUTESQL
參數化不支援支援輸入/輸出參數
計畫重用不可重用(每次重新編譯)可重用(參數化查詢)
防注入需自行處理參數與程式碼分離
變數作用域僅看見全域/會話變數可存取區域變數(透過參數)
效能高編譯 CPU低編譯 CPU

關鍵限制:EXEC 內無法直接存取外部區域變數

DECLARE @Val INT = 100;
EXEC ('PRINT @Val');  -- 錯誤:Must declare the scalar variable "@Val"

解法:改用 SP_EXECUTESQL 透過參數傳遞。

安全實作檢核清單

  • ✅ 所有使用者輸入值走參數化,嚴禁字串拼接。
  • ✅ 動態物件名稱(資料表、欄位、結構描述)使用 QUOTENAME() 包裹,防止識別碼注入。
  • ✅ 動態資料庫名稱:QUOTENAME(@DBName) + N'.dbo.Table'。
  • ✅ 限制動態 SQL 權限:僅授與 EXECUTE 權限於封裝預存程序,不直接授與底層物件權限。
  • ✅ 記錄動態 SQL 文字至稽核表(含參數值),利於事後追蹤。

進階:動態 ORDER BY / WHERE 條件

DECLARE @SortCol SYSNAME = N'CreateDate';
DECLARE @SortDir VARCHAR(4) = N'DESC';
DECLARE @SQL NVARCHAR(MAX) = N'SELECT * FROM Orders ORDER BY ' + QUOTENAME(@SortCol) + N' ' + @SortDir;
-- @SortDir 需驗證僅為 ASC/DESC,不可直接拼接使用者輸入
EXEC SP_EXECUTESQL @SQL;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved