0

我有像这样的字符串

开放系统 SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG)

在我的 GROUPS 列下的数据库中。

我想要做的是从该字符串中提取 2222 。我正在使用的代码是这样的。

    SELECT 
        SUBSTRING(GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS,0)+1)+1)+1, 4 ) AS GroupNo

    FROM MY_TABLE

    WHERE

    ISNUMERIC(SUBSTRING(GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS,0)+1)+1)+1, 4 )) = 1

我需要通过更改我使用的子字符串方式或更改一些逻辑来固定上面的代码。你能告诉我我的代码有哪些可以改进的地方吗?

4

3 回答 3

1

您可以实现一个实现regex的 CLR UDF 。

于 2010-01-15T08:31:27.417 回答
1

如果您经常这样做,我会考虑通过触发器将插入/更新/删除上的数据解析到单独的表中(例如MY_TABLE_ELEMENTS),然后 SELECT from MY_TABLEjoin to MY_TABLE_ELEMENTS.

例如,您可以使用拆分函数(拆分“(”,如果我正确理解您的代码),将每个整个拆分元素存储到 MY_TABLE_ELEMENTS 中,或者仅解析数字部分。

于 2010-01-15T08:29:06.267 回答
1

基于集合的实现。

这比单行代码的性能要差,但对于较大的结果集应该可以更好地扩展,特别是如果您将生成动态数字表的 CTE 替换为静态数字表。

DECLARE @t TABLE
(groups VARCHAR(250))

INSERT @t
VALUES ('OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG)')

INSERT @t
VALUES ('OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(3333)/BTVY(4444)/ACSVTYSAG)')

DECLARE @chr_delim CHAR(1)
SET @chr_delim = '('

-- nums_cte generates a dynamic numbers table
-- replace this with your own numbers table if you have one
;WITH nums_cte 
AS 
( 
        SELECT 1 AS n 
        UNION ALL 
        SELECT n+1 FROM nums_cte 
        WHERE n < 250
) 
,splitCTE    
AS
(
        SELECT  SUBSTRING(s,n,CHARINDEX(@chr_delim, s + @chr_delim,n) -n) AS ELEMENT
                ,s
                ,ROW_NUMBER() OVER (PARTITION BY s
                                    ORDER BY n
                                   ) AS rn
        FROM (SELECT groups AS s FROM @t) AS D
        JOIN nums_cte
        ON n <= LEN(s)
        AND SUBSTRING(@chr_delim + s,n,1) = @chr_delim 
)
SELECT LEFT(ELEMENT,4) AS GroupNo
       ,s AS originalString
FROM splitCTE
WHERE rn = 4
AND   ISNUMERIC(LEFT(ELEMENT,4)) = 1
OPTION (MAXRECURSION 0)
于 2010-01-15T09:41:38.617 回答