2

I need to replace some values in Oracle 19 column that is CLOB with JSON constraint, but cannot find a right way to do it. Json can be big and I suppose regex function on string may not work due to the length restrictions.

My json may have 'locationId' property at any level with some values. Let's say I have bad value 000 and want to replace it with 111, so everywhere where is "locationId":"000" it becomes "locationId":"111".

I'm trying to use next json_transform command:

SELECT json_transform('
{
 "a": {
   "locationId":"000"
 }, 
 "b": {
   "locationId":"111", 
   "x": {
     "locationId":"000"
    }
 }
}', REPLACE '$..locationId?(@ == "000")' = '111' IGNORE ON MISSING) 
FROM dual

But it returns unchanged json, when next query for the same json fetches values to replace properly :

SELECT json_query('
{
 "a": {
   "locationId":"000"
 }, 
 "b": {
   "locationId":"111", 
   "x": {
     "locationId":"000"
   }
 }
}', '$..locationId?(@ == "000")' WITH WRAPPER) 
FROM dual

Result: ["000","000"]

There is no any documentation or examples how to use filters within json_transform, so I'm not sure it's even possible. Maybe anybody know how to do it? Doesn't matter with json functions or not.

Links I use:

Oracle Json Path Expressions

Oracle json_query

Oracle json_transform

2 Answers 2

1

Have you seen that even

REPLACE '$..locationId' = '111' IGNORE ON MISSING

doesn't change anything ? (at least in Cloud 21c)

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

3 Comments

Yes, so thats why i'm afraid .. (two dots) may not work for transform. But there is nothing in oracle documentation about limits for json path for transform!
for the fun you may try , REPLACE '$.locationId?(@ == "000")' = '111' IGNORE ON MISSING , REPLACE '$.*.locationId?(@ == "000")' = '111' IGNORE ON MISSING , REPLACE '$.*.*.locationId?(@ == "000")' = '111' IGNORE ON MISSING , REPLACE '$.*.*.*.locationId?(@ == "000")' = '111' IGNORE ON MISSING since json_transform supports several expressions at once.
'$.*.locationId?(@ == "000")' = '111' doesn't work either. Only strict path like '$.a.locationId?(@ == "000")' = '111' works. Very limited functionality from Oracle..
1

It's more complicated:

SELECT json_transform('
{
 "locationId" : "000",
 "a": {
   "locationId":"000"
 }, 
 "b": {
   "locationId":"000", 
   "x": {
     "locationId":"000", 
       "y": {
         "locationId":"000"
        }
    }
 }
}'
    , REPLACE '$.locationId?(@ == "000")' = '111' IGNORE ON MISSING
    , REPLACE '$.*.locationId?(@ == "000")' = '111' IGNORE ON MISSING
    , REPLACE '$.*.*.locationId?(@ == "000")' = '111' IGNORE ON MISSING
    , REPLACE '$.*.*.*.locationId?(@ == "000")' = '111' IGNORE ON MISSING
) 
FROM dual;

Gives:

{"locationId":"111","a":{"locationId":"111"},"b":{"locationId":"111","x":{"locationId":"111","y":{"locationId":"111"}}}}

2 Comments

This doesn't work for me in Oracle 19c. Only strict path without * works
The latest I posted shows that the behavior also changes according to the content of the sibling nodes. So the best may be to post a bug report, unless somebody else can better explain why.

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.