exec與sp_executesql語法的區別詳解(轉)
動態語句語法:
--方法1查詢表改為動態
select * from sysobjects
exec("select ID,Name from sysobjects")
exec sp_executesql N"select ID,Name from sysobjects"--多了一個N為unicode
--方法2:欄位名,表名,資料庫名之類作為變數時,用動態SQL
declare @FName varchar(20)
set @FName="ID"
exec("select "[email protected]+" from sysobjects where "[email protected]
declare @s varchar(1000)
set @s=N"select "[email protected]+" from sysobjects where "[email protected]+"=5"
exec sp_executesql @s--會報錯
declare @s nvarchar(1000)--改為nvarchar
set @s=N"select "[email protected]+" from sysobjects where "[email protected]+"=5"
exec sp_executesql @s--成功
--方法3:輸入引數
declare @i int,@s nvarchar(1000)
set @i=5
exec("select ID,Name from sysobjects where ID="
set @s="select ID,Name from sysobjects where [email protected]"
exec sp_executesql @s,N"@i int",@i--此處輸入引數要加上N
--方法4:輸出引數
declare @i int,@s nvarchar(1000)
set @s="select @i=count(1) from sysobjects"
--用exec
exec("declare @i int "[email protected]+" select @i")--把整個語句用字串加起來執行
--用sp_executesql
exec sp_executesql @s,N"@i int output",@i output--此處輸出引數要加上N
select @i
--方法5:輸入輸出
--用sp_executesql
declare @i int,@con int,@s nvarchar(1000)
set @i=5
select @s="select @con=count(1) from sysobjects where ID>@i"
exec sp_executesql @s,N"@con int output,@i int",@con output ,@i
select @con
--用exec
declare @i int,@s nvarchar(1000)
set @i=5
select @s="declare @con int select @con=count(1) from sysobjects where
ID>"+rtrim(@i)+" select @con"
exec(@s)
SQL Server EXEC和sp_executesql的區別
1,EXEC的運用
2,sp_executesql的運用
MSSQL為我們提供了兩種動態執行SQL語句的命令,分別是EXEC和
sp_executesql;通常,sp_executesql則更具有優勢,它提供了輸入輸出介面,而EXEC
沒有。還有一個最大的優點就是運用 sp_executesql,能夠重用執行計劃,這就大大
提供了執行效能(對於這個我在後面的例子中會詳加說明),還可以編寫更安全的程式碼
。EXEC在某些情況下會更靈活。除非您有令人信服的理由運用 EXEC,否側儘量運用
sp_executesql.
1,EXEC的運用
EXEC命令有兩種用法,一種是執行一個儲存流程,另一種是執行一個動態的批處理。
以下所講的都是第二種用法。
下面先運用 EXEC演示一個例子,程式碼1
DECLARE @TableName VARCHAR(50),@Sql NVARCHAR(MAX),@OrderID INT; SET
@TableName = "Orders"; SET @OrderID = 10251; SET @sql = "SELECT * FROM
"+QUOTENAME(@TableName) +"WHERE OrderID = "+CAST(@OrderID AS VARCHAR(10))
+" ORDER BY ORDERID DESC" EXEC(@sql); 注:這裡的EXEC括號中只允許包含一個字
符串變數,但是可以串聯多個變數,如果我們這樣寫EXEC:
EXEC("SELECT TOP("+ CAST(@TopCount AS VARCHAR(10)) +")* FROM "+QUOTENAME
(@TableName) +" ORDER BY ORDERID DESC");
SQL編譯器就會報錯,編譯不通過,而如果我們這樣:
EXEC(@
所以最佳的做法是把程式碼構造到一個變數中,然後再把該變數作為EXEC命令的輸入參
數,這樣就不會受限定了;
EXEC不提供介面
這裡的介面是指,它不能執行一個包含一個帶變數符的批處理,這裡乍一聽好像不明
白,不要緊,我在下面有一個例項,您一看就知道什麼意思.
DECLARE @TableName VARCHAR(50),@Sql NVARCHAR(MAX),@OrderID INT; SET
@TableName = "Orders"; SET @OrderID = 10251; SET @sql = "SELECT * FROM
"+QUOTENAME(@TableName) +"WHERE OrderID = @OrderID ORDER BY ORDERID DESC"
EXEC(@sql); 關鍵就在SET @sql這一句話中,如果我們執行這個批處理,編譯器就會
產生一下不正確
Msg 137, Level 15, State 2, Line 1
必須宣告標量變數 "@OrderID"。
運用 EXEC時,如果您想訪問變數,必須把變數內容串聯到動態構建的程式碼字串中
,如:SET @sql = "SELECT * FROM "+QUOTENAME(@TableName) +"WHERE OrderID =
"+CAST(@OrderID AS VARCHAR(10))+" ORDER BY ORDERID DESC"
串聯變數的內容也存在效能方面的弊端。SQL Server為每一個的查詢字串建立新的
執行計劃,即使查詢模式相同也是這樣。為演示這一點,先清空快取中的執行計劃
DBCC FREEPROCCACHE (這個不是本文所涉及的內容,您可以檢視MS的MSDN)
http://msdn.microsoft.com/zh-cn/library/ms174283.aspx
將程式碼1執行3次,分別對@OrderID 賦予下面3個值,10251,10252,10253。然後運
用下面的程式碼查詢
SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects WHERE
sql NOT LIKE "%cach%" AND sql NOT LIKE "%sys.%" 點選F5執行,就會出現下面
如圖所示的查詢結果:
我們可以看到,每執行一次都要產生一次的編譯,執行計劃沒有得到充分重用。
EXEC除了不支援動態批處理中的輸入引數外,他也不支援輸出引數。預設情況下,
EXEC把查詢的輸出返回給呼叫者。例如下面程式碼返回Orders表中所有的記錄數
DECLARE @sql NVARCHAR(MAX) SET @sql = "SELECT COUNT(ORDERID) FROM Orders";
EXEC(@sql); 然而,如果你要把輸出返回給呼叫批處理中的變數,事情就沒有那麼基
本了。為此,你必須運用 INSERT EXEC語法把輸出插入到一個目標表中,然後從這表
中獲取值後賦給該變數,就像這樣:
DECLARE @sql NVARCHAR(MAX),@RecordCount INT SET @sql = "SELECT COUNT
(ORDERID) FROM Orders"; CREATE TABLE #T(TID INT); INSERT INTO #T EXEC
(@sql); SET @RecordCount = (SELECT TID FROM #T) SELECT @RecordCount DROP
TABLE #T 2,sp_executesql的運用
sp_executesql命令在SQL Server中引入的比EXEC命令晚一些,它主要為重用執行計
劃提供更好的支援。
為了和EXEC作一個鮮明的比較 ,我們看看如果用程式碼1的程式碼,把EXEC換成
sp_executesql,看看能不能得到我們所期望的結果
DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT ,@sql2
NVARCHAR(MAX); SET @TableName = "Orders "; SET @OrderID = 10251; SET @sql
= "SELECT * FROM "+QUOTENAME(@TableName) + " WHERE OrderID = "+CAST
(@OrderID AS VARCHAR(50)) + " ORDER BY ORDERID DESC" EXEC sp_executesql
@sql 留心最後一行;
事實證明可以執行;
sp_executesql提供介面
sp_executesql命令比EXEC命令更靈活,因為它提供一個介面,該介面及支援輸入參
數也支援輸出引數。這功能使你可以建立帶引數的查詢字串,這樣就可以比EXEC更
好的重用執行計劃,sp_executesql的構成與儲存流程非常相似,不同之處在於你是動
態構建程式碼。它的構成包括:程式碼快,引數宣告部分,引數賦值部分。說了這麼多,
還是看看它的語法吧
EXEC sp_executesql
@stmt = <statement>,--類似儲存流程主體
@params = <params>, --類似儲存流程引數部分
<params assignment> --類似儲存流程呼叫
@stmt引數是輸入的動態批處理,它可以引入輸入引數或輸出引數,和儲存流程的主
體語句一樣,只不過它是動態的,而儲存流程是靜態的,不過你也可以在儲存流程中
運用 sp_executesql;
@params引數與定義輸入/輸出引數的儲存流程頭類似,實際上和儲存流程頭的語法完
全一樣;
@<params assignment> 與呼叫儲存流程的EXEC部分類似。
為了說明sp_executesql對執行計劃的管理優於EXEC,我將運用前面討論EXEC時用到的
程式碼。
1: DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT; 2:
SET @TableName = "Orders "; 3: SET @OrderID = 10251; 4: SET @sql =
"SELECT * FROM "+QUOTENAME(@TableName) + " WHERE OrderID = @OID ORDER BY
ORDERID DESC" 5: EXEC sp_executesql 6: @stmt = @sql, 7: @params =
N"@OID AS INT ", 8: @OID = @OrderID 在呼叫該程式碼和檢查它生成的執行計劃前
,先清空快取中的執行計劃;
DBCC FREEPROCCACHE
將上面的動態程式碼執行3次,每次執行都賦予@OrderID 不同的值,然後查詢
sys.syscacheobjects表,並留心它的輸出,優化器只建立了一個備用計劃,而且該
計劃被重用的3次
SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects WHERE
sql NOT LIKE "%cache%" AND sql NOT LIKE "%sys.%" AND sql NOT LIKE "%
sp_executesql%" 點選F5執行,就會出現如下表所示的結果;
sq_executesql的另一個與其介面有關的強大功能是,你可以運用輸出引數為呼叫批
處理中的變數返回值。運用 該功能可以防止用臨時表返回資料,從而得到更高效的
程式碼和更少的重新編譯。定義和運用輸出引數的語法與儲存流程類似。也就是說,你
須要在宣告引數時指定OUTPUT子句。例如,下面的靜態程式碼基本的演示瞭如何 從動
態批處理中運用 輸出引數@p把值返回到外部批處理中的變數@i.
DECLARE @sql AS NVARCHAR(12),@i AS INT;SET @sql = N" SET @p = 10"; EXEC
sp_executesql @stmt = @sql, @params = N"@p AS INT OUTPUT", @p = @i
OUTPUTSELECT @i該程式碼返回輸出10
相關推薦
exec與sp_executesql語法的區別詳解(轉)
動態語句語法: --方法1查詢表改為動態 select * from sysobjects exec("select ID,Name from sysobjects") exec sp_executesql N"select ID,Name from sysobjec
深入探討Linux靜態庫與動態庫的詳解(轉)
share 分享 命名 one .com 過程 程序 簡單介紹 mage 2.生成動態庫並使用 linux下編譯時通過 -shared 參數可以生成動態庫(.so)文件,如下 庫從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分靜態庫和動態庫兩種。
最詳盡的 JS 原型與原型鏈終極詳解(三)
小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。 七. 函式物件 (複習一下前面的知識點) 所有函式物件的proto都指向Funct
最詳盡的 JS 原型與原型鏈終極詳解(二)
小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。 四. __proto__ JS 在建立物件(不論是普通物件還是函式物件)的時候,都有一個叫做__pr
最詳盡的 JS 原型與原型鏈終極詳解(一)
小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。 一. 普通物件與函式物件 JavaScript 中,萬物皆物件!但物件也是有區別的。分為普通物件和函
Lua元表與元方法詳解(轉)
Lua中提供的元表是用於幫助Lua資料變數完成某些非預定義功能的個性化行為,如兩個table的相加。假設a和b都是table,通過元表可以定義如何計算表示式a+b。當Lua試圖將兩個table相加時,它會先檢查兩者之一是否有元表,然後檢查該元表中是否存在_
安裝Jdk、Maven、Tomcat與配置環境變數詳解(Win10)
前言 本文針對於WIN10下JDK,Maven,Tomcat等常用開發工具的下載配置步驟作出詳解。Win7,Win8步驟類似。對於這些常用開發工具建議建立一個資料夾統一維護 由於,Maven,Tomcat等工具都是依賴與JDK,所以首先要安裝好JDK。話不多說
java中異常與try catch finally詳解(轉載)
簡介程式執行時,發生的不被期望的事件,它阻止了程式按照程式設計師的預期正常執行,這就是異常。異常發生時,是任程式自生自滅,立刻退出終止,還是輸出錯誤給使用者?或者用C語言風格:用函式返回值作為執行狀態?。Java提供了更加優秀的解決辦法:異常處理機制。異常處理機制能讓程式在異
Linux的SOCKET編程詳解(轉)
readv lose 服務 網絡字節序 返回值 quest avi 取數 key Linux的SOCKET編程詳解 1. 網絡中進程之間如何通信 進 程通信的概念最初來源於單機系統。由於每個進程都在自己的地址範圍內運行,為保證兩個相互通信的進 程之間既互不幹擾又
綜合運用: C++11 多線程下生產者消費者模型詳解(轉)
並發 rep 生產 我會 交流 模型 操作 const ref 生產者消費者問題是多線程並發中一個非常經典的問題,相信學過操作系統課程的同學都清楚這個問題的根源。本文將就四種情況分析並介紹生產者和消費者問題,它們分別是:單生產者-單消費者模型,單生產者-多消費者模型,多生產
C/C++中作用域詳解(轉)
防止 局部作用域 gist 文件中 方式 為什麽不使用 形式參數 lan archive 作用域規則告訴我們一個變量的有效範圍,它在哪兒創建,在哪兒銷毀(也就是說超出了作用域)。變量的有效作用域從它的定義點開始,到和定義變量之前最鄰近的開括號配對的第一個閉括號。也就是說,作
C# ListView用法詳解(轉)
分組 創建 cti 排列 checkbox 定義 com 程序 erl 一、ListView類 1、常用的基本屬性: (1)FullRowSelect:設置是否行選擇模式。(默認為false) 提示:只有在Details視圖該屬性才有
C++ 智能指針詳解(轉)
include 復雜 測試類 信息 思想 編譯 應該 其他 eas C++ 智能指針詳解 一、簡介 由於 C++ 語言沒有自動內存回收機制,程序員每次 new 出來的內存都要手動 delete。程序員忘記 delete,流程太復雜,最終導致沒有 delete,異常導致程
解析xml的4種方法詳解(轉)
項目 目標 源碼 更多 news 大量 優秀 大型 頻繁 http://blog.csdn.net/jzhf2012/article/details/8532873 1. 介紹 1)DOM(JAXP Crimson解析器) DOM是用與平臺和語言無關的方式表
css動畫-animation各個屬性詳解(轉)
yellow range 空隙 定義 tro content bin ora .com CSS3的animation很容易就能實現各種酷炫的動畫,雖然看到別人的成果圖會覺得很難,但是如果掌握好各種動畫屬性,做好酷炫吊炸天的動畫都不在話下,好,切入正題。 一、動畫屬性:
epoll使用詳解(轉)
supports weak 第一次 sets processes windows 監聽事件 atoi 變化 epoll - I/O event notification facility在linux的網絡編程中,很長的時間都在使用select來做事件觸發。在linux新的內
Understand:高效代碼靜態分析神器詳解(轉)
none 前段時間 兩個 箭頭 ++ 開發 obj 結構 導入 之前用Windows系統,一直用source insight查看代碼非常方便,但是年前換到mac下面,雖說很多東西都方便了,但是卻沒有了靜態代碼分析工具,很幸運,前段時間找到一款比source insight軟
回溯法實例詳解(轉)
函數 枚舉 必須 using tool 有一個 發現 ads 問題 概念 回溯算法實際上一個類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就“回溯”返回,嘗試別的路徑。 回溯法是一種選優搜索法,按選優條件向前搜索,以達
Spartan6芯片配置模式詳解(轉)
roc gen bit png 寬度 con 讀取配置 3.2 多個 1. 配置概述 Spartan6系列FPGA通過把應用程序數據導入芯片內部存儲器完成芯片的配置。Spart-6 FPGA可以自己從外部非易失性存儲器導入編程數據,或者通過外界的微處理器、DSP等對其進行
log4j的配置詳解(轉)
version let imp err pro 字符 bug rom 程序 轉自:http://blog.sina.com.cn/s/blog_5ed94d710101go3u.html 最近使用log4j寫log時候發現網上的寫的都是千篇一律,寫的好的嘛不