1. 程式人生 > >exec與sp_executesql語法的區別詳解(轉)

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]

+"=5" )


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="
[email protected]
)

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(@
[email protected]
[email protected]); 編譯器就會通過;

所以最佳的做法是把程式碼構造到一個變數中,然後再把該變數作為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

相關推薦

execsp_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時候發現網上的寫的都是千篇一律,寫的好的嘛不