2011-07-27 27 views
1

我有一個SQLServer2008 R2存儲過程,它包含從分隔字符串中解析出整數的算法。從T-SQL分隔字符串解析整數值的更好方法

這裏的SQL代碼,我通過了分隔字符串循環,並提取可能的分隔字符串中存在的任何號碼做出的一個例子:

-- Create a delimited list for testing 
DECLARE @NumericList nvarchar(MAX) = N'1, 33,44 ,55, foo ,666,77 77,8,bar,9,10' 

-- Declare the delimiter 
DECLARE @ListDelimiter VARCHAR(1) = ',' 

-- Remove white space from the list 
SET @NumericList = REPLACE(@NumericList, ' ',''); 

-- Var that will hold the value of the delimited item during the while-loop 
DECLARE @NumberInScope VARCHAR(MAX) 

WHILE(LEN(@NumericList) > 0) 
BEGIN 
    -- Get the value to the left of the first delimiter. 
    IF(CHARINDEX(@ListDelimiter, @NumericList) > 0) 
     SET @NumberInScope = LEFT(@NumericList, CHARINDEX(@ListDelimiter, @NumericList)) 
    ELSE 
     SET @NumberInScope = @NumericList 

    -- Remove the @NumberInScope value from the @NumericList 
    SET @NumericList = RIGHT(@NumericList, LEN(@NumericList) - LEN(@NumberInScope)) 

    -- Remove the delimiter from the @NumberInScope 
    SET @NumberInScope = REPLACE(@NumberInScope,@ListDelimiter,'') 

    -- Print only the integer values 
    IF(ISNUMERIC(@NumberInScope) = 1) 
    BEGIN 
     PRINT @NumberInScope 
    END 
END 

上面的代碼工作正常,但檢查代碼後在我看來,做同樣的事情必須有一種更簡潔的方式。換句話說,是否有任何字符串函數(或者任何新的R2函數,可能),我忽略了我可以實現的那樣會縮小代碼,並且希望更容易閱讀?

+0

退房[阿龍貝特朗的博客文章(http://sqlblog.com/blogs/aaron_bertrand/archive/2010/07/07/splitting-a-list-of-integers -another-roundup.aspx)解析整數值列表的各種實現。 – etliens

回答

2

下面是代碼,您也可以創建一個「分裂」的功能和使用

DECLARE @NumericList nvarchar(max) = N'1, 33,44 ,55, foo ,666,77 77,8,bar,9,10' 

;WITH cte as (
SELECT CAST(1 as bigint) p1, CHARINDEX(',', @NumericList+',') p2, 
CAST(null as Nvarchar(max)) NumberInScope 
UNION ALL 
SELECT p2 + 1, CHARINDEX(',',@NumericList+',', p2 + 1), 
SUBSTRING(@NumericList, p1, p2-p1) 
FROM cte WHERE p2>0 
) 
SELECT NumberInScope from cte WHERE isnumeric(NumberInScope) > 0 
OPTION (MAXRECURSION 0) 
+0

雖然我需要一些時間來弄清楚發生了什麼,但這是一個非常漂亮的解決方案。我有很多問題,但我會堅持一個:「WITH WITH cte as ...」的分號的目的是什麼?我從來沒有在T-SQL中使用(或看過)分號。 – Jed

+1

@Jed您必須使用;否則SQL會失敗,除非在WITH之前沒有代碼。它是從早期的代碼中分離出來的。我在cte語句中做的是對nvarchar的recusive分裂。 –

+1

根據BOL的說法:當一個CTE用於批處理語句中時,其前面的語句必須跟一個分號。 – etliens