web-dev-qa-db-ja.com

CASEステートメント内のJSON_QUERYがエスケープ文字を削除できないのはなぜですか?

関数がcaseステートメント内で適用されている場合、json_queryは二重引用符( ")のエスケープ文字を削除できないようです。

以下のサンプルコード。

declare @data nvarchar(max);
declare @debug int = 0;

set @data = '{"id":10}';

set @debug = 0;
select
    isjson(@data) as 'validateData',
    @data as 'unprocessedSourceData',
    json_query(@data) as 'processedSourceData',
    case when @debug = 1 then json_query(@data) else null end as 'conditionallyProcessedSourceData'
    for json path, without_array_wrapper ;

set @debug = 1;
select
    isjson(@data) as 'validateData',
    @data as 'unprocessedSourceData',
    json_query(@data) as 'processedSourceData',
    case when @debug = 1 then json_query(@data) else null end as 'conditionallyProcessedSourceData'
    for json path, without_array_wrapper ;

最初のクエリの結果:

{"validateData":1,"unprocessedSourceData":"{\"id\":10}","processedSourceData":{"id":10}}

2番目のクエリの結果:

{"validateData":1,"unprocessedSourceData":"{\"id\":10}","processedSourceData":{"id":10},"conditionallyProcessedSourceData":"{\"id\":10}"}

末尾のエスケープ文字に注意してください: "{\"id\":10}"

1)なぜそうなのでしょうか?

2)@debug = 1の場合、conditionallyProcessedSourceData要素に有効なJSONが含まれ、@debug = 0の場合、要素がnullになるように、このクエリを再作成するにはどうすればよいですか?

4

From JSON_QUERY(Transact-SQL) から

タイプnvarchar(max)のJSONフラグメントを返します。

そして

JSON_QUERYは有効なJSONフラグメントを返します。その結果、FOR JSONはJSON_QUERY戻り値の特殊文字をエスケープしません。

したがって、nvarchar(max)データがnvarchar(max)からのものでない限り、_for json path_はjson_query()データをエスケープします。

クエリでは、データは、_json_query_から直接ではなく、caseステートメントから取得されます。

あなたができる回避策は、ケースの外に_json_query_を置くことです。

_json_query(case when @debug = 1 then @data else null end)
_

これを完全なスクリプトに組み込んで、さまざまなアプローチを比較できるようにすると、次のようになります。

_declare @data nvarchar(max);
declare @debug int = 0;

set @data = '{"id":10}';

set @debug = 0;
select
    isjson(@data) as 'validateData',
    @data as 'unprocessedSourceData',
    json_query(@data) as 'processedSourceData',
    case when @debug = 1 then json_query(@data) else null end as 'conditionallyProcessedSourceData', 
    json_query(case when @debug = 1 then @data else null end) as 'caseResultProcessed'
    for json path, without_array_wrapper ;

set @debug = 1;
select
    isjson(@data) as 'validateData',
    @data as 'unprocessedSourceData',
    json_query(@data) as 'processedSourceData',
    case when @debug = 1 then json_query(@data) else null end as 'conditionallyProcessedSourceData', -- This was the issue
    json_query(case when @debug = 1 then @data else null end) as 'caseResultProcessed' -- This is the solution
    for json path, without_array_wrapper ;
_
6
Mikael Eriksson