[英]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;
說明:
一種可能的方法是使用LEFT
, RIGHT
, CHARINDEX
和LEN
函數解析和操作文本值。 下一條語句演示了這種方法:
-- 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值)來覆蓋最終的排序順序。
在這種情況下,當每個子字符串的順序很重要時,可以使用JSON
或XML
轉換。 下一個基本示例使用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.