Как кодировать сущности в качестве разделителя в значении при конкатенации с использованием трюка T / SQL FOR XML - PullRequest
0 голосов
/ 15 апреля 2019

Я использую трюк T / SQL FOR XML для объединения набора значений с разделителем. Я хотел бы, чтобы сущность кодировала мой разделитель (| в данном случае) в пределах значений, но затем FOR XML повторно кодирует | поэтому я получаю & amp; # 124;

if object_id('tempdb..#t') is not null drop table #t
create table #t (v varchar(100))
insert #t(v) values ('Foo'),('A|B'),('Bar')

select (
    select '|' + v AS [text()]
    FROM #t
    FOR XML PATH ('')
) + '|' as vConcat

-- Result of above = |Foo|A|B|Bar| -- delimiter in A|B not escaped

select (
    select '|' + replace(v, '|', '|') AS [text()] 
    FROM #t
    FOR XML PATH ('')
) + '|' as vConcat

-- Result of above = |Foo|A|B|Bar| -- delimiter double-escaped

Есть ли способ заставить FOR XML кодировать дополнительные символы? Или есть лучший способ получения экранированных разделителей внутри FOR XML?

Использование другого разделителя - не тот ответ, который я ищу.

Я знаю, что обернуть все выражение в замену, чтобы отменить двойное кодирование, сработает, но это не кажется мне очень элегантным.

select replace((
    select '|' + replace(v, '|', '|') AS [text()] 
    FROM #t
    FOR XML PATH ('')
) + '|', '|', '|') as vConcat

-- Result of above = |Foo|A|B|Bar|

Редактировать

Чтобы прояснить вопрос, я хочу кодировать сущность моего разделителя (только в пределах оригинальных значений) в дополнение к обычным специальным символам XML.

if object_id('tempdb..#t') is not null drop table #t
create table #t (v varchar(100))
insert #t(v) values ('F&o'),('A|B'),('Bar'),('A|B')

select (
    select '|' + v AS [text()]
    FROM #t
    FOR XML PATH ('')
) + '|' as vConcat

-- Result of above = |F&o|A|B|Bar|A|B| -- special chars encoded but not delimiter in A|B value

select (
    select '|' + replace(v, '|', '|') AS [text()] 
    FROM #t
    FOR XML PATH ('')
) + '|' as vConcat

-- Result of above = |F&o|A|B|Bar|A|B| -- delimiter in A|B value double-encoded

-- Desired result = |F&o|A|B|Bar|A|B|

1 Ответ

1 голос
/ 15 апреля 2019

Вы можете использовать value() в XML.

SELECT (SELECT '|' + replace(v, '|', '|') AS [text()]
               FROM #t
               FOR XML PATH (''), TYPE).value('.', 'varchar(max)') + '|' vconcat;

дб <> скрипка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...