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

时间:2015-10-29 10:56:44

标签: sql oracle oracle12c dbms-metadata

我们最近将Oracle数据库从10g迁移到12c(12.1.0.1.0)。在考虑了某些查询的问题之后,我们决定进一步清理数据库并删除所有不需要的对象 因此,我编写了一个查询,在数据库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%')

这会导致以下异常:

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.

因为我们有'身体类型'我们的数据库中的对象并没有提供带有DBMS_METADATA.GET_DDL()的ddl。运行下面的查询会显示与初始查询完全相同的异常。

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

所以,我尝试创建一个内部列表,首先将所有用户对象的列表减少到我真正关心的一次,重写我的查询如下:

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%')

有趣的是,它带来了如上所示的相同异常。我不明白为什么会这样。

我希望Oracle首先创建内部列表并仅使用剩余值使用DBMS_METADATA.GET_DLL()函数,因为相同的值将导致异常。为什么Oracle在这里做其他事情?

要解决这个特定问题,我必须在内部查询中添加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%')

提前感谢有关为何会发生这种情况的任何解释? - 我记得,后来的查询在Oracle 10g上运行时没有任何问题 (我担心在其他报告上会有相同的行为,因为这种行为可能会导致错误计算!)。

2 个答案:

答案 0 :(得分:2)

这是一个错误。 Oracle Support刚刚向我确认,由于Oracle Version 12.1.0中的错误而发生异常。 1

有两种选择可供选择:
1)更新到Oracle Version 12.1.0。 2 并修复了错误 2)等待几周的Oracle即将开始工作的补丁。该补丁将在Oracle Version 12.1.0中修复此问题。 1
我们没有决定采用哪种方案,但我非常有信心,因为Oracle Support确实重现了我的问题,所以其中一种方法可以正常工作。

答案 1 :(得分:1)

很可能是谓词推(我找不到一个简单的解释抱歉)

首先不运行内部记录集然后评估余数。它正在推动外部进入内部派生表。查询计划会告诉您。

通过使用ROWNUM,您首先强制它评估内部记录集。它不是ORDER BY ROWNUM那样做的。而不是ORDER BY你也可以做AND ROWNUM > 0而它会做同样的事情,因为它必须在评估ROWNUM表达式之前评估每一行。