在SQL Server中找到模式的终点

时间:2019-02-20 08:29:49

标签: sql sql-server string tsql

一列中有一个逗号分隔的字符串,看起来像

test=1,value=2.2,system=321

我想从字符串中提取值。我可以使用select PatIndex('%value=%',columnName)然后使用left,但这只能找到patindex的开头。

如何识别模式结束值=%,以便我们可以提取出该值?

5 个答案:

答案 0 :(得分:2)

SUBSTRING和您的CHARINDEX绑一些PATHINDEX

DECLARE @text VARCHAR(100) = 'test=1,value=2.21954,system=321'

SELECT
    Original = @text,
    Parsed = SUBSTRING(                                     -- Get a portion of the original value
                @text,
                PATINDEX('%value=%',@text) + 6,             -- ... starting from the 'value=' (without the 'value=')
                -1 + CHARINDEX(                             -- ... and get as many characters until the first comma
                    ',',
                    SUBSTRING(                              -- ... (find the comma starting from the 'value=' onwards)
                        @text,
                        PATINDEX('%value=%',@text) + 6,
                        100)))

结果:

Original                        Parsed
test=1,value=2.2,system=321     2.2

请注意,如果CHARINDEX之后没有逗号,则value=将失败。您可以使用WHERE进行过滤。

我强烈建议您将已分割的值存储在适当的表上,这样就不必处理字符串噩梦了。

答案 1 :(得分:1)

您可以使用CHARINDEX作为起始位置来查找模式之后的第一个逗号 CROSS APPLY用于使查询更易于阅读:

WITH tests(str) AS (
    SELECT 'test=1,value=2.2,system=321'
)
SELECT str, substring(str, pos1, pos2 - pos1) AS match
FROM tests
CROSS APPLY (SELECT PATINDEX('%value=%', str) + 6) AS ca1(pos1)
CROSS APPLY (SELECT CHARINDEX(',', str, pos1 + 1)) AS ca2(pos2)
-- 2.2

答案 2 :(得分:1)

首先,如果要查询非规范化数据,则不要使用这种方法存储非规范化数据。 SQL语言不擅长字符串操作。解析和拆分字符串也不能利用索引,这意味着任何试图查找例如引用system 321的所有记录的查询都必须扫描并解析所有行。

SQL Server 2016和JSON

SQL Server 2016添加了对JSON和STRING_SPLIT函数的支持。早期版本已经提供了XML类型。最好将复杂值存储为JSON或XML,而不要尝试解析字符串。

一种选择是将字符串转换为JSON对象并检索value的内容,例如:

DECLARE @text VARCHAR(100) = 'test=1,value=2.2,system=321'

select json_value('{"' + replace(replace(@text,',','","'),'=','":"') + '"}','$.value')

这将返回2.2

替换项将原始字符串转换为

{"test":"1","value":"2.2","system":"321"}

JSON_VALUE(@json,'$.')将返回该对象的value属性

SQL Server的早期版本

在早期的SQL Server版本中,您可以通过相同的方式将该字符串转换为XML元素并使用XQuery:

DECLARE @text VARCHAR(100) = 'test=1,value=2.2,system=321';

declare @xml varchar(100)='<r ' + replace(replace(@text,',','" '),'=',' ="') + '" />';
select @xml
select cast(@xml as xml).value('(/r[1]/@value)','varchar(20)')

在这种情况下,@xml包含:

<r test ="1" value ="2.2" system ="321" />

查询结果为2.2

答案 3 :(得分:0)

您可以尝试以下操作。

DECLARE @xml AS XML 
SELECT @xml = Cast(( '<X>' + Replace(txt, ',', '</X><X>') + '</X>' ) AS XML) 
FROM   (VALUES ('test=1,value=2.2,system=321')) v(txt) 

SELECT LEFT(value, Charindex('=', value) - 1)           AS LeftPart, 
       RIGHT(value, Charindex('=', Reverse(value)) - 1) AS RightPart 
FROM   (SELECT n.value('.', 'varchar(100)') AS value 
        FROM   @xml.nodes('X') AS T(n))T 

Online Demo

输出

+----------+-----------+
| LeftPart | RightPart |
+----------+-----------+
| test     | 1         |
+----------+-----------+
| value    | 2.2       |
+----------+-----------+
| system   | 321       |
+----------+-----------+

答案 4 :(得分:0)

如果您使用的是SQL Server(2016或更高版本),则可以尝试以下查询

SELECT RIGHT(Value,CHARINDEX('=',REVERSE(Value))-1) FROM YourTableName
CROSS APPLY STRING_SPLIT ( ColumnName , ',' )  
WHERE Value Like 'Value=%'