'What's the fastest way to search for a value in json in SQL, if we do not know the path

I am looking for the fastest way to search in a SQL table for a value in a JSON.

I am trying to update this value. And there may be more occurrences in the same JSON.

update d
    set d.Content = replace(d.Content, rm.WrongValue , rm.NewValue)
    from dbo.Document d
    inner join RenameMatches rm d.content like '%' + rm.WrongValue + '%'

The next line is taking to long and I am trying to make it faster

 d.content like '%' + rm.WrongValue + '%'

I thought using JSON_Modify, however, the path is not always the same.

Thanks!



Solution 1:[1]

If there's multiple WrongValue's in that RenameMatches, then you could loop through them.

But then it needs some sequencial number without gaps.

In the example below, the values are assumed to be strings.
So they get double-quoted to match complete string values.

Demo:

-- 
-- Sample data
-- 
create table Document (
 document_id int identity primary key, 
 content nvarchar(max)
);

insert into Document (content) values
  ('[{"id":1, "code":"abc123"},{"id":2, "code":"def456"}]') 
, ('{"id":3, "data":{"name":"test",code1":"abc123","code2":"abc123"}}');

create table RenameMatches (
 WrongValue nvarchar(30) not null primary key, 
 NewValue nvarchar(30) not null
);

insert into RenameMatches (WrongValue, NewValue) values
  ('abc123', 'abc12345')
, ('def456', 'def456789');
-- Using a table variable with identity
DECLARE @RenameMatches table (
 id INT identity primary key, 
 WrongValue NVARCHAR(30) not null, 
 NewValue NVARCHAR(30) not null
);

INSERT INTO @RenameMatches (WrongValue, NewValue) 
SELECT WrongValue, NewValue
FROM RenameMatches;

DECLARE @MaxRenameID INT = (SELECT MAX(id) FROM @RenameMatches);
DECLARE @RenameID INT = 1;

WHILE @RenameID <= @MaxRenameID
BEGIN
   UPDATE d
   SET d.Content = REPLACE(d.Content
                   , quotename(rm.WrongValue,'"') 
                   , quotename(rm.NewValue,'"')) 
   FROM Document d
   JOIN @RenameMatches rm
     ON rm.id = @RenameID 
    AND d.content like '%"'+rm.WrongValue+'"%';

   SET @RenameID += 1;
END;
select * from Document
document_id content
1 [{"id":1, "code":"abc12345"},{"id":2, "code":"def456789"}]
2 {"id":3, "data":{"name":"test",code1":"abc12345","code2":"abc12345"}}

Demo on db<>fiddle here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LukStorms