多年前,我也有寫博客,那時是寫一些個人生活上的隨筆,從沒想過寫跟自己工作相關的IT博客。因為網上牛人多,自己才疏學淺,所以一直在做“潛水員”,盡管自己連游泳都不會!但是我在博客園學到了許多,加上博客園簡明的風格也是我喜歡的,時間長了,我也想分享一些關于IT技術方面的經驗心得,也算是對自己在工作上的一些總結吧。不求有功,但求無過。如果您有更好的建議或意見,歡迎與我交流。好了,閑話休提,進入主題。在數據庫編程中,有時會遇到把字符串,按一定規則進行分割,比如“a,b,c,1,2,3”這樣的以逗號為分隔符的字符串,需要把分割出來,分割后單獨變行一行記錄。首先想到的是使用替換函數把分隔符去掉。于是有了:
1 IF (OBJECT_ID(N'Tempdb..##T1') IS NOT NULL) 2 BEGIN 3 DROP TABLE ##T1 4 END 5 GO 6 7 DECLARE @string NVARCHAR(MAX) 8 SET @string=N'123,abc,456,AAA,DDD' 9 SET @string=N'SELECT * INTO ##T1 FROM (SELECT ''' + REPLACE(@string,',',''' AS result UNION ALL SELECT ''') + ''') a' 10 EXEC(@string)11 12 SELECT * FROM ##T113 14 GO
該方法拼接SQL語句,簡單巧妙,但有不足。(1)拼接的SQL不夠直觀,較難編寫;(2)如果分隔符是半角的英文單引號的話,需要再作處理;(3)某些情況下,如果字符串有中文等非英文字符,會顯示亂碼;(4)由于拼接的SQL,如果要分割的字符串很長很長,那么拼接的SQL可能會過長,而不能被執行。所以這種方法只能作簡單的替換或開拓思維之用。方法2(推薦):
1 IF OBJECT_ID(N'fn_split_with_rowno') IS NOT NULL 2 BEGIN 3 DROP FUNCTION fn_split_with_rowno 4 END 5 6 GO 7 8 CREATE FUNCTION fn_split_with_rowno 9 (10 @str NVARCHAR(MAX)11 ,@split NVARCHAR(20) = ','12 )13 RETURNS @t TABLE(row_no INT ,col NVARCHAR(500))14 AS15 BEGIN16 DECLARE @i INT17 SET @i = 018 WHILE (CHARINDEX(@split ,@str) <> 0)19 BEGIN20 INSERT @t (row_no,col)21 VALUES(@i + 1,SUBSTRING(@str ,1 ,CHARINDEX(@split ,@str) -1)) 22 SET @str = STUFF(@str ,1 ,CHARINDEX(@split ,@str) + LEN(@split) -1 ,'')23 SET @i = @i + 1 24 END 25 IF (@str <> '')26 INSERT @t (row_no,col)27 VALUES(@i + 1 ,@str)28 29 RETURN30 END31 32 GO
封裝成函數,方便調用,并且不會出現方法1中的問題。調用函數:
1 SELECT * FROM fn_split_with_rowno(N'123,abc,456,AAA,DDD,博客園',',')
執行結果:
方法3(來自網絡):
1 DECLARE @string NVARCHAR(MAX) 2 SET @string = N'123,abc,456,AAA,DDD,博客園' 3 SELECT REPLACE(REVERSE((LEFT(s ,CHARINDEX(',' ,s)))) ,',' ,'') AS result 4 FROM ( 5 SELECT r,REVERSE(LEFT(@string ,r)) + ',' AS s 6 FROM ( 7 SELECT ( 8 SELECT COUNT(*) 9 FROM sys.objects10 WHERE NAME <= t.name11 ) AS r12 FROM sys.objects AS t13 ) a14 WHERE r <= LEN(@string) AND LEFT(@string + ',' ,r + 1) LIKE '%,'15 ) t16 ORDER BY r
方法4(來自網絡):
1 DECLARE @string NVARCHAR(MAX) 2 SET @string = N'123,abc,456,AAA,DDD' 3 4 DECLARE @idoc INT; 5 DECLARE @doc xml; 6 SET @doc = CAST('<Root><item><S>' + REPLACE(@string ,',' ,'</S></item><item><S>') + '</S></item></Root>' AS XML) 7 8 EXEC sp_xml_PReparedocument @Idoc OUTPUT,@doc 9 10 SELECT * FROM OPENXML(@Idoc ,'/Root/item' ,2) WITH ([S] VARCHAR(10)) 11 12 GO
后面兩種方法也是過于復雜,并且也有不足。
新聞熱點
疑難解答