昨天遇到一個SQL Server的問題:須要寫一個儲存過程來處理幾個表中的數據,最後問題出在我想將一個表的一個列的多行內容拼接成一行sql
好比表中有兩列數據 :函數
ep_classes ep_name學習
AAA 企業1spa
AAA 企業2code
AAA 企業3xml
BBB 企業4blog
BBB 企業5字符串
我想把這個表變成以下格式:數學
ep_classes ep_name
class
AAA 企業1,企業2,企業3
BBB 企業4,企業5
原先的表名爲:ep_detail。
實現代碼以下:
select ep_classes, ep_name = (stuff((select ‘,’ + ep_name from ep_detail where ep_classes = a.ep_classes for xml path(」)),1,1,」)) from ep_detail a group by ep_classes
這裏使用了SQL Server 2005版本之後加入的stuff以及for xml path,先說下在上面這句sql中的做用,而後再詳細的說明一下這兩個的用法。
for xml path(」)
這句是把獲得的內容以XML的形式顯示。
stuff((select ‘,’ + ep_name from ep_detail where ep_classes = a.ep_classes for xml path(」)),1,1,」)
這句是把拼接的內容的第一個「,」去掉
好了,如今開始具體說一下用法:
①stuff:
一、做用
stuff(param1, startIndex, length, param2)
將param1中自startIndex(SQL中都是從1開始,而非0)起,刪除length個字符,而後用param2替換刪掉的字符。
二、參數
param1
一個字符數據表達式。param1能夠是常量、變量,也能夠是字符列或二進制數據列。
startIndex
一個整數值,指定刪除和插入的開始位置。若是 startIndex或 length 爲負,則返回空字符串。若是startIndex比param1長,則返回空字符串。startIndex能夠是 bigint 類型。
length
一個整數,指定要刪除的字符數。若是 length 比param1長,則最多刪除到param1 中的最後一個字符。length 能夠是 bigint 類型。
三、返回類型
若是param1是受支持的字符數據類型,則返回字符數據。若是param1是一個受支持的 binary 數據類型,則返回二進制數據。
四、備註
若是結果值大於返回類型支持的最大值,則產生錯誤。
eg:
select STUFF(‘abcdefg’,1,0,‘1234’) –結果爲’1234abcdefg’ select STUFF(‘abcdefg’,1,1,‘1234’) –結果爲’1234bcdefg’ select STUFF(‘abcdefg’,2,1,‘1234’) –結果爲’a1234cdefg’ select STUFF(‘abcdefg’,2,2,‘1234’) –結果爲’a1234defg’
經過以上4個小例子,應該能明白stuff的用法了。
②for xml path:
for xml path有的人可能知道有的人可能不知道,其實它就是將查詢結果集以XML形式展示,有了它咱們能夠簡化咱們的查詢語句實現一些之前可能須要藉助函數活存儲過程來完成的工做。那麼以一個實例爲主.
咱們仍是經過列子引入:
假設有個表存放着學生的選課狀況(stu_courses):
接下來咱們來看應用FOR XML PATH的查詢結果語句以下:
select stu_name,stu_course from stu_courses for xml path;
結果以下:
<row> <stu_name>張三</stu_name> <stu_course>數學</stu_course> </row> <row> <stu_name>張三</stu_name> <stu_course>語文</stu_course> </row> <row> <stu_name>張三</stu_name> <stu_course>英語</stu_course> </row> <row> <stu_name>李四</stu_name> <stu_course>數學</stu_course> </row> <row> <stu_name>李四</stu_name> <stu_course>語文</stu_course> </row>
由此能夠看出 FOR XML PATH 能夠將查詢結果根據行輸出成XML各式!並且咱們還能夠改變XML行節點的名稱,代碼以下:
select stu_name,stu_course from stu_courses for xml path(‘course’);
看顯示結果,原來的行節點<row> 變成了咱們在PATH後面括號()中自定義的名稱<course>:
<course> <stu_name>張三</stu_name> <stu_course>數學</stu_course> </course> <course> <stu_name>張三</stu_name> <stu_course>語文</stu_course> </course> <course> <stu_name>張三</stu_name> <stu_course>英語</stu_course> </course> <course> <stu_name>李四</stu_name> <stu_course>數學</stu_course> </course> <course> <stu_name>李四</stu_name> <stu_course>語文</stu_course> </course>
其實咱們還能夠改變列節點,還記的給列起別名的關鍵字AS嗎?就是用它!代碼以下:
select stu_name as MyName,stu_course as MyCourse from stu_courses for xml path(‘course’);
<course> <MyName>張三</MyName> <MyCourse>數學</MyCourse> </course> <course> <MyName>張三</MyName> <MyCourse>語文</MyCourse> </course> <course> <MyName>張三</MyName> <MyCourse>英語</MyCourse> </course> <course> <MyName>李四</MyName> <MyCourse>數學</MyCourse> </course> <course> <MyName>李四</MyName> <MyCourse>語文</MyCourse> </course>
咱們還能夠構建咱們喜歡的輸出方式,看代碼:
select ‘[‘+stu_name+‘,’+stu_course+‘]’ from stu_courses for xml path(」);
顯示結果:
[張三,數學][張三,語文][張三,英語][李四,數學][李四,語文]
好了,經過上面的說明,估計你們就能夠明白開始問題中的sql語句了!
固然,關於開始的問題還有其餘的解決辦法,好比:遊標、自定義函數等等,那些之後再作補充吧。
以上僅做拋磚引玉之用,若是有問題或者其餘的簡便方法,但願提出你們共同討論學習!