简体   繁体   English

Oracle 12c以一种奇怪的方式解释SQL(内部查询)

[英]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). 我们最近将Oracle数据库从10g迁移到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. 因此,我编写了一个查询,在数据库DDL中搜索要显示的特定文本,其中使用了特定的视图或函数。

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() . 因为我们的数据库中有'Body Type'对象,并且它们没有提供带有DBMS_METADATA.GET_DDL()的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. 我希望Oracle首先创建内部列表并仅使用剩余值来使用DBMS_METADATA.GET_DLL()函数,因为相同的值将导致异常。 Why is Oracle doing something else here? 为什么Oracle在这里做其他事情?

To solve that particular issue I have to add an ORDER BY in the inner query what looks stupid to me. 要解决这个特定的问题,我必须在内部查询中添加一个看起来很愚蠢的ORDER BY Why do I have to force Oracle to create an inner query first with using an ORDER BY ? 为什么我必须首先使用ORDER BY强制Oracle创建内部查询?

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. - 我记得,后来的查询在Oracle 10g上运行没有任何问题。
(I'm worried to have the same behavior on other reports that do calculation which might be wrong because of that behavior!). (我担心在其他报告中会有相同的行为,因为这种行为可能会导致计算错误!)。

It's a bug. 这是一个错误。 Oracle Support just confirmed to me that the exception occures due to a bug in Oracle Version 12.1.0. Oracle Support刚刚向我确认由于Oracle Version 12.1.0中的错误而发生异常。 1 only. 仅限1

There are two options to choose from: 有两种选择可供选择:
1) update to Oracle Version 12.1.0. 1)更新到Oracle Version 12.1.0。 2 and the bug is fixed. 2 ,错误是固定的。
2) wait a couple weeks for a patch that Oracle is starting to work on soon. 2)等待几周的Oracle即将开始工作的补丁。 The patch will fix this issue in Oracle Version 12.1.0. 该补丁将在Oracle Version 12.1.0中解决此问题。 1 . 1

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. 我们没有决定采用哪种方案,但我非常有信心,因为Oracle支持确实重现了我的问题,所以其中一种方法可行。

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. 通过使用ROWNUM您将强制它首先评估内部记录集。 It's not the ORDER BY its the ROWNUM doing that. 这不是ROWNUMORDER BY 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. 除了ORDER BY您还可以执行AND ROWNUM > 0并且它将执行相同的操作,因为它必须在评估ROWNUM表达式之前评估每一行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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