メモ:T-SQL FOR XML は XML にするから XML でエスケープ必要な文字がエスケープされる

メモ:T-SQL 単一列の結果表をシンプルな JsonArray にしたい - お だ のスペース

で、XML にしたいわけじゃないのに FOR XML 使ってますが、こういう時に XMLエスケープ必要な文字があった場合困ることが起きます。

前回のデータを変えて試してみます。

create table [データ] (
  [Id] bigint not null identity(1, 1) primary key
  , [Name] nvarchar(20) not null
)
go
insert into [データ] ([Name]) values 
(N'あいう&えお')
, (N'かき<div>くけこ</div>')
select concat(',', '"', [Name], '"') from [データ]
for xml path('')
,"あいう&amp;えお","かき&lt;div&gt;くけこ&lt;/div&gt;"

エスケープされてますね。XML 化するのでまあ当然。。

これをエスケープしてない文字列としてとる方法があります。

まず FOR XML クエリの TYPE ディレクティブ - SQL Server | Microsoft Docs を使って XML 型として返します。

select concat(',', '"', [Name], '"') from [データ] 
for xml path(''), type
,"あいう&amp;えお","かき&lt;div&gt;くけこ&lt;/div&gt;"

結果は変わりませんが、XML 型 になっています。
これで XML 型のメソッドが使えます。
xml データ型のメソッド - SQL Server | Microsoft Docs
今回は value() メソッド (xml データ型) - SQL Server | Microsoft Docs を使って値を全部取り出します。

select (
  select concat(',', '"', [Name], '"') from [データ] 
  for xml path(''), type
).value('.', 'nvarchar(max)')
,"あいう&えお","かき<div>くけこ</div>"

はい、エスケープされてない生文字列が取れました。