Migrating from Oracle 11 to 19c - oracle

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?

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.

Related

Error 38824 : A CREATE OR REPLACE Command May not Change the EDITIONABLE Property of an Existing Object

we are implementing a unit test system of our database production object like package, procedure, trigger & co. To do so, we have a container which create a database from https://github.com/oracle/docker-images/tree/master/OracleDatabase .
Then we execute scripts which are creating schema, users, grant some privileges, create good tablespaces... Then we use Data Pump Oracle to expdp and impdp the schema. These steps are successful.
The problem appear when we try to exec test on our Procedures and Packages. They are not find in schema due to compilation error "ORA-38824 : A CREATE OR REPLACE Command May not Change the EDITIONABLE Property of an Existing Object".
But if we drop the procedure tested, then recreate it, the error does not appear anymore. Things is we do not want to manually drop & re create the procedure.
the only difference between our environment & the container database is that when we create a procedure/package from scratch, Editionable parameter in object detail are at 'N' in container when it is at 'Y' in our env.
It seems that Editionable parameter for objects has to be set at Database level.
But the question is where can it be set ?
We tried to 'ALTER USER X ENABLE EDITIONS;' without success since it is causing 'ORA-38813: editions not supported for schema X'.
Is Impdp & Expdp causing trouble ?
We tried using 'source_edition' & 'target_edition' for our expdp impdp process.
We are clearly missing something or doing something wrong but we are not able to find what.
I have searched on internet, but not too much people have been facing this issue..
Could you please provide us help?
Thanks in advance.
Vincent.
I checked the Oracle Support website (should have done this earlier) and this error is related to a bug in 12c. For example in one such document (Meta Link Document) it is said as follows. So please refer this issue to Oracle by raising an SR and most likely they will come back with a suggestion for an Oracle version upgrade:
Please apply the merge patch Bug 27314007 : MERGE REQUEST ON TOP OF 12.2.0.1.0 FOR BUGS 25557064 26645487
Using these steps for the upgrade:
Stop the current DBUA session.
Download and apply the patch to 12.2 Oracle home.
Restore the 12.1 database.
Re-run the upgrade from 12.1 to 12.2.
Thanks,
I went through this recently, and analyzing it we would not use the EDITIONABLE functionality, so I ran the command below, leaving the NONEDITIONABLE objects, because that way the objects are replaced. And in the DBA_OBJECTS table, the EDITIONABLE column is N, so when it is time to do the imp, there is no problem.
DECLARE
TYPE t_cursor IS REF CURSOR;
TYPE t_string_array IS TABLE OF VARCHAR2(1000) INDEX BY BINARY_INTEGER;
vcursor t_cursor;
varraystring t_string_array;
vstring VARCHAR2(500);
i BINARY_INTEGER;
BEGIN
OPEN vcursor FOR
select 'ALTER ' || do.object_type || ' ' || do.owner || '.' || do.object_name || ' NONEDITIONABLE'
from DBA_OBJECTS do
where do.editionable = 'Y'
and do.owner NOT IN('QS_CB','DIP','PERFSTAT','QS_ADM','PM','SH','HR','OE','ODM_MTR','WKPROXY','ANONYMOUS','OWNER','SYS','SYSTEM','SCOTT','SYSMAN','XDB','DBSNMP','EXFSYS','OLAPSYS','MDSYS','WMSYS','WKSYS','DMSYS','ODM','EXFSYS','CTXSYS','LBACSYS','ORDPLUGINS','SQLTXPLAIN','OUTLN','TSMSYS','XS$NULL','TOAD','STREAM','SPATIAL_CSW_ADMIN','SPATIAL_WFS_ADMIN','SI_INFORMTN_SCHEMA','QS','QS_CBADM','QS_CS','QS_ES','QS_OS','QS_WS','PA_AWR_USER','OWBSYS_AUDIT','OWBSYS','ORDSYS','ORDDATA','ORACLE_OCM','SPATIAL_CSW_ADMIN_USR','SPATIAL_WFS_ADMIN_USR','MGMT_VIEW','MDDATA','FLOWS_FILES','FLASHBACK','AWRUSER','APPQOSSYS','APEX_PUBLIC_USER','DVSYS')
and do.object_type IN ('FUNCTION','LIBRARY','PACKAGE BODY','PACKAGE','PROCEDURE','TRIGGER','TYPE','TYPE BODY','SYNONYM','VIEW');
LOOP
FETCH vcursor BULK COLLECT
INTO varraystring;
EXIT WHEN varraystring.count = 0;
FOR i IN varraystring.first .. varraystring.last LOOP
EXECUTE IMMEDIATE varraystring(i);
END LOOP;
EXIT WHEN vcursor%NOTFOUND;
END LOOP;
CLOSE vcursor;
END;

