http://www.cnblogs.com/goody9807/archive/2010/10/19/1855697.htmlhtml
動態sql語句基本語法 sql
1 :普通SQL語句能夠用Exec執行
eg: Select * from tableName 數據庫
Exec( 'select * from tableName ') 緩存
Exec sp_executesql N 'select * from tableName ' -- 請注意字符串前必定要加N 安全
2:字段名,表名,數據庫名之類做爲變量時,必須用動態SQL
eg: 函數
declare @fname varchar(20) set @fname = 'FiledName ' post
Select @fname from tableName -- 錯誤,不會提示錯誤,但結果爲固定值FiledName,並不是所要。 性能
Exec( 'select ' + @fname + ' from tableName ') -- 請注意 加號先後的 單引號的邊上加空格
固然將字符串改爲變量的形式也可 url
declare @fname varchar(20) set @fname = 'FiledName ' --設置字段名
declare @s varchar(1000) set @s = 'select ' + @fname + ' from tableName ' Exec(@s) -- 成功 spa
exec sp_executesql @s -- 此句會報錯
declare @s Nvarchar(1000) -- 注意此處改成nvarchar(1000)
set @s = 'select ' + @fname + ' from tableName '
Exec(@s) -- 成功
exec sp_executesql @s -- 此句正確
3. 輸出參數
declare @num int, @sql nvarchar(4000)
set @sql= 'select count(*) from tableName '
exec(@sql)
--如何將exec執行結果放入變量中?
declare @num int, @sql nvarchar(4000)
set @sql= 'select @a=count(*) from tableName '
exec sp_executesql @sql,N '@a int output ',@num output select @num
-----------------------
@maxnum int output --最大數量
declare @idcount int --用於存儲 exec 語句賦值的變量
declare @maxpagesql nvarchar(300) --必定要nvarchaar
set @maxpagesql = 'select @idcount=count(id) from QuestionInfo where 1=1 '
exec sp_executesql @maxpagesql,N'@idcount int output ',@maxnum output
select @maxnum
動態SQL EXEC(http://www.cnblogs.com/Junelee1211/archive/2011/08/25/2153024.html)
一、EXEC命令的括號中只容許包含一個字符串變量,或者一個 字符串文本,或者字符串變量與字符串文本的串聯。不能再括號中使用函數或CASE表達式,以下面嘗試在括號中調用QUOTENAME函數以引用對象名稱,運行將失敗:
1: DECLARE @schemaname NVARCHAR(255),@tablename NVARCHAR(128)
2: SET @schemaname='dbo'
3: SET @tablename='Order Details'
4:
5: EXEC (N'SELECT COUNT(*) FROM '+QUOTENAME(@schemaname)+N'.'+QUOTENAME(@tablename)+N';')
上述代碼將會產生以下錯誤:
消息 102,級別 15,狀態 1,第 5 行 'QUOTENAME' 附近有語法錯誤。 SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 0 毫秒。
SQL Server 執行時間: CPU 時間 = 0 毫秒,佔用時間 = 0 毫秒。
因此作好的方法是把代碼構造到一個變量中,這樣就不會受限制了,而後再把該變量做爲EXEC命令的輸入參數,就像這樣:
1: DECLARE @schemaname NVARCHAR(255) ,
2: @tablename NVARCHAR(128) ,
3: @sql NVARCHAR(MAX)
4: SET @schemaname = 'dbo'
5: SET @tablename = 'Order Details'
6: SET @sql = N'SELECT COUNT(*) FROM ' + QUOTENAME(@schemaname) + N'.'
7: + QUOTENAME(@tablename) + N';'
8: EXEC (@sql)
二、EXEC不提供接口。EXEC(<string>)不提供接口。它惟一的輸入就是包含你要調用代碼的字符串。動態批處理不能訪問在調用批處理中定義的局部變量。以下面代碼嘗試訪問定義在調用批處理中的變量將失敗。
1: DECLARE @i INT
2: SET @i = 10248
3:
4: DECLARE @sql NVARCHAR(MAX)
5:
6: SET @sql = 'SELECT * FROM dbo.Orders WHERE OrderID=@i;'
7: EXEC(@sql)
將產生以下錯誤:
消息 137,級別 15,狀態 2,第 1 行 必須聲明標量變量 "@i"。
使用EXEC時,若是想訪問變量,必須把變量內容串聯到動態構建的 代碼字符串中。
DECLARE @i INT SET @i = 10248 DECLARE @sql NVARCHAR(MAX) SET @sql = 'SELECT * FROM dbo.Orders WHERE OrderID=' + CAST(@i AS NVARCHAR(10)) + ';' EXEC(@sql)
這樣就沒有問題了。
若是一個變量包含字符串,把該變量的內容串聯到代碼將會致使安全風險(SQL注入),爲了不SQL注入,能夠吧字符串大小限制爲所需的最小長度。固然,實際中這種狀況根本不須要動態SQL直接執行SQL語句就能夠,這個示例只是爲了演示。
串聯變量的內容存在性能方面的弊端,SQL Server將爲每一個惟一的查詢字符串建立新的即席執行計劃,即便查詢模式相同也是這樣的。爲演示這一點,先清空緩存中的執行計劃。
DBCC FREEPROCCACHE
1: SELECT cacheobjtype ,
2: objtype ,
3: usecounts ,
4: sql
5: FROM sys.syscacheobjects
6: WHERE sql NOT LIKE '%cache%'
7: AND sql NOT LIKE '%sys.%'
獲得查詢結果:
cacheobjtype objtype usecounts sql Compiled Plan Adhoc 1 SELECT * FROM dbo.Orders WHERE OrderID=10250; Compiled Plan Adhoc 1 SELECT * FROM dbo.Orders WHERE OrderID=10248; Compiled Plan Prepared 3 (@1 smallint)SELECT * FROM [dbo].[Orders] WHERE [OrderID]=@1 Compiled Plan Adhoc 4 SET STATISTICS IO ON SET STATISTICS TIME ON Compiled Plan Adhoc 1 SELECT * FROM dbo.Orders WHERE OrderID=10249; Compiled Plan Adhoc 4 SET STATISTICS IO OFF SET STATISTICS TIME OFF
EXEC除了不支持動態批處理中的輸入參數外,也不支持輸出參數。默認狀況下,EXEC把查詢輸出返回給調用者。若是你想把輸出結果返回給調用批處理中的變量,事情就沒那麼簡單了,爲此,你須要使用INSERT EXEC把輸出插入到一個目的表,而後再從該表中取值,賦給該變量,就像這樣:
1: DECLARE @schemaname NVARCHAR(128) ,
2: @tablename NVARCHAR(128) ,
3: @colname NVARCHAR(128) ,
4: @sql NVARCHAR(MAX) ,
5: @cnt INT
6:
7: SET @schemaname = 'dbo'
8: SET @tablename = 'Orders'
9: SET @colname = 'CustomerID'
10:
11: SET @sql = N'SELECT COUNT(DISTINCT ' + QUOTENAME(@colname) + ') FROM '
12: + QUOTENAME(@schemaname) + N'.' + QUOTENAME(@tablename) + N';'
13:
14: CREATE TABLE #T1 ( cnt INT )
15: INSERT INTO #T1
16: EXEC ( @sql
17: )
18: SELECT @cnt = cnt
19: FROM #T1
20: SELECT @cnt
21: DROP TABLE #T1
三、在SQL Server2000中串聯變量值時,EXEC比sp_executesql多一個優點,它支持更長的代碼,儘管技術上sp_executesql的輸入代碼字符串是NTEXT類型的,但你通常是在局部變量中構造代碼字符串。而你又不能用大型對象類型聲明局部變量,因此,實際上在sp_executesql中執行的查詢字符串被限制爲Unicode字符串(NVARCHAR)支持的最大長度4000,而EXEC支持常規字符串(VARCHAR)容許最大8000個字符。另外EXEC還支持一個特殊的功能,它容許你在括號中串聯多個變量,每一個變量都支持8000個字符的長度。
在SQL Server2005中,就不用這麼糾結了,由於能夠爲EXEC命令提供一個VARCHAR(MAX)或NVARCHAR(MAX)的變量做爲輸入,輸入字符串能夠達到2GB大小