Конкатенация / агрегирование строк с JSON в SQL Server - PullRequest
0 голосов
/ 11 декабря 2019

Это может быть простой вопрос для тех, кто имеет опыт работы с JSON в SQL Server. Я нашел этот интересный способ агрегирования строк, используя FOR XML в здесь .

create table #t (id int, name varchar(20))

insert into #t
values (1, 'Matt'), (1, 'Rocks'), (2, 'Stylus')

select  id
    ,Names = stuff((select ', ' + name as [text()]
    from #t xt
    where xt.id = t.id
    for xml path('')), 1, 2, '')
from #t t
group by id

Как я могу сделать то же самое, используя JSON вместо XML?

1 Ответ

2 голосов
/ 12 декабря 2019

Нельзя заменить подход XML на JSON. Эта конкатенация строк работает из-за некоторых внутренних особенностей XML, которые не совпадают в JSON.

Начиная с SQL Server 2017 и выше, вы можете использовать STRING_AGG(), но в более ранних версиях подход XML является способомgo.

Некоторая предыстория и подсказка

Сначала подсказка: показанный вами код небезопасен для специальных символов XML. Посмотрите мой пример ниже.

Сначала я объявляю простой XML

DECLARE  @xml XML=
N'<a>
  <b>1</b>
  <b>2</b>
  <b>3</b>
  <c>
    <d>x</d>
    <d>y</d>
    <d>z</d>
  </c>
</a>';

- XPath . говорит движку XML использовать текущий узел (ивсе в пределах)
- поэтому это вернет любой контент в XML

SELECT @xml.value('.','varchar(100)')

- Вы можете указать путь для получения 123 или xyz

SELECT @xml.query('/a/b').value('.','varchar(100)')
SELECT @xml.query('//d').value('.','varchar(100)')

Теперь ваша проблемадля объединения табличных данных:

DECLARE @tbl TABLE(SomeString VARCHAR(100));
INSERT INTO @tbl VALUES('This'),('will'),('concatenate'),('magically'),('Forbidden Characters & > <');

- Простой запрос FOR XML помечает столбец с <SomeString>, а каждая строка с <row>:

SELECT SomeString FROM @tbl FOR XML PATH('row');

- Номы можем создать то же самое без каких-либо тегов:
- Внимание: внимательно посмотрите, что результат - даже без тегов - имеет тип XML и выглядит как гиперссылка в SSMS.

SELECT SomeString AS [*] FROM @tbl FOR XML PATH('');

- теперь мы можем использовать в качестве суб-выбора в окружающем запросе.
- Результат возвращается в виде строки , а неXML больше не печатается ... Посмотрите на запрещенные символы!

SELECT
 (SELECT SomeString FROM @tbl FOR XML PATH('row'))
,(SELECT SomeString AS [*] FROM @tbl FOR XML PATH(''))

- Мы можем использовать ,TYPE для принудительного выбора подвыбора, который будет рассматриваться как сам XML-тип
- Это позволяетиспользуйте .query() и / или .value()

SELECT
 (SELECT SomeString FROM @tbl FOR XML PATH('row'),TYPE).query('data(//SomeString)').value('.','nvarchar(max)')
,(SELECT SomeString AS [*] FROM @tbl FOR XML PATH(''),TYPE).value('.','nvarchar(max)')

XQuery's .data() можно использовать для объединения именованных элементов с пробелами между ними.
XQuery's .value() необходимо использовать для повторного пробега запрещенногоперсонажи.

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