Sql server 如何将逗号分隔的字符串解析为单独的行,但忽略某些值的逗号

Sql server 如何将逗号分隔的字符串解析为单独的行,但忽略某些值的逗号,sql-server,Sql Server,我们有一个逗号分隔的字符串 "col1=xyz,col2=mno,col3=ABC,ZZZ,col4=complete" 因此,期望的结果需要是: col1 xyz col2 mno col3 ABC,ZZZ col4 complete 当我试着解析这段代码时,col4会被拆分,因为它有一个逗号 col1 xyz col2 mno **col3 ABC col4 ZZZ** col4 complete 使用SQL将其转化为所需结果的最佳方法是什么?简单的回答是:你不能。 答案很长:你可以,

我们有一个逗号分隔的字符串

"col1=xyz,col2=mno,col3=ABC,ZZZ,col4=complete"
因此,期望的结果需要是:

col1 xyz
col2 mno
col3 ABC,ZZZ
col4 complete
当我试着解析这段代码时,col4会被拆分,因为它有一个逗号

col1 xyz
col2 mno
**col3 ABC
col4 ZZZ**
col4 complete

使用SQL将其转化为所需结果的最佳方法是什么?

简单的回答是:你不能。 答案很长:你可以,如果你选择一个不同的分隔符,它不会出现在你的字符串中-分号或美元符号怎么样?或者2定义一个转义字符,这意味着后面的字符应该以与通常不同的方式进行解析,但我不确定这在您的上下文中是否可行,或者3停止使用CSV并使用固定宽度字段,例如:field1始终是10个字符,等等,然后不需要分隔符

Declare @YourTable table (ID int,SomeList varchar(max)) 
Insert Into @YourTable values
(1,'col1=xyz,col2=mno,col3=ABC,ZZZ,col4=complete'),
(2,'emp_id="123",emp_status="New Hire",emp_name="Smith, John A"')

;with cte as (
      Select A.ID,B.*
      From  @YourTable A
      Cross Apply [dbo].[udf-Str-Parse](Replace(A.SomeList,' ','|'),',') B
)
Select A.ID
      ,Col_Name = left(A.RetVal,charindex('=',A.RetVal)-1)
      ,Value    = replace(substring(replace(A.RetVal + case when charIndex('=',B.RetVal)>0 then '' else ','+B.RetVal end,'|',' '),charindex('=',A.RetVal)+1,len(B.RetVal)+len(A.RetVal)),'"','')
 From  cte A
 Left  Join cte B on A.ID=B.ID and A.RetSeq=B.RetSeq-1 
 Where B.RetVal is not null and charIndex('=',A.RetVal)>0
 Order By ID,A.RetSeq
返回

如果需要的话,UDF


你们对col的数量有限制吗?。字符串是如何生成的。在使用不同的分隔符生成字符串时,最好进行修复。等号左侧的值是否始终具有已知的格式或前缀?如果它们总是以col开头,那么读到其中一个后跟等号,把它从末尾切掉,剩下的都是前一行的值或我让它工作的值,我还有另一个类似的逗号分隔字符串,所以当我在同一个查询中第二次尝试交叉应用时,我相信我得到的是双精度counts@SQLUser需要查看您的dataSelect A.ID,Col_Name=leftB.RetVal,charindex'=',B.RetVal-1,Value=ReplaceSubstringB.RetVal,charindex'=',B.RetVal+1,LenB.RetVal',,Col_Name2=leftC.RetVal,charindex'=',C.RetVal-1,Value2=ReplaceSubstringC.RetVal,charindex'=',C.RetVal+1,LenC.RetVal',从@YourTable交叉应用选择A.SomeList B交叉应用选择A.SomeList2 CSo,我有两个以逗号分隔的大列,我需要执行相同的步骤。所以我尝试了两次交叉应用,我相信我得到了一个双计数字符串\u New\u Value=emp\u id=123,emp\u status=Full Time,'emp\u name='Smith,John a String\u Value=emp\u id=123,emp\u status=New Hire,emp\u name=Smith,John a so,我们需要将这两列解析为各自的列名和值,因此,我们需要将4个新列String_to_Value解析为:String_to_Column_Name显示列名String_to_Value显示值同样,String_Old_Value将解析为Likewise,String\u Old\u Value将被解析为String\u Old\u Column\u Name解析列名String\u Old\u Value解析Value 1,'col1=xyz,col2=mno,col3=ABC,ZZZ,col4=complete',2,'emp\u id=123,emp\u status=New Hire,emp\u Name=Smith,John A,emp\u salary=2000'不会拆分emp\u薪资…它就是看不到
ID  Col_Name    Value
1   col1        xyz
1   col2        mno
1   col3        ABC,ZZZ
2   emp_id      123
2   emp_status  New Hire
2   emp_name    Smith, John A
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table 
As
Return (  
    Select RetSeq = Row_Number() over (Order By (Select null))
          ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
    From  (Select x = Cast('<x>'+ replace((Select @String as [*] For XML Path('')),@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
--Select * from [dbo].[udf-Str-Parse]('this,is,<test>,for,< & >',',')