6

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? 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

9

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.

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

Comments

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 Comments

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.
Ah nice trick; manipulate the string before parsing the JSON; sneaky

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.