5

In our SQL Server table we have a json object stored with an array of strings. I want to programatically split that string into several columns. However, I cannot seem to get it to work or even if it's possible.

Is this a possibility to create multiple columns within the WITH clause or it is a smarter move to do it within the select statement?

I trimmed down some of the code to give a simplistic idea of what's given.

The example JSON is similar to { "arr": ["str1 - str2"] }

SELECT b.* FROM [table] a
OUTER APPLY
OPENJSON(a.value, '$.arr')
WITH
(
    strSplit1 VARCHAR(100) SPLIT('$.arr', '-',1),
    strSplit2 VARCHAR(100) SPLIT('$.arr', '-',2)
) b
2
  • NB: { "arr": ["str1 - str2"] } is an array holding a single string. { "arr": ["str1","str2"] } is an array with 2 strings. Did you mean the latter, or is the former correct?
    – JohnLBevan
    Commented Oct 24, 2018 at 15:27
  • There's no SPLIT in SQL Server. There's a STRING_SPLIT in SQL Server 2016+. You should probably fix the JSON contents though. If you want an array of strings, why use ["str1 - str2"] instead of ["str1","str2"]? Commented Oct 24, 2018 at 15:46

2 Answers 2

8

Due to the tag [tsql] and the usage of OPENJSON I assume this is SQL-Server. But might be wrong... Please always specify your RDBMS (with version).

Your JSON is rather weird... I think you've overdone it while trying to simplify this for brevity...

Try this:

DECLARE @tbl TABLE(ID INT IDENTITY,YourJSON NVARCHAR(MAX));
INSERT INTO @tbl VALUES(N'{ "arr": ["str1 - str2"] }') --weird example...
                      ,(N'{ "arr": ["a","b","c"] }');  --array with three elements

SELECT t.ID
      ,B.[value] AS arr
FROM @tbl t
CROSS APPLY OPENJSON(YourJSON) 
WITH(arr NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.arr) B;

A rather short approach (but fitting to this simple example only) was this:

SELECT t.ID
      ,A.*
FROM @tbl t
OUTER APPLY OPENJSON(JSON_QUERY(YourJSON,'$.arr')) A 

Hint

JSON support was introduced with SQL-Server 2016

UPDATE: If the JSON's content is a weird CSV-string...

There's a trick to transform a CSV into a JSON-array. Try this

DECLARE @tbl TABLE(ID INT IDENTITY,YourJSON NVARCHAR(MAX));
INSERT INTO @tbl VALUES(N'{ "arr": ["str1 - str2"] }') --weird example...
                      ,(N'{ "arr": ["a","b","c"] }')  --array with three elements
                      ,(N'{ "arr": ["x-y-z"] }');     --array with three elements in a weird CSV format

SELECT t.ID
      ,B.[value] AS arr
      ,C.[value]
FROM @tbl t
CROSS APPLY OPENJSON(YourJSON) 
WITH(arr NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.arr) B
CROSS APPLY OPENJSON('["' + REPLACE(B.[value],'-','","') + '"]') C;

Some simple replacements in OPENJSON('["' + REPLACE(B.[value],'-','","') + '"]') will create a JSON array out of your CSV-string, which can be opened in OPENJSON.

0

I'm not aware of any way to split a string within JSON. I wonder if the issue is down to your JSON containing a single string rather than multiple values?

The below example shows how to extract each string from the array; and if you wish to go further and split those strings on the hyphen, shows how to do that using SQL's normal SUBSTRING and CHARINDEX functions.

create table [table]
(
    value nvarchar(max)
)

insert [table](value)
values ('{ "arr": ["str1 - str2"] }'), ('{ "arr": ["1234 - 5678","abc - def"] }')

SELECT b.value
, rtrim(substring(b.value,1,charindex('-',b.value)-1))
, ltrim(substring(b.value,charindex('-',b.value)+1,len(b.value)))
FROM [table] a
OUTER APPLY OPENJSON(a.value, '$.arr') b

If you want all values in a single column, you can use the string_split function: https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-2017

SELECT ltrim(rtrim(c.value))
FROM [table] a
OUTER APPLY OPENJSON(a.value, '$.arr') b
OUTER APPLY STRING_SPLIT(b.value, '-') c
2
  • 1
    I prefer OPENJSON over STRING_SPLIT() as it returns in the given order, which is not guaranteed by STRING_SPLIT(). It's easy to transform a CSV into a JSON array. There's an example in my answer. Commented Oct 24, 2018 at 15:53
  • Ah nice trick; manipulate the string before parsing the JSON; sneaky
    – JohnLBevan
    Commented Oct 24, 2018 at 15:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.