简体   繁体   中英

Oracle 12c interprets SQL in a strange way (Inner Query)

We've recently migrated our Oracle database from 10g to 12c (12.1.0.1.0). After considering an issue with some queries we deceided to further clean up the database and drop all unneeded objects.
Therefore I wrote a query that searches the database DDL for a certain text to show up, where a particular view or function is used.

SELECT 
  object_name, object_type, DBMS_METADATA.GET_DDL(object_type, object_name) as ddl_txt 
FROM user_objects 
WHERE object_type IN ( 'FUNCTION', 'VIEW', 'PROCEDURE', 'TRIGGER') 
  AND UPPER( DBMS_METADATA.GET_DDL(object_type, object_name) ) LIKE upper('%myFunction%')

This results in the following exception:

ORA-31600: invalid input value TYPE BODY for parameter OBJECT_TYPE in function GET_DDL
ORA-06512: at "SYS.DBMS_METADATA", line 5746
ORA-06512: at "SYS.DBMS_METADATA", line 8333
ORA-06512: at line 1
31600. 00000 -  "invalid input value %s for parameter %s in function %s"
*Cause:    A NULL or invalid value was supplied for the parameter.
*Action:   Correct the input value and try the call again.

The exeption occures because we have 'Body Type' objects in our database and they do not provide a ddl with the DBMS_METADATA.GET_DDL() . Running the query below brings out the exact same exception as from the initial query.

select dbms_metadata.get_ddl('TYPE BODY', 'myBodyStringType') from dual

So, I try to create an inner list to first reduce the list of all user object to the once I do really care by rewriting my query as followed:

select
  lst.*,
  DBMS_METADATA.GET_DDL(lst.object_type, lst.object_name) as ddl_txt 
from (
      SELECT 
        object_name, object_type
      FROM user_objects 
      WHERE object_type IN ( 'FUNCTION', 'VIEW', 'PROCEDURE', 'TRIGGER') 
) lst
where upper(DBMS_METADATA.GET_DDL(lst.object_type, lst.object_name)) like upper('%myFunction%')

The funny point is, that it brings out the same exception as shown above. I do not understand why that happens.

I expect Oracle to create the inner list first and consume the DBMS_METADATA.GET_DLL() function only with the remaining values since same values will result in an exception. Why is Oracle doing something else here?

To solve that particular issue I have to add an ORDER BY in the inner query what looks stupid to me. Why do I have to force Oracle to create an inner query first with using an ORDER BY ?

select
  lst.*,
  DBMS_METADATA.GET_DDL(lst.object_type, lst.object_name) as ddl_txt 
from (
      SELECT 
        object_name, object_type
      FROM user_objects 
      WHERE object_type IN ( 'FUNCTION', 'VIEW', 'PROCEDURE', 'TRIGGER')
      ORDER BY ROWNUM ASC
) lst
where upper(DBMS_METADATA.GET_DDL(lst.object_type, lst.object_name)) like upper('%myFunction%')

Thanks in advance for any explanation on why that happens? - I have in mind, that the later query was running without any issues on Oracle 10g.
(I'm worried to have the same behavior on other reports that do calculation which might be wrong because of that behavior!).

Oracle Support just confirmed to me that the exception occures due to a bug in Oracle Version 12.1.0. only.

There are two options to choose from:
1) update to Oracle Version 12.1.0. and the bug is fixed. ,错误是固定的。
2) wait a couple weeks for a patch that Oracle is starting to work on soon. The patch will fix this issue in Oracle Version 12.1.0. .

We did not decided which option we are taking, but I'm very confident that one or the other will work since Oracle Support did reproduce my problem.

Most likely it's predicate pushing (I can't find a simple explanation sorry)

It's not running the inner recordset first then evaluating the remainder. It's pushing the outside where into the inside derived table. The query plan will tell you for sure.

By using ROWNUM you're forcing it to evaluate the inner recordset first. It's not the ORDER BY its the ROWNUM doing that. Instead of ORDER BY you could also do AND ROWNUM > 0 and it would do the same thing because it has to evaluate every row before it can evaluate the ROWNUM expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM