我必须更新一个文本列,该列是由|
分隔的字符串的列表。我想用空文本替换第二个字符串。
列值示例:
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|
答案 0 :(得分:0)
您可以使用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) );
答案 1 :(得分:0)
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;
答案 2 :(得分:0)
说明:
一种可能的方法是使用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
不能保证输出表中子字符串的顺序。
输出行可以按任何顺序排列。订单不保证 匹配输入字符串中子字符串的顺序。您可以 通过使用ORDER BY子句覆盖最终排序顺序 SELECT语句(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