I tried different ways to find the row that has a duplicate key but without success. The goal is to find the row that has a duplicate key
This is the current row in the table I'm trying to retrieve.This is the duplicate key 12/07/2023":1000.
SELECT 1, '{"fl":{"12/07/2023":1000,"12/07/2023":1000,"12/31/2023":1500,"12/13/2023":2000},"TIME1":{"12/07/2023":0,"12/31/2023":5000}}' FROM DUAL UNION ALL
CREATE TABLE test_json1 (id int, json_date clob );
insert into test_json1 (id,json_date)
SELECT 2, '{"fl":{"12/07/2023":2000,"12/08/2023":3000,"12/31/2023":4000,"12/13/2023":5000},"TIME1":{"12/07/2023":0,"12/31/2023":6000}}' FROM DUAL UNION ALL
SELECT 1, '{"fl":{"12/07/2023":1000,"12/07/2023":1000,"12/31/2023":1500,"12/13/2023":2000},"TIME1":{"12/07/2023":0,"12/31/2023":5000}}' FROM DUAL UNION ALL
SELECT 1,'{"fl":{"12/07/2023":150,"12/31/2023":250,"12/13/2023":350},"TIME1":{"12/07/2023":0,"12/31/2023":100}}' FROM DUAL;
This is a difficult problem because while the JSON specification (PDF) states that:
Therefore your JSON may technically be valid but most JSON processors will not keep duplicate keys and will overwrite the first instance of a duplicate with the second instance of the duplicate.
If you try to extract the keys using
JSON_DATAGUIDE:Then the output is:
and
{"o:path":"$.fl.\"12\/07\/2023\"","type":"number","o:length":4}only appears once (the duplicate is discarded).You can get the values using:
Which outputs:
And the duplicate value is extracted but there is no JSON expression to extract the key corresponding to a particular position within the object.
You can reverse engineer it, to some degree, using PL/SQL functions:
Then:
Outputs:
But then you can see that the PL/SQL parser has discarded the duplicate key, just like
JSON_DATAGUIDEdid, and the keys for the second row of data do not correspond to the values.So, while you should solve this problem using a JSON parser, in practice most implementations of JSON parsers are going to discard duplicate keys.
You could try solving it using regular expressions to find a key followed by a number and then a repeat of that key and number within the same object:
Which outputs:
Note: this will only find the first duplicate in a row and there may be edge cases where the regular expression does not work.
fiddle