We are migrating from Oracle 11.2 to 19c. When DB objects were moved, few packages were invalid. All those packages involves updating a table (say tableA) which has clob data. And tableA is locked using "select..for update some_column nowait"
cursor c1 is select *
from table A,
XMLTable(....)
where A.id=1
FOR UPDATE of A.ind NOWAIT
The error states "ORA-01786 for update of this query expression is not allowed"
I read oracle forums and talked to the DBA. Solution suggested is to write a select for update which does not involve JSON data" (Documentation id 2507724.1, Patch 28822515)
It nearly impossible to rewrite the package. Can someone help me understand how to know if this patch has know bugs or if there is any other patch to overcome this?
CodePudding user response:
It isn't entirely clear that the error you are seeing is from the same change that affected JSON data, but it seems likely that it could apply to XML data too.
If so it wouldn't be a bug, as the change the MoS document you referred to says was introduced in patch 28822515 was apparently fixing a bug for it not throwing ORA-01786 in this sort of scenario. (That patch is the January 2019 CPU for versions before 19c; again the document says that was back-porting a change in 19c to earlier versions.)
A more complete example like:
declare
cursor c1 is
select *
from A,
XMLTable('/x/y/z' passing A.xml columns z number path '.')
where A.id=1
FOR UPDATE of A.ind NOWAIT;
begin
for r1 in c1 loop
dbms_output.put_line(r1.id || ': ' || r1.z);
end loop;
end;
/
works as expected in 11gR2 (11.2.0.2) and in relatively unpatched 18c (18.4), but errors in 21c (21.3) - which is essentially an evolved version of 19c.
Avoid the error seems to be fairly straightforward - you need to separate the cursor that locks the table for update from the XMLTable call, which with this example at least you can easily do with nested cursors:
declare
cursor c1 is
select *
from A
where A.id=1
FOR UPDATE of A.ind NOWAIT;
cursor c2(xml xmltype) is
select *
from XMLTable('/x/y/z' passing c2.xml columns z number path '.');
begin
for r1 in c1 loop
for r2 in c2(r1.xml) loop
dbms_output.put_line(r1.id || ': ' || r2.z);
end loop;
end loop;
end;
/
which is shown working in the three db<>fiddles linked to above.