从长字符串文本中拆分数据,然后更新每个数据

时间:2018-08-23 10:23:46

标签: sql-server tsql

我正在尝试在ms sql数据库中创建一个有点复杂的存储过程。我的主要重点是输入长字符串文本,然后按字符分割数据并在匹配的地方更新该数据。详细信息:DataString是输入的长文本字符串,其中包含类似于下面示例的值。
'-'是数据类型名称与其值之间的分隔符
','是两种不同类型的值之间的分隔符
':'是两组数据之间的分隔符,每组数据之间用:分开
现在,您能告诉我如何从长字符串中获取每个数据并将其插入匹配的位置吗?提出问题,是否仍然需要了解一些内容。预先感谢

长文本字符串的示例:

ASIN-NsQf8,type-0,Price-7,IsPrime-1:ASIN-fD5tsQ,type-1,Price-13,IsPrime-0:ASIN-tvQtsu,type-1,Price-14,IsPrime-1

未完成的SQL代码:

CREATE PROCEDURE dbo.lk_UpdateMatchingDataOfThirdparty 
@DataString VARCHAR(MAX)
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE ThirdPartyData SET Price = @value_get_from_string, IsPrime = @value_get_from_string, DateChecked = GETDATE()
    WHERE ASIN = '@value_get_from_string' AND type = '@value_get_from_string';
END
GO

1 个答案:

答案 0 :(得分:1)

不幸的是string_split()不返回序列号。因此,如果您对替代的拆分/解析功能也很满意,那么该功能也很有效。

注意:我对try_convert()部分进行了假设

示例

Declare @DataString varchar(max) = 'ASIN-NsQf8,type-0,Price-7,IsPrime-1:ASIN-fD5tsQ,type-1,Price-13,IsPrime-0:ASIN-tvQtsu,type-1,Price-14,IsPrime-1'

UPDATE A 
   SET Price       = B.Price
     , IsPrime     = B.IsPrime
     , DateChecked = GETDATE()
 From  ThirdPartyData A
 Join  (
        Select [ASIN]   =replace(max(case when B.RetVal Like 'ASIN-%' then B.RetVal end),'ASIN-','')
              ,[Type]   =try_convert(int,replace(max(case when B.RetVal Like 'type-%' then B.RetVal end),'type-',''))
              ,[Price]  =try_convert(money,replace(max(case when B.RetVal Like 'price-%' then B.RetVal end),'price-',''))
              ,[IsPrime]=try_convert(bit,replace(max(case when B.RetVal Like 'IsPrime-%' then B.RetVal end),'IsPrime-',''))
         From  [dbo].[tvf-Str-Parse](@DataString,':') A
         Cross Apply [dbo].[tvf-Str-Parse](A.RetVal,',') B
         Group By A.RetSeq
       ) B 
   on  A.[ASIN]=B.[ASIN] and A.[Type]=B.[Type]

如果有助于可视化,则子查询返回

ASIN    Type    Price   IsPrime
tvQtsu  1       14.00   1
NsQf8   0       7.00    1
fD5tsQ  1       13.00   0

感兴趣的TVF

CREATE FUNCTION [dbo].[tvf-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 replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
    Cross Apply x.nodes('x') AS B(i)
);
  

编辑:如果您想采用2016+ string_split()方法

Select [ASIN]   =replace(max(case when Value Like 'ASIN-%' then Value end),'ASIN-','')
      ,[Type]   =try_convert(int,replace(max(case when Value Like 'type-%' then Value end),'type-',''))
      ,[Price]  =try_convert(money,replace(max(case when Value Like 'price-%' then Value end),'price-',''))
      ,[IsPrime]=try_convert(bit,replace(max(case when Value Like 'IsPrime-%' then Value end),'IsPrime-',''))
 From (
       Select A.RN
             ,B.*
        From ( Select RN=Row_Number() over (Order by (select null)),* from string_split(@DataString,':') ) A
        Cross Apply string_split(A.Value,',') B
      ) A
 Group By RN