簡體   English   中英

更新SQL Server中分隔符之間包含的一部分字符串

[英]Update part of a string included between delimiters in SQL Server

我必須更新文本列,該文本列是由|分隔的字符串列表。 我想用空文本替換第二個字符串。

列值示例:

TD_DM_U100|BK_U100|TL_DM_U100||||
TD_DM_U200|BK_U200|TL_DM_L100||SOME TEXT||
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT|

更新后的結果(刪除第二個字符串)

TD_DM_U100||TL_DM_U100||||
TD_DM_U200||TL_DM_L100||SOME TEXT||
TD_DM_U300||TL_DM_L100||SOME TEXT|MORE TEXT|

您可以使用charindex()substring()函數的貢獻進行更新

update tab
   set col = replace(col,substring(col,charindex('|', col),len(col)),'||')+
             substring( substring(col,charindex('|', col),len(col)), 
                                      charindex('|', col),len(col) );

演示版

小提琴

SET NOCOUNT ON;
GO

DECLARE
    @val VARCHAR(MAX);

DECLARE
    @TestData TABLE
    (
        Id INT IDENTITY (1, 1),
        Col1 VARCHAR(100)
    );

DECLARE
    @i INT = 1;

INSERT INTO @TestData
VALUES
(
    'TD_DM_U100|BK_U100|TL_DM_U100||||'
),
(
    'TD_DM_U200|BK_U200|TL_DM_L100||SOME TEXT||'
),
(
    'TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT|'
);

DECLARE
    @Result TABLE
    (
        Col1 VARCHAR(100)
    );

WHILE @i <=
    (
        SELECT
            COUNT(*)
        FROM
            @TestData
    )
BEGIN

    SET @val = NULL;

    SELECT
        @val = COALESCE(@val + '| ' + v.Col1, v.Col1)
    FROM
        (
            SELECT
                ROW_NUMBER() OVER (ORDER BY
                (
                    SELECT
                        1
                )
                ) rn,
                value
            FROM
                STRING_SPLIT(
                (
                    SELECT
                        Col1
                    FROM
                        @TestData
                    WHERE
                        Id = @i
                )
                , '|')
        ) t1
        CROSS APPLY
            (
                SELECT
                    CASE
                        WHEN rn = 2 THEN ''
                        ELSE value
                    END
            ) v (Col1);


    INSERT INTO @Result
    SELECT
        @val;

    SET @i += 1;

END;

SELECT
    *
FROM
    @Result;

說明:

一種可能的方法是使用LEFTRIGHTCHARINDEXLEN函數解析和操作文本值。 下一條語句演示了這種方法:

-- Statement
DECLARE @Text varchar(max) = 'A|B|C|D|'
SELECT 
   LEFT(@Text, CHARINDEX('|', @Text)) AS LeftPart,
   RIGHT(@Text, LEN(@Text) - CHARINDEX('|', @Text)) AS RightPart

-- Output
LeftPart RightPart
A|       B|C|D|

解:

在您的情況下,由於您需要更改文本的第二部分,因此該語句將更加復雜:

表:

CREATE TABLE #Data (
   [Text] varchar(max)
)
INSERT INTO #Data
   ([Text])
VALUES
   ('TD_DM_U100|BK_U100|TL_DM_U100||||'),
   ('TD_DM_U200|BK_U200|TL_DM_L100||SOME TEXT||'),
   ('TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT|')

聲明:

UPDATE #Data
SET [Text] = CONCAT(
   LEFT([Text], CHARINDEX('|', [Text])),
   '|',  -- Or use some different value
   RIGHT(RIGHT([Text], LEN([Text]) - CHARINDEX('|', [Text])), LEN(RIGHT([Text], LEN([Text]) - CHARINDEX('|', [Text]))) - CHARINDEX('|', RIGHT([Text], LEN([Text]) - CHARINDEX('|', [Text]))))
)

輸出:

SELECT *
FROM #Data
--------------------------------------------
Text
--------------------------------------------
TD_DM_U100||TL_DM_U100||||
TD_DM_U200||TL_DM_L100||SOME TEXT||
TD_DM_U300||TL_DM_L100||SOME TEXT|MORE TEXT|

筆記:

與其他信息一樣,您可能遇到的另一種方法是將每個文本轉換為一個表,更新該表中的行,然后將表的行聚合為文本。 SQL Server支持STRING_SPLIT (來自SQL Server 2016)和STRING_AGG (來自SQL Server 2017)功能,但是在您的特定情況下,這不是一個選擇。 原因是STRING_SPLIT不保證輸出表STRING_SPLIT字符串的順序。

輸出行可以按任何順序排列。 不能保證順序與輸入字符串中子字符串的順序匹配。 您可以通過在SELECT語句上使用ORDER BY子句(ORDER BY值)來覆蓋最終的排序順序。

在這種情況下,當每個子字符串的順序很重要時,可以使用JSONXML轉換。 下一個基本示例使用JSON功能對此進行了演示:

-- Statement
DECLARE @Text nvarchar(max) = N'TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT|'
SELECT 
   @Text AS [Text],
   j.[key] + 1 AS Position,
   j.[value]
FROM OPENJSON(CONCAT(N'["', REPLACE(@Text, '|', '","'), N'"]')) j

-- Output
Text                                                Position value
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 1        TD_DM_U300
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 2        BK_U300
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 3        TL_DM_L100
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 4   
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 5        SOME TEXT
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 6        MORE TEXT
TD_DM_U300|BK_U300|TL_DM_L100||SOME TEXT|MORE TEXT| 7   

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM