最近項目不管查詢報表仍是其餘數據都在和SQL Server數據庫打交道,對於STUFF也有了解,可是發現當下一次再寫SQL語句時我還得查看相關具體用法,說到底仍是沒有徹底理解其原理,因此本節咱們來談談STUFF,Jeff是在項目中哪裏不熟悉,哪裏不會或者哪裏耗時比較多就會去深刻理解和鞏固即便是很基礎的知識,直到徹底不用浪費時間去查閱相關資料,這是個人出發點。數據庫
STUFF字符串函數是將字符串插入到另外一個字符串中。它會刪除開始位置第一個字符串中的指定長度的字符,而後將第二個字符串插入到開始位置的第一個字符串中,語法以下。express
STUFF(<character_expression>,<開始>,<長度>,<character_expression>)
<character_expression>參數是給定的字符串數據,能夠是字符或二進制數據的常量,變量或列。<start>參數是一個整數值,指定開始刪除和插入的位置,能夠是BIGINT類型。若是<開始>或<長度>參數爲負數,則返回NULL字符串。若是<start>參數比第一個<character_expression>長,則返回一個NULL字符串。 <length>參數能夠是BIGINT類型,它是一個整數,指定要刪除的字符數。若是<length>比第一個<character_expression>長,則刪除發生到最後一個<character_expression>中的最後一個字符。函數
DECLARE @FullName VARCHAR(100) DECLARE @Alias VARCHAR(20) SET @FullName = 'Jeffcky Wang' SET @Alias = ' "Superman" ' SELECT STUFF(@FullName, CHARINDEX(' ', @FullName), 1, @Alias) AS [FullName]
如上STUFF函數中的第一個參數咱們給定的是@FullName,第二個是開始的位置,咱們經過CHARINDEX函數找出@FullName以空格隔開的的位置返回,最後由@Alias來代替,結果如圖所示。ui
DECLARE @Time VARCHAR(10) SET @Time = '1030' SELECT STUFF(@Time, 3, 0, ':') AS [HH:MM]
咱們給定的字符串爲@Time即1030,咱們從第3個位置開始,刪除長度爲0,此時則在3前面插入冒號,結果如上圖輸出10:30。spa
DECLARE @CreditCardNumber VARCHAR(20) SET @CreditCardNumber = '370200199408103544' SELECT STUFF(@CreditCardNumber, LEN(@CreditCardNumber) -3, 4, 'XXXX') AS [Output]
如上咱們將身份證經過STUFF將最後四位用XXXX代替。以上是STUFF最基礎的用法。STUFF最多見的用途莫過於結合FOR XML PATH對返回JSON字符串的拼接。首先利用FOR XML PATH則返回XML格式的字符串,咱們將FOR XML PATH添加到查詢的末尾,此時容許咱們將查詢的結果做爲XML元素輸出,元素名稱包含在PATH參數中。。3d
SELECT TOP 5 ',' + Name FROM Production.Product FOR XML PATH ('')
,Adjustable Race,All-Purpose Bike Stand,AWC Logo Cap,BB Ball Bearing,Bearing Ball
此時咱們利用STUFF將上述利用FOR XML PATH生成的字符串中的前置逗號去掉,以下:code
SELECT Name = STUFF(( SELECT TOP 5 ',' + NAME FROM Production.Product FOR XML PATH('') ), 1, 1, '')
好比咱們要查詢各類產品中的產品列表名稱,最後咱們改形成以下:xml
SELECT TOP 5 p2.ProductID, Name = STUFF(( SELECT ',' + NAME FROM Production.Product AS p1 WHERE p1.ProductID = p2.ProductID FOR XML PATH('') ), 1, 1, '') FROM Production.Product AS p2 GROUP BY p2.ProductID
接下來咱們利用STUFF結合FOR XML PATH來拼接JSON字符串,以下:blog
DECLARE @content VARCHAR(MAX) SET @content = (SELECT '['+ STUFF((SELECT TOP 5 ',{"ProductName": "' + ProductName + '","Price": "' + CONVERT(VARCHAR, Price) + '","Quantity": "' + CONVERT(VARCHAR, quantity) + '","Inserton": "' + CONVERT(VARCHAR, Inserton, 105) + '"}' FROM ProductList FOR XML PATH('')), 1, 1,'' ) + ']'[ProductDetail]) PRINT @content
結果如上正確輸出JSON字符串,接下來咱們將如上拼接換行再試試。字符串
DECLARE @content VARCHAR(MAX) SET @content = ( SELECT '[' + STUFF(( SELECT TOP 5 ',{"ProductName": "' + ProductName + '","Price": "' + CONVERT(VARCHAR, Price) + '","Quantity": "' + CONVERT(VARCHAR, quantity) + '","Inserton": "' + CONVERT(VARCHAR, Inserton, 105) + '"}' FROM ProductList FOR XML PATH('') ), 1, 1, '') + ']' [ProductDetail] ) PRINT @content
如上是利用SQL Prompt直接格式化換行,結果依然正確輸出JSON字符串,咱們再來手動換行試試。
DECLARE @content VARCHAR(MAX) SET @content = (SELECT '['+ STUFF((SELECT TOP 5 ', {"ProductName": "' + ProductName + '","Price": "' + CONVERT(VARCHAR, Price) + '","Quantity": "' + CONVERT(VARCHAR, quantity) + '","Inserton": "' + CONVERT(VARCHAR, Inserton, 105) + '"}' FROM ProductList FOR XML PATH('')), 1, 1,'' ) + ']'[ProductDetail]) PRINT @content
結果輸出如上咱們不指望的字符串,主要是由FOR XML PATH形成的,好比咱們利用FOR XML PATH進行以下查詢:
SELECT ' ' FOR XML PATH('')
當咱們利用FOR XML PATH查詢數據時,若是字符串中包含空格時會形成出現以如上錯誤的字符串來填充,因此此時咱們爲了消除這種錯誤格式,咱們將上述繼續添加參數。
SELECT ' ' FOR XML PATH(''),TYPE
此時咱們將上述輸出JSON字符串不錯誤的格式修改爲以下便可:
DECLARE @content VARCHAR(MAX) SET @content = (SELECT '['+ STUFF((SELECT TOP 5 ', {"ProductName": "' + ProductName + '","Price": "' + CONVERT(VARCHAR, Price) + '","Quantity": "' + CONVERT(VARCHAR, quantity) + '","Inserton": "' + CONVERT(VARCHAR, Inserton, 105) + '"}' FROM ProductList FOR XML PATH('') ,TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1,'' ) + ']'[ProductDetail]) PRINT @content
或者咱們對上述輸出的錯誤字符串進行替換,以下:
select t.PK, ltrim(rtrim(replace( (select ' ' + isnull(ti.Column1, '') + ' ' + isnull(ti.Column2, '') from yourTable ti where ti.PK = t.PK for xml path ('')) , ' ', ''))) fruits from yourTable t group by t.PK;
這裏咱們解決了利用STUFF有可能輸出JSON字符串帶有錯誤的字符串的問題,在利用STUFF輸出JSON字符串時只要有一列數據包含NULL,那麼返回的數據則爲空,那麼咱們在對列數據經過ISNULL來進行判斷,好比以下將輸出NULL。
DECLARE @content VARCHAR(MAX) SET @content = (SELECT '['+ STUFF((SELECT TOP 5 ', {"ProductName": "' + NULL + '","Price": "' + CONVERT(VARCHAR, Price) + '","Quantity": "' + CONVERT(VARCHAR, quantity) + '","Inserton": "' + CONVERT(VARCHAR, Inserton, 105) + '"}' FROM ProductList FOR XML PATH('') ,TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1,'' ) + ']'[ProductDetail]) PRINT @content
因此此時咱們必須經過ISNULL來判斷列數據是否爲NULL,修改爲以下形式:
DECLARE @content VARCHAR(MAX) SET @content = (SELECT '['+ STUFF((SELECT TOP 5 ', {"ProductName": "' + ISNULL(ProductName,'') + '","Price": "' + CONVERT(VARCHAR, Price) + '","Quantity": "' + CONVERT(VARCHAR, quantity) + '","Inserton": "' + CONVERT(VARCHAR, Inserton, 105) + '"}' FROM ProductList FOR XML PATH('') ,TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1,'' ) + ']'[ProductDetail]) PRINT @content