一、SQL語句直接處理非數字型列的“累加”問題
查詢要求:取出Person表中所有人的FirstName,並以逗號隔開。
可直接通過SELECT @local_variable = expression的形式實現:
1 |
DECLARE @Result varchar(8000) |
3 |
SELECT @Result=@Result + CASE WHEN @Result='' THEN FirstName ELSE ',' + FirstName |
4 |
END FROM Person ORDER BY Id |
5 |
SELECT @Result AS Names |
我們還有一種比較笨拙的方式進行查詢,那就是通過遊標:
02 |
DECLARE @Result varchar(8000) |
03 |
DECLARE @SQL varchar(50) |
04 |
DECLARE c CURSOR FORWARD_ONLY READ_ONLY FOR |
05 |
SELECT FirstName FROM Person ORDER BY Id |
08 |
FETCH next FROM c INTO @SQL |
09 |
WHILE @@fetch_status = 0 |
11 |
SET @Result = CASE WHEN @Result='' |
13 |
ELSE @Result + ',' + @SQL |
15 |
FETCH next FROM c INTO @SQL |
18 |
SELECT @Result AS Names |
大部分SQL查詢我們都會力爭不用遊標,因為不用考慮分配和釋放遊標,可大大節省資料庫資源提升效率。
二、動態SQL語句基礎
在一中,我們已經使用了動態SQL。這裡再總結一下經常使用的動態SQL程式設計基礎。
1、單引號,雙引號
單引號:
1 |
SELECT '''' AS Result --單引號 |
那麼雙引號呢?8個單引號麼?如果是真的8個單引號一起,實際上返回的是3個單引號。真正的雙引號可以”含有“8個單引號,當然必須要像下面這樣加起來:
1 |
SELECT ''''+'''' AS Result --雙引號 |
但是更直接的寫法是下面這樣的:
1 |
SELECT '''''' AS Result --雙引號 |
沒錯,就是6個單引號連寫。
單引號和雙引號也可以搞得這麼煩?這也許正是SQL程式設計不如高階程式語言來得簡單直白的地方。
2、定義變數,給變數賦值
來看一個簡單的SQL語句:
1 |
DECLARE @a varchar(20),@b varchar(20) |
我們通過DECLARE定義變數,通過SET給變數賦值,也可以通過SELECT給變數賦值:
1 |
DECLARE @a varchar(20),@b varchar(20) |
SET和SELECT賦值的區別:據說SELECT 一次性賦值, 比用SET 逐個賦值效率好。
3、EXEC(@sql)
普通的SQL語句,可以直接通過EXEC執行
1 |
EXEC ('SELECT TOP 10 * FROM Person(NOLOCK) ORDER BY Id DESC')--兩邊的括號不可少 |
也可以通過定義變數,執行變數sql,但是必須加上括號:
1 |
DECLARE @Sql varchar(2000) |
2 |
SET @Sql='SELECT TOP 10 * FROM Person(NOLOCK) ORDER BY Id DESC' |
4、Exec sp_executesql
sp_executesql 支援對 Transact-SQL 字串中指定的任何引數的引數值進行替換,但是 EXECUTE 語句不支援。因此,由 sp_executesql 生成的 Transact-SQL 字串比由 EXECUTE 語句所生成的更相似。SQL Server 查詢優化器可能將來自 sp_executesql 的 Transact-SQL 語句與以前所執行的語句的執行計劃相匹配,以節約編譯新的執行計劃的開銷。
對於普通的SQL語句,這個和EXEC直接執行SQL是一樣的:
1 |
EXEC sp_executesql N'SELECT TOP 10 * FROM Person(NOLOCK) ORDER BY Id DESC' --必須加N |
注意,那個大寫的N必須加在要執行的sql語句前面,而且那個N也不是白來的,它還有重要的含義!
如果我們執行的sql語句定義成變數的形式,下面的sql是無法執行的:
1 |
DECLARE @Sql varchar(2000) |
2 |
SET @Sql='SELECT TOP 10 * FROM Person(NOLOCK) ORDER BY Id DESC' |
3 |
EXEC sp_executesql @Sql |
搞怪的是,如果將@sql變數型別由varchar改成nvarchar,就可以執行了:
1 |
DECLARE @Sql nvarchar(2000) |
2 |
SET @Sql='SELECT TOP 10 * FROM Person(NOLOCK) ORDER BY Id DESC' |
3 |
EXEC sp_executesql @Sql |
到這裡哀樂響起,為什麼為什麼?偏偏你要折磨我?下面就來解惑吧:
(1)、EXEC sp_executesql N 這個倒貼過來的N表示後面的sql內容是unicode也是對應nvarchar型別;
(2)、將varchar改成nvarchar才能執行,就是為了執行sql時,將所有引數值轉換為字元或 unicode 並使其成為 Transact-SQL 字串的一部分。
5、將EXEC執行結果放入變數中
比如,我們需要查詢Person表的所有記錄數,可以像下面這樣實現將執行結果放入變數@Num中:
2 |
DECLARE @Num int, @Sql nvarchar(4000) |
3 |
SET @Sql='SELECT @TotalCount=COUNT(0) FROM Person ' |
4 |
EXEC sp_executesql @Sql,N'@TotalCount int output',@Num output |
5 |
SELECT @Num AS TotalCount |
6、兩個型別轉換函式
下面示例將整數(int)轉換成字串(varchar):
4 |
SELECT CONVERT(varchar(50),@input)+' abc' AS result |
6 |
SELECT CAST(@input AS varchar(50))+ ' xyz' AS result |
這兩個平時開發估計經常使用,大家應該不陌生。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16436858/viewspace-681072/,如需轉載,請註明出處,否則將追究法律責任。