| 特性 | EXEC (@sql) | sp_executesql |
|---|---|---|
| 參數介面 | 無 (需字串拼接) | 有 (@params + 參數賦值) |
| 計畫重用 | 難 (每次不同字串產生新計畫) | 易 (參數化查詢共用計畫) |
| 輸出參數 | 不支援 (需 INSERT EXEC 臨時表) | 支援 (OUTPUT 子句) |
| 注入風險 | 高 (字串拼接) | 低 (參數化) |
| 動態批次長度 | 受限 (單一字串變數) | 靈活 (支援多變數拼接) |
DECLARE @TableName VARCHAR(50) = 'Orders', @OrderID INT = 10251;
DECLARE @sql NVARCHAR(MAX) = 'SELECT * FROM ' + QUOTENAME(@TableName) + ' WHERE OrderID = ' + CAST(@OrderID AS VARCHAR(10));
EXEC (@sql); -- 每次 @OrderID 變動產生新計畫
缺點:
INSERT #t EXEC(@sql) 繞道。
DECLARE @TableName VARCHAR(50) = 'Orders', @OrderID INT = 10251;
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM ' + QUOTENAME(@TableName) + N' WHERE OrderID = @OID ORDER BY OrderID DESC';
EXEC sp_executesql
@stmt = @sql,
@params = N'@OID INT',
@OID = @OrderID; -- 參數化,計畫可重用
DBCC FREEPROCCACHE;
-- 執行 3 次,不同 @OrderID
EXEC sp_executesql ... @OID=10251;
EXEC sp_executesql ... @OID=10252;
EXEC sp_executesql ... @OID=10253;
SELECT cacheobjtype, objtype, usecounts, text
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle)
WHERE text LIKE '%Orders%' AND text NOT LIKE '%cache%';
-- 結果:usecounts = 3,單一計畫被重用 3 次
DECLARE @sql NVARCHAR(100) = N'SET @p = 10', @i INT;
EXEC sp_executesql
@stmt = @sql,
@params = N'@p INT OUTPUT',
@p = @i OUTPUT;
SELECT @i; -- 10
CREATE TABLE 欄位清單完全動態)。QUOTENAME() 包裹物件名稱,防注入。sys.dm_exec_cached_plans 確認計畫重用率。掌握 sp_executesql 參數化模式,是撰寫安全、高效能動態 SQL 的核心技能。