替换 SQL 列中不需要的字符串值部分

Replacing unwanted portions of a string value in SQL column

我有一个采用以下格式的 table,其中 COL1 包含一个唯一标识符,COL2 包含一组 phone 个数字,后跟一个标记(<abc><def>) 并用竖线分隔 (|)。每行中的 phone 记录数未知 - 它可能仅包含一个 phone 数字后跟标签或最多 10 个。

Table
----------
COL1 : COL2
----------
ID1 : 1234567890<abc>|4312314124<abc>|1232345133<def>|4131234131<abc>|41234134132<def>

我需要将此数据复制到新的 table 中,结果格式如下,即删除带有标签 <def>.

的字符串的所有部分
    Table
    ----------
    COL1 : COL2
    ----------
    ID1 : 1234567890<abc>,4312314124<abc>,4131234131<abc>

获得最佳性能的最佳方法是什么?我需要程序来转换 table 中包含大约一百万条记录的数据。

我不明白你在 first.but 的问题的答案如果你 sql 服务器是 2016 或 upper.I 认为它具有良好的性能,你可以遵循代码

Insert into table2 (ID1)
SELECT 
    STUFF((SELECT [value] +N',' AS 'data()' FROM STRING_SPLIT(ID1,'|') WHERE [value] LIKE'%<abc>' FOR XML PATH(''),TYPE)
    .value('text()[1]','nvarchar(max)'),1,2,N'') AS ID1 
FROM    
    table1

你的那个字符串可以很容易地转换成一些 XML 基本上使用 replace()。然后可以使用 XQuery 选择具有正确标记的 phone 个数字。作为奖励,这可能适用于任意数量的 phone 个数字。

(我没有得到你的模式,所以我使用我自己的。你自己把它翻译成你的。)

CREATE TABLE elbat
             (nmuloc nvarchar(MAX));

INSERT INTO elbat
            (nmuloc)
            VALUES ('1234567890<abc>|4312314124<abc>|1232345133<def>|4131234131<abc>|41234134132<def>');

WITH
cte AS
(
SELECT convert(xml,
               concat('<phonenumbers><phonenumber number="', 
               replace(replace(substring(nmuloc,
                                         1,
                                         len(nmuloc) - 1),
                               '<',
                               '" tag="'),
                       '>|',
                       '"/><phonenumber number="'),
               '"/></phonenumbers>')) phonenumbers
       FROM elbat
)
SELECT stuff((SELECT ',' + nodes.node.value('concat(./@number, "<", ./@tag, ">")',
                                            'nvarchar(max)')
                     FROM cte
                          CROSS APPLY phonenumbers.nodes('/phonenumbers/phonenumber[@tag="abc"]') nodes(node)
                     FOR XML PATH(''),
                             TYPE).value('(.)[1]',
                                         'nvarchar(max)'),
             1,
             1,
             '');

但是,当您使用它时,您真的应该考虑规范化您的模式,并且不要再在字符串中使用定界符分隔列表以及非原子序数和标记组合!

SQL Fiddle

如果性能很重要,那么我建议 delimitedSplit8k_Lead。您可以只使用管道作为分隔符来拆分字符串,然后排除不以结尾的项目(标记)。

DECLARE @table TABLE (COL1 VARCHAR(10), COL2 VARCHAR(1000));
INSERT @table
VALUES
('ID1','1234567890<abc>|4312314124<abc>|1232345133<def>|4131234131<abc>|41234134132<def>'),
('ID2','2662314129<abc>|7868845133<abc>|6831234131<abc>|41234139999<xxx>|1234567999<abc>')

SELECT t.COL1, ds.item
FROM @table t
CROSS APPLY dbo.DelimitedSplit8K_LEAD(t.COL2,'|') ds
WHERE ds.Item LIKE '%<abc>';

Returns

COL1       item
---------- -----------------
ID1        1234567890<abc>
ID1        4312314124<abc>
ID1        4131234131<abc>
ID2        2662314129<abc>
ID2        7868845133<abc>
ID2        6831234131<abc>
ID2        1234567999<abc>

然后使用 XML PATH 进行连接,如下所示:

DECLARE @table TABLE (COL1 VARCHAR(10), COL2 VARCHAR(1000));
INSERT @table
VALUES
('ID1','1234567890<abc>|4312314124<abc>|1232345133<def>|4131234131<abc>|41234134132<def>'),
('ID2','2662314129<abc>|7868845133<abc>|6831234131<abc>|41234139999<xxx>|1234567999<abc>')

SELECT t.COL1, stripBadNumbers.newString
FROM @table t
CROSS APPLY 
(VALUES((
  SELECT ds.item
  FROM dbo.DelimitedSplit8K_LEAD(t.COL2,'|') ds
  WHERE ds.Item LIKE '%<abc>'
  FOR XML PATH(''), TYPE
).value('.', 'varchar(1000)'))) stripBadNumbers(newString);

Returns:

COL1       newString
---------- -------------------------------------------------------------------
ID1        1234567890<abc>4312314124<abc>4131234131<abc>
ID2        2662314129<abc>7868845133<abc>6831234131<abc>1234567999<abc>