一、背景
當我想通過 select 語句將查詢內容拼接成字符串輸出時出現這種情況。
select U_ID+U_NAME from MES_USER
消息 245,級別 16,狀態 1,第 1 行
在將 varchar 值 '小白' 轉換成數據類型 int 時失敗。
用+號直接拼接的肯定不行,那是在編程語言中的做法。
二、問題解決
(1)問題重現
select 1+'--Test--'
--> 在將 varchar 值 '--Test--' 轉換成數據類型 int 時失敗。
(2)解決方案
方案一:cast 函數
select CAST(1 as varchar)+ '--Test--'
--> '1--Test--'
方案二:convert 函數
在 sql 語句中用 cast 或 convert 函數進行強轉,轉型成功後即可拼接
select CONVERT(varchar,1)+ '--Test--'
--> '1--Test--'
方案三:RTRIM()/ LTRIM()字符串函數
select RTRIM(U_ID)+U_NAME from MES_USER
select LTRIM(U_ID)+U_NAME from MES_USER
這裏使用了SQL SERVER字符串函數LTRIM() / RTRIM(),分別爲去除字符串左邊多餘的空格函數和去除字符串右邊多餘的空格函數,此爲一對函數。在去掉空格時會將其中類型強轉成字符串類型。
方案四:(重點來了!)
select (STUFF((select ','+ RTRIM(U_ID) + U_NAME from MES_USER for xml path ('')),1,1,''))
這個 sql 是將所有查詢內容拼接成一整串字符串,並用逗號隔開,稍微複雜了一點點,涉及到三個函數,不過不急,待我慢慢道來……
函數一:字符串函數LTRIM()/RTRIM()
這個上面說過了,不再複述。
函數二:for xml path(param)--將查詢結果以xml格式輸出
(1)當 path 後面沒有參數時,每行數據被默認 <row> 標籤包裹,每行列數據被被其列名標籤包裹。例:
select U_ID,U_NAME from MES_USER for xml path
--結果:
<row>
<U_ID>1</U_ID>
<U_NAME>小白</U_NAME>
</row>
<row>
<U_ID>2</U_ID>
<U_NAME>小黑</U_NAME>
</row>
<row>
<U_ID>3</U_ID>
<U_NAME>大黑</U_NAME>
</row>
(2) - 每行數據最外面包裹的標籤由path的參數控制(沒有參數時,默認爲row),所以要去掉則可以直接給一個空字符串作爲path的參數。
- 每行列數據所被直接包裹的標籤由查詢結果的列名控制,要去掉只需要保證查詢出來的列沒有列名就可以了(保證沒有列名最簡單的方法是給每個字段加一個空字符串)。例:
select U_ID+'',U_NAME+'' from MES_USER for xml path('')
--結果
1小白2小黑3大黑
函數三:stuff函數
格式:stuff(character_expression, start, length, replaceWith_expression)
刪除原字符串(character_expression)指定起始位置(start)指定長度(length)的字符,並在該位置插入代替的字符(replaceWith_expression)
select (STUFF((select ','+ RTRIM(U_ID) + U_NAME from MES_USER for xml path ('')),1,1,''))
這裏的意思就是將第一個逗號用空字符替換掉。
小提示:這裏查出來的結果可以放到另一個 select 的條件 IN 裏面,特別方便,練熟之後就不用老是一個個去添加逗號了。
三、補充
將小數返回成百分數的格式輸出。
(1)不保留小數位
select cast(cast(0.888876*100 as numeric(3,0)) as varchar(10)) +'%'
--> 89%
(2)保留小數位
select cast(cast(0.888876*100 as numeric(5,2)) as varchar(10)) +'%'
--> 88.89%