3

In SQL Server 2022 and Azure SQL, the function JSON_ARRAY has been added.

This works:

select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col

This doesn't:

select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col
union all
select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col

The union gives me [S0002][206] Line 1: Operand type clash: nvarchar(max) is incompatible with void type

So why would the union not work?

5
  • Although the docs say it is available on Azure SQL, I couldn't get it to work there. I'm testing this with the SQL Server 2022 Docker image. Commented Oct 6, 2022 at 10:51
  • what if you cast/convert one json_array() to nvarchar(max)? Commented Oct 6, 2022 at 11:26
  • 1
    @lptr Thanks for the suggestion, but unfortunately I get the same error. Tried casting both of them as well. Commented Oct 6, 2022 at 11:30
  • Json_query() the array? Commented Oct 6, 2022 at 11:36
  • No ability to try this but perhaps a rowgoal could force the optimizer to treat the union correctly - eg union the result of select top(100000)... etc? Commented Oct 6, 2022 at 13:27

1 Answer 1

2

Seems a bug to me, something happening with union (with or without all) and also with intersect, except, etc. before the JSON transformation converts the array to a simple string. But a join between two subqueries works:

select * FROM 
(select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col ) AS x
INNER JOIN 
(select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col) AS y
ON x.id = y.id;

I'd suggest filing a bug here (at least at the moment).

In the meantime, you can coerce slightly different behavior using explicit collation against the expressions:

select 1 as id, JSON_ARRAY(1 , 2 , 3) 
  COLLATE SQL_Latin1_General_CP1_CI_AS as array_col 
UNION ALL
select 1 as id, JSON_ARRAY(1 , 2 , 3) 
  COLLATE SQL_Latin1_General_CP1_CI_AS as array_col;

enter image description here

For integers it probably doesn't matter what collation you use (only that you use the same one for all aligned expressions in the union!) but, for strings, you might instead use:

select 1 as id, JSON_ARRAY(1 , 2 , 3) 
  COLLATE DATABASE_DEFAULT as array_col 
UNION ALL
select 1 as id, JSON_ARRAY(1 , 2 , 3) 
  COLLATE DATABASE_DEFAULT as array_col;

An uglier workaround could be to forcefully materialize the output of both queries, and union those:

select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col into #x;
select 1 as id, JSON_ARRAY(1 , 2 , 3) as array_col into #y;
select * from #x union all select * from #y;

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.