"no more data to read from socket" message when using with clause (in oracle sql developer) [duplicate]

My procedure looks like this:
Declare
cur_1 Sys_Refcursor;
cur_2 Sys_Refcursor;
v_1 VARCHAR2(30);
v_2 VARCHAR2(30);
v_3 VARCHAR2(30);
v_4 VARCHAR2(30);
Begin
OPEN cur_1 for Select * from tab1#dblink1;
Loop
Fetch cur_1 into v_1, v_2;
EXIT WHEN cur_1%NOTFOUND;
OPEN cur_2 for Select * from tab2#dblink1 where col1 = v_1 and col2 = v2;
Loop
Fetch cur2 into v_3, v_4;
Exit when cur_2%notfound;
INSERT INTO local.tab3 values (v_1,v_2, v_3, v_4);
END Loop;
close cur_2;
End Loop;
close cur_1;
END;
The abobe procedure compiles, but when I run it I get following error:
No more data to read from socket
No more data to read from socket
No more data to read from socket
No more data to read from socket
No more data to read from socket
No more data to read from socket
No more data to read from socket
No more data to read from socket
...(Few more 'No more data to read from socket')
IO Error: Connection reset by peer: socket write error
Process exited.
Interesting thing is when I comment out the entire inner loop the procedure runs without error. So I know something is wrong with the inner loop (I tried commenting only the insert statement inside the inner loop and got the same error).
Both my localdb and dblink1 databases have same version:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
Generic advice for troubleshooting "No more data to read from socket" errors.
These errors are usually caused by another serious error, such as an ORA-600 error. A problem so serious that the server process crashed and could not even send a proper error message to the client. (Another common reason for these errors is a network disconnection caused by SQLNET.EXPIRE_TIME or some other process that kills old sessions.)
Look at the Alert Log to find out the original error message.
Look for the file alert_[name].log in this directory: select value from v$parameter where name = 'background_dump_dest';
After you find the specific error message and details, go to support.oracle.com. Use the "ora-600 tool" and then lookup the first number after the ORA-600 message.
There will usually be one or more articles for that specific type of ORA-600 error. Use the exact version and platform to narrow down the possible list of bugs. (But don't be surprised if the "Versions affected" in the article are wrong. Oracle's claims of "fixed in version x.y" are not always true.)
The articles typically explain in more details how the problem happened, possible workarounds, and a solution that usually involves a patch or upgrade.
In practice you rarely want to solve these problems. The "typical" advice is to contact Oracle Support to verify you really have the same problem, get a patch, get permission and bring down the environment(s), and then apply the patch. And then probably realize the patch doesn't work. Congratulations, you just wasted a lot of time.
Instead, you can usually avoid the problem with a subtle change to the query or procedure. There are a lot of features in Oracle, there's almost always another way to do it. If the code ends up looking a bit weird, add a comment to warn future programmers: "This code looks weird to avoid bug X, which should be fixed in version Y."
Specific advice for this code
If that's really your entire procedure, you should replace it with something like this:
insert into local.tab3(col1, col2, col3, col4)
select tab1.col1, tab1.col2, tab2.col1, tab2.col2
from tab1#dblink1 tab1
join tab2#dblink1 tab2
on tab1.col1 = tab2.col1
and tab1.col2 = tab2.col2;
In general, you should always do things in SQL if possible. Especially if you can avoid opening many cursors. And especially if you can avoid opening many cursors to a remote database.
As jonearles mentioned you should write this in one SQL statement.
If you insist on using PL/SQL : you are doing way too much work yourself, declaring variables, open cursors, looping, assigning variables. Consider this PL/SQL:
begin
for c1 in (select * from tab1#dblink1)
loop
for c2 in (Select * from tab2#dblink1 where col1 = c1.col1 and col2 = c1.col2)
loop
insert into local.tab3 values (c1.col1,c1.col2,c2.col1,c2.col2);
end loop;
end loop;
end;
/

PL/SQL "WHERE CURRENT OF" vs "ROWID"

Why Oracle made "where current of" syntax when you can use "rowid"? Example:
BEGIN
FOR rec IN (SELECT t.column1, t.rowid rid FROM test_table) LOOP
UPDATE test_table tb SET column1 = some_function(rec.column1) WHERE tb.rowid = rec.rid;
END LOOP;
COMMIT;
END;
DECLARE
CURSOR cur IS SELECT t.column1 FROM test_table;
param1 test_table.column1%TYPE;
BEGIN
LOOP
FETCH cur INTO param1;
UPDATE test_table tb SET tb.column1 = some_function(param1) WHERE CURRENT OF cur;
EXIT WHEN cur%NOTFOUND;
END LOOP;
COMMIT;
END;
Where Current Of is used to identify LAST FETCHED ROW in cursor. It's more safe, because You have 100% confidence, that f.e. You updating LAST FETCHED ROW from curosr. With Rowids there's danger, because it's really easy to mess up something.
Using WHERE CURRENT OF clause without having FOR UPDATE clause mentioned in your SELECT statement could be risky. Reason behind that is when you are not applying FOR UPDATE clause then you are not exclusively placing Row level lock to those rows which you are intending to update in the following UPDATE DML. And hence it opens an opportunity for outside world of violating data consistency i.e. some other user from different session may be looking to UPDATE same rows of your targeted table.
Also, in you learn more about WHERE CURRENT OF clause you will notice that during this clause Oracle internally makes use of ROWID's only to reach/identify the rows which needs to be updated.
Hope it helps !! Happy Programming

How to create a table and insert in the same statement

I'm new to Oracle and I'm struggling with this:
DECLARE
cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO cnt FROM all_tables WHERE table_name like 'Newtable';
IF(cnt=0) THEN
EXECUTE IMMEDIATE 'CREATE TABLE Newtable ....etc';
END IF;
COMMIT;
SELECT COUNT(*) INTO cnt FROM Newtable where id='something'
IF (cnt=0) THEN
EXECUTE IMMEDIATE 'INSERT INTO Newtable ....etc';
END IF;
END;
This keeps crashing and gives me the "PL/SQL: ORA-00942:table or view does not exist" on the insert-line. How can I avoid this? Or what am I doing wrong? I want these two statements (in reality it's a lot more of course) in a single transaction.
It isn't the insert that is the problem, it's the select two lines before. You have three statements within the block, not two. You're selecting from the same new table that doesn't exist yet. You've avoided that in the insert by making that dynamic, but you need to do the same for the select:
EXECUTE IMMEDIATE q'[SELECT COUNT(*) FROM Newtable where id='something']'
INTO cnt;
SQL Fiddle.
Creating a table at runtime seems wrong though. You said 'for safety issues the table can only exist if it's filled with the correct dataset', which doesn't entirely make sense to me - even if this block is creating and populating it in one go, anything that relies on it will fail or be invalidated until this runs. If this is part of the schema creation then making it dynamic doesn't seem to add much. You also said you wanted both to happen in one transaction, but the DDL will do an implicit commit, you can't roll back DDL, and your manual commit will start a new transaction for the insert(s) anyway. Perhaps you mean the inserts shouldn't happen if the table creation fails - but they would fail anyway, whether they're in the same block or not. It seems a bit odd, anyway.
Also, using all_tables for the check could still cause this to behave oddly. If that table exists in another schema, you create will be skipped, but you select and insert might still fail as they might not be able to see, or won't look for, the other schema version. Using user_tables or adding an owner check might be a bit safer.
Try the following approach, i.e. create and insert are in two different blocks
DECLARE
cnt NUMBER;
BEGIN
SELECT COUNT (*)
INTO cnt
FROM all_tables
WHERE table_name LIKE 'Newtable';
IF (cnt = 0)
THEN
EXECUTE IMMEDIATE 'CREATE TABLE Newtable(c1 varchar2(256))';
END IF;
END;
DECLARE
cnt2 NUMBER;
BEGIN
SELECT COUNT (*)
INTO cnt2
FROM newtable
WHERE c1 = 'jack';
IF (cnt2 = 0)
THEN
EXECUTE IMMEDIATE 'INSERT INTO Newtable values(''jill'')';
END IF;
END;
Oracle handles the execution of a block in two steps:
First it parses the block and compiles it in an internal representation (so called "P code")
It then runs the P code (it may be interpreted or compiled to machine code, depending on your architecture and Oracle version)
For compiling the code, Oracle must know the names (and the schema!) of the referenced tables. Your table doesn't exist yet, hence there is no schema and the code does not compile.
To your intention to create the tables in one big transaction: This will not work. Oracle always implicitly commits the current transaction before and after a DDL statement (create table, alter table, truncate table(!) etc.). So after each create table, Oracle will commit the current transaction and starts a new one.

Different behavior for REF CURSOR between Oracle 10g and 11g when unique index present?

Description
I have an Oracle stored procedure that has been running for 7 or so years both locally on development instances and on multiple client test and production instances running Oracle 8, then 9, then 10, and recently 11. It has worked consistently until the upgrade to Oracle 11g. Basically, the procedure opens a reference cursor, updates a table then completes. In 10g the cursor will contain the expected results but in 11g the cursor will be empty. No DML or DDL changed after the upgrade to 11g. This behavior is consistent on every 10g or 11g instance I've tried (10.2.0.3, 10.2.0.4, 11.1.0.7, 11.2.0.1 - all running on Windows).
The specific code is much more complicated but to explain the issue in somewhat realistic overview: I have some data in a header table and a bunch of child tables that will be output to PDF. The header table has a boolean (NUMBER(1) where 0 is false and 1 is true) column indicating whether that data has been processed yet.
The view is limited to only show rows in that have not been processed (the view also joins on some other tables, makes some inline queries and function calls, etc). So at the time when the cursor is opened, the view shows one or more rows, then after the cursor is opened an update statement runs to flip the flag in the header table, a commit is issued, then the procedure completes.
On 10g, the cursor opens, it contains the row, then the update statement flips the flag and running the procedure a second time would yield no data.
On 11g, the cursor never contains the row, it's as if the cursor does not open until after the update statement runs.
I'm concerned that something may have changed in 11g (hopefully a setting that can be configured) that might affect other procedures and other applications. What I'd like to know is whether anyone knows why the behavior is different between the two database versions and whether the issue can be resolved without code changes.
Update 1: I managed to track the issue down to a unique constraint. It seems that when the unique constraint is present in 11g the issue is reproducible 100% of the time regardless of whether I'm running the real world code against the actual objects or the following simple example.
Update 2: I was able to completely eliminate the view from the equation. I have updated the simple example to show the problem exists even when querying directly against the table.
Simple Example
CREATE TABLE tbl1
(
col1 VARCHAR2(10),
col2 NUMBER(1)
);
INSERT INTO tbl1 (col1, col2) VALUES ('TEST1', 0);
/* View is no longer required to demonstrate the problem
CREATE OR REPLACE VIEW vw1 (col1, col2)
AS
SELECT col1, col2
FROM tbl1
WHERE col2 = 0;
*/
CREATE OR REPLACE PACKAGE pkg1
AS
TYPE refWEB_CURSOR IS REF CURSOR;
PROCEDURE proc1 (crs OUT refWEB_CURSOR);
END pkg1;
CREATE OR REPLACE PACKAGE BODY pkg1
IS
PROCEDURE proc1 (crs OUT refWEB_CURSOR)
IS
BEGIN
OPEN crs FOR
SELECT col1
FROM tbl1
WHERE col1 = 'TEST1'
AND col2 = 0;
UPDATE tbl1
SET col2 = 1
WHERE col1 = 'TEST1';
COMMIT;
END proc1;
END pkg1;
Anonymous Block Demo
DECLARE
crs1 pkg1.refWEB_CURSOR;
TYPE rectype1 IS RECORD (
col1 vw1.col1%TYPE
);
rec1 rectype1;
BEGIN
pkg1.proc1 ( crs1 );
DBMS_OUTPUT.PUT_LINE('begin first test');
LOOP
FETCH crs1
INTO rec1;
EXIT WHEN crs1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(rec1.col1);
END LOOP;
DBMS_OUTPUT.PUT_LINE('end first test');
END;
/* After creating this index, the problem is seen */
CREATE UNIQUE INDEX unique_col1 ON tbl1 (col1);
/* Reset data to initial values */
TRUNCATE TABLE tbl1;
INSERT INTO tbl1 (col1, col2) VALUES ('TEST1', 0);
DECLARE
crs1 pkg1.refWEB_CURSOR;
TYPE rectype1 IS RECORD (
col1 vw1.col1%TYPE
);
rec1 rectype1;
BEGIN
pkg1.proc1 ( crs1 );
DBMS_OUTPUT.PUT_LINE('begin second test');
LOOP
FETCH crs1
INTO rec1;
EXIT WHEN crs1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(rec1.col1);
END LOOP;
DBMS_OUTPUT.PUT_LINE('end second test');
END;
Example of what the output on 10g would be:
begin first test
TEST1
end first test
begin second test
TEST1
end second test
Example of what the output on 11g would be:
begin first test
TEST1
end first test
begin second test
end second test
Clarification
I can't remove the COMMIT because in the real world scenario the procedure is called from a web application. When the data provider on the front end calls the procedure it will issue an implicit COMMIT when disconnecting from the database anyways. So if I remove the COMMIT in the procedure then yes, the anonymous block demo would work but the real world scenario would not because the COMMIT would still happen.
Question
Why is 11g behaving differently? Is there anything I can do other than re-write the code?
This appears to be a bug discovered fairly recently. Metalink Bug 1045196 describes the exact problem. Hopefully a patch will be released soon. For those of you who can't get past the Metalink wall here are a few details:
Metalink
Bug 10425196: PL/SQL RETURNING REF CURSOR ACTS DIFFERENTLY ON 11.1.0.6 VS 10.2.0.5
Type: Defect
Severity: 2 - Severe Loss of Service
Status: Code Bug
Created: 22-Dec-2010
DIAGNOSTIC ANALYSIS from original case submission:
- 10.2.0.4 Windows Expected Behavior
- 10.2.0.5 Solaris Expected Behavior
- 11.1.0.6 Solaris Un-Expected Behavior
- 11.1.0.7 Windows Un-Expected Behavior
- 11.2.0.1 Solaris Un-Expected Behavior
- 11.2.0.2 Solaris Un-Expected Behavior
FURTHER DETAILS I can confirm:
- 10.2.0.3 Windows Expected Behavior
- 11.2.0.1 Windows Un-Expected Behavior
Additional Details
Changing the OPTIMIZER_FEATURES_ENABLE='10.2.0.4' parameter does not resolve the problem. So it seems to be related more to a design change in the 11g database engine rather than an optimizer tweak.
Code Workaround
This appears to be a result of the use of the index when querying the table and not the act of updating the table and/or committing. Using my example above, here are two ways to ensure the query does not use the index. Both may affect the performance of the query.
Affecting the performance of the query might be temporarily acceptable until a patch is released but I believe that using FLASHBACK as #Edgar Chupit suggested could affect the performance of the entire instance (or may not be available on some instances) so that option may not be acceptable for some. Either way, at this point in time code changes appear to be the only known workaround.
Method 1: Change your code to wrap the column in a function to prevent the unique index on this one column from being used. In my case this is acceptable because although the column is unique it will never contain lower case characters.
SELECT col1
FROM tbl1
WHERE UPPER(col1) = 'TEST1'
AND col2 = 0;
Method 2: Change your query to use a hint preventing the index from being used. You might expect the NO_INDEX(unique_col1) hint to work, but it does not. The RULE hint does not work. You can use the FULL(tbl1) hint but it's likely that this may slow down your query more than using method 1.
SELECT /*+ FULL(tbl1) */ col1
FROM tbl1
WHERE col1 = 'TEST1'
AND col2 = 0;
Oracle's Response and Proposed Workaround
Oracle support has finally responded with the following Metalink update:
Oracle Support - July 20, 2011 5:51:19 AM GMT-07:00 [ODM Proposed Solution(s)]
Development has reported this will be a significant issue to fix and
has suggested that the following workaround be applied:
edit init.ora/spfile with the following undocumented parameter:
"_row_cr" = false
Oracle Support - July 20, 2011 5:49:20 AM GMT-07:00 [ODM Cause Justification]
Development has determined this to be a defect
Oracle Support - July 20, 2011 5:48:27 AM GMT-07:00 [ODM Cause Determination]
Cause has been traced to a row source cursor optimization
Oracle Support - July 20, 2011 5:47:27 AM GMT-07:00 [ODM Issue Verification]
Development has confirmed this to be an issue in 11.2.0.1
After some further correspondence it sounds as though this isn't being treated as a bug so much as a design decision moving forward:
Oracle Support - July 21, 2011 5:58:07 AM GMT-07:00 [ODM Proposed Solution Justif]
From 10.2.0.5 onward (which includes 11.2.0.2) we have an optimization called
ROW CR it is only applicable to queries which use an unique index to
determine the row in the table.
A brief overview of this optimization is that we try to avoid rollbacks while
constructing a CR block if the present block has no uncommitted changes.
So the difference seen in 11.2.0.2 is because of this optimization. The
suggested workaround is to turn off of this optimization so that things will
work exactly as they used to work in 10.2.0.4
In our case, given our client environments and since it is isolated to a single stored procedure we will continue to use our code workaround to prevent any unknown instance-wide side effects from affecting other applications and users.
This is indeed strange issue, thanks for sharing!
It really looks like a behavior change in Oracle starting with Oracle 11.1 and there is even confirmed bug with similar issue on metalink (bug#10425196). Unfortunately at the moment there is no much information available on metalink on subject mater, but I've also opened SR with Oracle asking to provide more information.
While at the moment I can not provide you an explanation why it happens and if there is a (hidden) parameter that can reverse this behavior back to 10g style, I think I can provide you with workaround. You can use Oracle flashback query functionality to force Oracle to retrieve data as to expected point in time.
If you change your code as follows:
OPEN crs FOR
SELECT col1
>>> FROM vw1 as of scn dbms_flashback.get_system_change_number
WHERE col1 = 'TEST1';
then result should be the same as in 10g.
And this is simplified version of original test case:
SQL> drop table tbl1;
Table dropped
SQL> create table tbl1(col1 varchar2(10), col2 number);
Table created
SQL> create unique index tbl1_idx on tbl1(col1);
Index created
SQL> insert into tbl1(col1,col2) values('TEST1',0);
1 row inserted
SQL> DECLARE
2 cursor web_cursor is
3 SELECT col1
4 FROM tbl1
5 WHERE col2 = 0 and col1 = 'TEST1';
6
7 rec1 web_cursor%rowtype;
8 BEGIN
9 OPEN web_cursor;
10
11 UPDATE tbl1
12 SET col2 = 1
13 WHERE col1 = 'TEST1';
14
15 -- different result depending on commit!
16 commit;
17
18 DBMS_OUTPUT.PUT_LINE('Start');
19 LOOP
20 FETCH web_cursor
21 INTO rec1;
22
23 EXIT WHEN web_cursor%NOTFOUND;
24
25 DBMS_OUTPUT.PUT_LINE(rec1.col1);
26 END LOOP;
27 DBMS_OUTPUT.PUT_LINE('Finish');
28 END;
29 /
Start
Finish
PL/SQL procedure successfully completed
If you comment out commit on line 16 than the output will be:
Start
TEST1
Finish
PL/SQL procedure successfully completed
From Metalink (aka Oracle Support)
Status bug 10425196 : 92 - Closed, Not a Bug
PROBLEM:
When calling a stored procedure that returns a REF CURSOR, different behavior
is seen in 10.2.0.5 and earlier vs 11.1.0.6 and later databases.
Sequence Of Events
Call stored procedure passing in a Ref Cursor
Open Ref Cursor against TableA
Update some data inside TableA from inside the stored procedure
COMMIT the update
Procedure execution ends returning Ref Cursor back to caller
10.2.0.5 and Earlier
The returned cursor does not see the updated data as it was opened prior to
the data being updated. This is the expected behavior.
11.1.0.6 and Later
The returned cursor sees the updated data and returns the updated data which
is different than the 10.2.0.5 and earlier behavior.
DIAGNOSTIC ANALYSIS:
10.2.0.4 Windows Expected Behavior
10.2.0.5 Solaris Expected Behavior
11.1.0.6 Solaris Un-Expected Behavior
11.1.0.7 Windows Un-Expected Behavior
11.2.0.1 Solaris Un-Expected Behavior
11.2.0.2 Solaris Un-Expected Behavior
RELATED BUGS:
None found.
If it is necessary, you can revert back to the pre-10.2.0.5 behavior setting the following startup parameter and restart the database.
_row_cr = false

Resources