過去我執行拼湊出來的動态SQL語句,都直接使用EXEC @sql 的方式。有好幾次,都看到有資料說,應該盡量使用 sp_executesql。
究其原因,是因為僅僅參數不同的情況下,sp_executesql可以重用執行計劃,這不就有跟存儲過程一樣的優勢了嗎?同時,sp_executesql還可以提供動态SQL語句執行的傳回值,友善得很。
但sp_executesql的使用方式看上去比較複雜,一點都不像EXEC那樣直覺。
用法:
EXEC sp_executesql SQL語句,參數聲明,參數
如
CREATE TABLE #tmp(t INT NOT NULL,it DECIMAL(18,4),pt DECIMAL(18,4));
INSERT INTO #tmp(t,it,pt) VALUES(1,10.00,15.00);
INSERT INTO #tmp(t,it,pt) VALUES(2,20.00,30.00);
DECLARE @sql NVARCHAR(2000) = N'SELECT @it=it,@pt=pt FROM #tmp WHERE t=@tN;';
DECLARE @Param NVARCHAR(500) = N'@tN INT,@it DECIMAL(18,4) OUTPUT,@pt DECIMAL(18,4) OUTPUT';
DECLARE @tN INT,@it DECIMAL(18,4),@pt DECIMAL(18,4);
SET @tN = 1;
--@tN=@tN,第一個@tN是@Param裡的聲明,而第二個@tN則是外部的聲明,其他類似
EXEC sp_executesql @sql,@Param,@tN=@tN,@it=@it OUTPUT,@pt=@pt OUTPUT;
SELECT @it,@pt;
DROP TABLE #tmp;
為什麼有傳回值那麼重要呢?我在不知道這個用法以前,如果需要捕捉動态SQL語句裡的傳回值,要借用表對象:
詳見拙作:
declare @sql NVARCHAR(MAX) = N'SELECT @i,@j;';
declare @paramdefine NVARCHAR(MAX) = N'@i INT,@j INT,@k INT=3';
exec sp_executesql @sql,@paramdefine,@i=1,@j=2;