0

I have several columns in my database. In one of these columns is a JSON string like: fyvfvv.

[
  {
    "Value": "0000138010687",  
    "Name": "Code"
  }
]

I need to select those rows from the database, whose JSON is filled with the value of the mask "0000****", or the value is greater than a certain number. Can you tell me how to do it in the best way?

7
  • 1
    Have you had a look at OPENJSON? What have you tried? Why didn't it work. Commented Mar 14, 2023 at 9:04
  • 1
    Don't use such columns if you intend to query them. You can't use any indexes in a JSON query so you end up scanning the entire table. That's a bad JSON schema too, making querying with JSON functions a lot harder if not impossible - why not use "Code":"0000138010687" ? Commented Mar 14, 2023 at 9:13
  • 1
    If you change the JSON schema to the normal {"key":"value"} you'll be able to use JSON_VALUE(field,'$.Code') to get the code value. You'll also be able to create a computed and persisted field that can be indexed eg ThatCode AS JSON_VALUE(field,'$.Code') PERSISTED. Your query could become as simple as WHERE ThatCode LIKE '0000%' and take advantage of indexes. Commented Mar 14, 2023 at 9:16
  • 1
    the value is greater than a certain number that's another unusual requirement. Strings aren't numbers either in JSON or SQL. In JSON, 2 is a number but "2" is a string that's greater than "0000138010687" because strings are ordered alphabetically, and "2" comes after "0". You can use TRY_CAST to try and parse the value into a number. TRY_CAST will return NULL if the cast fails. If the JSON string had a normal schema you could use ThatCode_AsNumber AS TRY_CAST(JSON_VALUE(field,'$.Code') as number(18,0)) PERSISTED Commented Mar 14, 2023 at 9:22
  • @PanagiotisKanavos This is a legacy enterprise database with 10 years of history and it's not my place to change it. The column stores a lot of data in json form (I cut it down for example to understand the principle and redo it for myself) which is further used in many processes Commented Mar 14, 2023 at 9:25

2 Answers 2

3

You need to parse the stored JSON with OPENJSON() and use the appropriate WHERE clause.

Data:

SELECT *
INTO JsonTable
FROM (VALUES
   ('[{"Value": "00001380", "Name": "Code"}]'),
   ('[{"Value": "0000138010688", "Name": "Code"}]'),
   ('[{"Value": "0000138010689", "Name": "Code"}]')
) v (JsonColumn)

Statement (to get the rows):

SELECT *
FROM JsonTable t
WHERE EXISTS (
   SELECT 1
   FROM OPENJSON(t.JsonColumn) WITH (
      [Value] varchar(100) '$.Value',
      [Name] varchar(100) '$.Name'
   )
   WHERE [Value] LIKE '0000____'  
)

Statement (to get the rows and the parsed JSON):

SELECT *
FROM JsonTable t
CROSS APPLY OPENJSON(t.JsonColumn) WITH (
   [Value] varchar(100) '$.Value',
   [Name] varchar(100) '$.Name'
) j
WHERE j.[Value] LIKE '0000____'  

Both statements return the correct results, even if the parsed JSON array contains more than one item.

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

Comments

1

Assuming the json array contains one element only, then we can use JSON_VALUE() to get the element value by path :

select *
from (
  select *, 
    JSON_VALUE(JsonColumn, '$[0].Value') as theValue, 
    JSON_VALUE(JsonColumn, '$[0].Name') as theName
  from JsonTable
) as s
where theName = 'Code' and theValue like '0000%';

Demo here

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.