我有像
这样的字符串OPEN SYSTEMS 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
我需要通过更改我正在使用的子字符串方式或更改某些逻辑来固定上面的代码。你能告诉我在我的代码中可以改进哪些内容吗?
答案 0 :(得分:1)
如果您经常这样做,我会考虑通过触发器将insert / update / delete上的数据解析为单独的表(比如MY_TABLE_ELEMENTS
),然后从MY_TABLE
中选择SELECT加入{{ 1}}。
例如,您可以使用split函数(拆分“(”,如果我正确理解您的代码),将每个完整的拆分元素存储到MY_TABLE_ELEMENTS中,或者只解析数字部分。
答案 1 :(得分:1)
您可以实现一个实现regex的CLR UDF。
答案 2 :(得分: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)