1

How can I compare two JSON_OBJECT_T?

I have a PL/SQL procedure. I am getting a return of an array of JSON OBJECT from the GET request from HTTP API endpoint. I have prepared a JSON_OBJECT_T record REC1.

I am trying to compare REC1 with every record in the return array from the GET request. So as to figure out if I need to do an UPDATE request or PUT request for REC1.

I am in Oracle 19C, and I am trying to use JSON_EQUAL to compare the JSON_OBJECT_T, but I am getting the following error:

PLS-00201: identifier 'JSON_EQUAL' must be declared

How can I achieve this in PL/SQL? Is there another efficient method to achieve this?

Tried JSON_EQUAL.

Expecting: Return Boolean if equal

1

1 Answer 1

1

JSON_EQUALS is not supported in PL/SQL expressions, and will throw that exception.

You can use it in SQL within PL/SQL, but it seems you have to do a few extra steps when you're starting from JSON_ARRAY_T and JSON_OBJECT_T.

If you have an array and an object declared something like:

declare
  l_array json_array_t;
  l_object json_object_t;

and populated from your HTTP call or manually, then you need string versions declared, with your object converted to a string once, and each array element also converted to a string as you loop over the array.

  l_clob_1 := l_object.to_clob;
  <<json_loop>>
  for i in 0..l_array.get_size - 1 loop
    l_clob_2 := l_array.get(i).to_clob;

You can then use a SQL query to call JSON_EQUAL using those strings:

    select case when json_equal(l_clob_1, l_clob_2) then 1 else 0 end
    into l_match_num
    from dual;

You can then set your boolean flag, and break the loop, if that returns 1.

    if l_match_num = 1 then
      l_match_boo := true;
      exit json_loop;
    end if;
  end loop;

You can then use that boolean value however you need to.

So putting that together as a demo with made-up data:

declare
  l_array json_array_t;
  l_object json_object_t;
  l_clob_1 clob;
  l_clob_2 clob;
  l_match_num number;
  l_match_boo boolean;
begin
  l_array := json_array_t('[{"id": 1, "value":"hello"},{"id": 2, "value":"world"}]');
  l_object := json_object_t('{"id": 2, "value":"world"}');

  l_clob_1 := l_object.to_clob;
  <<json_loop>>
  for i in 0..l_array.get_size - 1 loop
    l_clob_2 := l_array.get(i).to_clob;
    select case when json_equal(l_clob_1, l_clob_2) then 1 else 0 end
    into l_match_num
    from dual;

    if l_match_num = 1 then
      dbms_output.put_line('Index ' || i || ' matched');
      l_match_boo := true;
      exit json_loop;
    end if;
  end loop;

  if l_match_boo then
    dbms_output.put_line('Match');
  else
    dbms_output.put_line('No match');
  end if;
end;
/

which output:

Index 1 matched
Match

fiddle

The context switching will affect the efficiency but how much maybe depends on the amount of data. You could potentially convert the array to a temporary table of JSON strings and then query that in once go, rather than one element at a time, but that might end up being more work and less efficient.


I am getting a return of an array of JSON OBJECT from GET request from HTTP API endpoint

If you are actually getting a string and parsing that into a JSON_ARRAY_T then you can probably approach this completely differently by using other functions like JSON_TABLE to parse it instead, and then doing the entire parse/comparison in a single SQL query. You haven't shown what you're actually ding though, so that may not be possible.

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.