語法
使用 CAST:
CAST ( expression AS data_type )
使用 CONVERT:
CONVERT (data_type[(length)], expression [, style])
參數(shù)
expression
是任何有效的 Microsoft SQL Server" 表達式。有關(guān)更多信息,請參見表達式。
data_type
目標系統(tǒng)所提供的數(shù)據(jù)類型,包括 bigint 和 sql_variant。不能使用用戶定義的數(shù)據(jù)類型。有關(guān)可用的數(shù)據(jù)類型的更多信息,請參見數(shù)據(jù)類型。
length
nchar、nvarchar、char、varchar、binary 或 varbinary 數(shù)據(jù)類型的可選參數(shù)。
style
日期格式樣式,借以將 datetime 或 smalldatetime 數(shù)據(jù)轉(zhuǎn)換為字符數(shù)據(jù)(nchar、nvarchar、char、varchar、nchar 或 nvarchar 數(shù)據(jù)類型);或者字符串格式樣式,借以將 float、real、money 或 smallmoney 數(shù)據(jù)轉(zhuǎn)換為字符數(shù)據(jù)(nchar、nvarchar、char、varchar、nchar 或 nvarchar 數(shù)據(jù)類型)。
將某種數(shù)據(jù)類型的表達式顯式轉(zhuǎn)換為另一種數(shù)據(jù)類型。有關(guān)可用的數(shù)據(jù)類型的更多信息,請參見數(shù)據(jù)類型。日期格式樣式,借以將 datetime 或 smalldatetime 數(shù)據(jù)轉(zhuǎn)換為字符數(shù)據(jù)(nchar、nvarchar、char、varchar、nchar 或 nvarchar 數(shù)據(jù)類型);或者字符串格式樣式,借以將 float、real、money 或 smallmoney 數(shù)據(jù)轉(zhuǎn)換為字符數(shù)據(jù)(nchar、nvarchar、char、varchar、nchar 或 nvarchar 數(shù)據(jù)類型)。當(dāng)轉(zhuǎn)換為字符數(shù)據(jù)時輸出。
隱性轉(zhuǎn)換對于用戶是不可見的。
SQL Server 自動將數(shù)據(jù)從一種數(shù)據(jù)類型轉(zhuǎn)換成另一種數(shù)據(jù)類型。例如,如果一個 smallint 變量和一個 int 變量相比較,這個 smallint 變量在比較前即被隱性轉(zhuǎn)換成 int 變量。
顯式轉(zhuǎn)換使用 CAST 或 CONVERT 函數(shù)。
CAST 和 CONVERT 函數(shù)將數(shù)值從一個數(shù)據(jù)類型(局部變量、列或其它表達式)轉(zhuǎn)換到另一個數(shù)據(jù)類型。
例如,下面的 CAST 函數(shù)將數(shù)值 $157.27 轉(zhuǎn)換成字符串 ''$157.27'':CAST ( $157.27 AS VARCHAR(10) )
CAST 函數(shù)基于 SQL-92 標準并且優(yōu)先于 CONVERT。
當(dāng)從一個 SQL Server 對象的數(shù)據(jù)類型向另一個轉(zhuǎn)換時,一些隱性和顯式數(shù)據(jù)類型轉(zhuǎn)換是不支持的。例如,nchar 數(shù)值根本就不能被轉(zhuǎn)換成 image 數(shù)值。nchar 只能顯式地轉(zhuǎn)換成 binary,隱性地轉(zhuǎn)換到 binary 是不支持的。nchar 可以顯式地或者隱性地轉(zhuǎn)換成 nvarchar。
當(dāng)處理 sql_variant 數(shù)據(jù)類型時,SQL Server 支持將具有其它數(shù)據(jù)類型的對象隱性轉(zhuǎn)換成 sql_variant 類型。然而,SQL Server 并不支持從 sql_variant 數(shù)據(jù)隱性地轉(zhuǎn)換到其它數(shù)據(jù)類型的對象。
SELECT CONVERT(CHAR(10), CURRENT_TIMESTAMP, 102)
(102表明使用了ANSI日期模式,即yy.mm.dd型)
然而,如果你希望將這個變量明確生成為datetime或smalldatetime變量,以此在特定的數(shù)據(jù)庫欄中兼容,那么你可以使用以下語句:
SELECT CAST(CONVERT(CHAR(10),CURRENT_TIMESTAMP,102) AS DATETIME
返回值將是 yy.mm.dd 00:00:00(如12:00AM作為時間戳;
函數(shù)QUOTENAME
--功能:返回帶有分隔符的Unicode 字符串,分隔符的加入可使輸入的字符串成為有效的Microsoft SQL Server 2005 分隔標識符。
--語法
QUOTENAME ( 'character_string' [ , 'quote_character' ] )
--舉例說明:
--比如你有一個表,名字叫index
--你有一個動態(tài)查詢,參數(shù)是表名
declare @tbname varchar(256)
set @tbname='index'
---查這個表里的數(shù)據(jù):
print('select * from '+@tbname)
exec('select * from '+@tbname)
--這樣print出來的數(shù)據(jù)是
select * from index
--因為index是字鍵字,肯定出錯,加上括號就可以了:
select * from [index]
--這便有了QUOTENAME,即:
print('select * from '+QUOTENAME(@tbname))
--結(jié)果:select * from [index]
exec('select * from '+QUOTENAME(@tbname))
EXEC命令有兩個用法:執(zhí)行一個存儲過程,或者執(zhí)行一個動態(tài)批次。批次是一個內(nèi)容為SQL語句的字符串。
例如:
declare @schemaName varchar(80),@tableName varchar(80),
@objName varchar(512);
set @schemaName='dbo';
set @tableName='Orders';
set @objName=@schemaName+'.'+@tableName;
exec('select count(*) from '+@objName);
注意,在exec的括號里,只允許是字符串變量、字符串常量存在。不允許在這里調(diào)用函數(shù)或者使用case表達式。
下面的代碼是錯誤的:
exec('select count(*) from '+quotename(@objName));
所以,基本的方法是將語句保存到一個變量里,例如:
set @sql='...';
exec(@sql);
這就不存在上述限制了。
1 EXEC沒有接口
Exec的唯一輸入是字符串。一個動態(tài)批次無權(quán)訪問調(diào)用它的批次內(nèi)所定義的局部變量:
declare @i int
set @i=1;
declare @sql varchar(255)
set @sql='select * from dbo.orders where rderid=@i';
exec(@sql);
出錯:必須聲明標量變量@i
原因還是@i不能放在''之內(nèi),它只能通過字符串連接動態(tài)的嵌入到SQL語句里:
set @sql='select * from dbo.orders where rderid='+cast(@i as varchar(10));
變量與字符串連接會引發(fā)所謂的SQL注入安全隱患,如果變量包含了字符串。要防患SQL注入的一個辦法是限制
字符串的大小。
這種連接會對性能造成映像。SS會為每個字符串單獨創(chuàng)建一個執(zhí)行計劃,無論兩個字符串是否是一個模式。為此,
下面顯示了一個例子:
首先清除cache里的執(zhí)行計劃:
DBCC freeproccache;
然后執(zhí)行下面的代碼三次,分別將@i設(shè)置為10248,10249,10250
DECLARE @i AS INT;
SET @i = 10248;
DECLARE @sql AS VARCHAR(52);
SET @sql = 'SELECT * FROM dbo.Orders WHERE rderID = '
+ CAST(@i AS VARCHAR(10)) + N';';
EXEC(@sql)
最后查詢sys.syscacheobjects:
SELECT cacheobjtype, objtype, usecounts, sql
FROM sys.syscacheobjects
WHERE sql NOT LIKE '%cache%'
AND sql NOT LIKE '%sys.%';
結(jié)果顯示為:
它會為每次查詢生成一個執(zhí)行計劃。以及一個參數(shù)化的執(zhí)行計劃。
EXEC也沒有輸出參數(shù)。缺省情況下,exec將返回該次查詢的輸出給調(diào)用者。如果希望將該結(jié)果保存到變量里,那就必須
使用Insert EXEC語法,并從表里從新讀取該數(shù)據(jù),然后儲存到目標變量里。
DECLARE
@schemaname AS NVARCHAR(128),
@tablename AS NVARCHAR(128),
@colname AS NVARCHAR(128),
@sql AS NVARCHAR(805),
@cnt AS INT;
SET @schemaname = N'dbo';
SET @tablename = N'Orders';
SET @colname = N'CustomerID';
SET @sql = N'SELECT COUNT(DISTINCT '
+ QUOTENAME(@colname) + N') FROM '
+ QUOTENAME(@schemaname)
+ N'.'
+ QUOTENAME(@tablename)
+ N';';
CREATE TABLE #T(cnt INT);
INSERT INTO #T
EXEC(@sql);
SET @cnt = (SELECT cnt FROM #T);
SELECT @cnt;
DROP TABLE #T;
注意如果忘記輸入最后的一條語句“Drop 。。?!保敲淳蜁霈F(xiàn)下面的令人討厭的錯誤:
數(shù)據(jù)庫中已存在名為 '#T' 的對象。
在上面這段程序里,創(chuàng)建了一個臨時表,它對于動態(tài)批次是可見的。所以可以修改上面的程序為:
SET @sql = N'INSERT INTO #T(cnt) SELECT COUNT(DISTINCT '
+ QUOTENAME(@colname) + N') FROM '
+ QUOTENAME(@schemaname)
+ N'.'
+ QUOTENAME(@tablename)
+ N';';
CREATE TABLE #T(cnt INT);
EXEC(@sql);
SET @cnt = (SELECT cnt FROM #T);
SELECT @cnt;
DROP TABLE #T;
因為EXEC的執(zhí)行是在Create Table之后,所以Insert語句可以移到@sql的定義里。
2 變量的連接
在SS2000里,EXEC優(yōu)于sp_executesql的一點是,它支持輸入的代碼長度要長一些。雖然,從技術(shù)上說后者的
輸入代碼字符串是NTEXT類型,通常希望用一個局部變量來保存它。但是,局部變量是不能聲明成大對象類型的。
所以,實際上sp_executesql的最大支持的字符串長度是Unicode字符串的長度(NVARCHAR,4000個字符)。而
EXEC,則支持常規(guī)的字符串(VARCHAR),即8000個字符。
而且,EXEC支持多個變量的連接,每個變量最大有8000個字符。
不過在SS2005里,變量類型可以是VARCHAR(max),最大為2G。
3 EXEC AT
這是05里的新語法。執(zhí)行遠程主機上的動態(tài)SQL語句
加上 N 代表存入數(shù)據(jù)庫時以 Unicode 格式存儲。
N'string' 表示string是個Unicode字符串
Unicode 字符串的格式與普通字符串相似,但它前面有一個 N 標識符(N 代表 SQL-92 標準中的國際語言 (National Language))。N 前綴必須是大寫字母。例如,'Michél' 是字符串常量而 N'Michél' 則是 Unicode 常量。Unicode 常量被解釋為 Unicode 數(shù)據(jù),并且不使用代碼頁進行計算。Unicode 常量確實有排序規(guī)則,主要用于控制比較和區(qū)分大小寫。為 Unicode 常量指派當(dāng)前數(shù)據(jù)庫的默認排序規(guī)則,除非使用 COLLATE 子句為其指定了排序規(guī)則。Unicode 數(shù)據(jù)中的每個字符都使用兩個字節(jié)進行存儲,而字符數(shù)據(jù)中的每個字符則都使用一個字節(jié)進行存儲。有關(guān)更多信息,請參見使用 Unicode 數(shù)據(jù)。
Unicode 字符串常量支持增強的排序規(guī)則
數(shù)據(jù)庫名是一個標識符,表名也是一個標識符,在SQL SERVER中標識符分為兩類:
標識符有兩類:
常規(guī)標識符
符合標識符的格式規(guī)則。在 Transact-SQL 語句中使用常規(guī)標識符時不用將其分隔。
SELECT *FROM TableXWHERE KeyCol = 124
分隔標識符
包含在雙引號 (") 或者方括號 ([ ]) 內(nèi)。符合標識符格式規(guī)則的標識符可以分隔,也可以不分隔。
SELECT *FROM [TableX] --Delimiter is optional.WHERE [KeyCol] = 124 --Delimiter is optional.
在 Transact-SQL 語句中,對不符合所有標識符規(guī)則的標識符必須進行分隔。
SELECT *FROM [My Table] --Identifier contains a space and uses a reserved keyword.WHERE [order] = 10 --Identifier is a reserved keyword.
常規(guī)標識符和分隔標識符包含的字符數(shù)必須在 1 到 128 之間。對于本地臨時表,標識符最多可以有 116 個字符。
兩者重要的區(qū)別:常規(guī)標識符必須嚴格遵守命名的規(guī)定,而分隔標識符則可以不遵守命名規(guī)定,只要用[],""分隔出來就可以。
標識符格式:
1、標識符必須是統(tǒng)一碼(Unicode)2.0標準中規(guī)定的字符,以及其他一些語言字符。如漢字.
2、標識符后的字符可以是(除條件一)“_”、“@”、“#”、“$”及數(shù)字。
3、標識符不允許是Transact-SQL的保留字。
4、標識符內(nèi)不允許有空格和特殊字符。
另外,某些以特殊符號開頭的標識符在SQL SERVER 中具有特定的含義。
如以“@”開頭的標識符表示這是一個局部變量或是一個函數(shù)的參數(shù);以#開頭的標識符表示這是一個臨時表或是一存儲過程。
以“##”開頭的表示這是一個全局的臨時數(shù)據(jù)庫對象。T
ransact-SQL的全局變量以“@@”開頭。
標識符最多可以容納128個字符。
您可能感興趣的文章:- SqlServer中用exec處理sql字符串中含有變量的小例子
- 解決PHP mysql_query執(zhí)行超時(Fatal error: Maximum execution time …)
- Android之采用execSQL與rawQuery方法完成數(shù)據(jù)的添刪改查操作詳解
- SQLServer:探討EXEC與sp_executesql的區(qū)別詳解
- 安裝sqlserver2000時出現(xiàn)wowexec.exe無反應(yīng)的解決方法
- SQL 中sp_executesql存儲過程的使用幫助
- sqlserver 錯誤602,未能在sysindexes中找到數(shù)據(jù)庫 的解決辦法
- 在Sql Server中調(diào)用外部EXE執(zhí)行程序引發(fā)的問題