从12.1更新到Oracle 12.2后,表操作符出错(ORA-21700)

时间:2018-06-12 15:52:48

标签: sql oracle plsql oracle12c oracle-manageddataaccess

我们的Oracle数据库最近已从12.1.0.2更新为12.2.0.1 +补丁集更新20180417.

自更新以来,我们在调用plsql过程时遇到以下错误: ORA-21700:对象不存在或标记为删除

我们已经缩小了问题,这似乎是由在包中定义的关联数组上使用表运算符引起的。我的所有研究表明,我们正在做的是在12.1中引入的,并且仍应在12.2中工作。

以下是与相关类型定义失败的过程的简化版本。它是使用托管数据访问从c#代码调用的。

这是包中的关联数组类型定义:

TYPE NUMBER_ARRAY IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

这是一个失败的程序:

PROCEDURE GetReadingStatus(
  STATUSID_ARR IN NUMBER_ARRAY,
  P_RETURNS OUT SYS_REFCURSOR    
)
BEGIN
  OPEN P_RETURNS FOR
    SELECT * FROM READINGSTATUS rs
    WHERE rs.statusID IN (select * from table(STATUSID_ARR));
END;

如果移除select * from table(STATUSID_ARR)部分,则会运行。

在12.2中对关联数组使用表运算符是否存在问题?问题可能源于其他问题吗?

3 个答案:

答案 0 :(得分:1)

  

我的所有研究表明,我们正在做的事情是在12.1中介绍的   并且仍应在12.2中工作。

这是真的。在Oracle 12c之前,您不能在SQL块中的PLSQL语句范围内使用关联数组。但是,Oracle确保在引入新版本时,旧版本不会受到影响。我试着测试你的代码,并且我的工作正常。看起来问题在其他地方,使用C#时可能会出现问题。见下面的演示:

我的Oracle版本:

SQL> select * from v$version;

BANNER
------     
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

表格数据:

SQL>SELECT * from TEST;
  col
  ---
   1
   2
   3

<强> 包装:

--Package Specification
CREATE OR REPLACE PACKAGE TESTTT
AS
TYPE NUMBER_ARRAY IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

Procedure GetReadingStatus (
                          STATUSID_ARR IN NUMBER_ARRAY,
                          P_RETURNS OUT SYS_REFCURSOR    
                        );
END;
/
--Package Body
CREATE OR REPLACE PACKAGE BODY TESTTT
AS
PROCEDURE GetReadingStatus(
                          STATUSID_ARR IN NUMBER_ARRAY,
                          P_RETURNS OUT SYS_REFCURSOR    
                        )
Is                        
BEGIN
  OPEN P_RETURNS FOR
    SELECT * 
    FROM TEST 
    where col IN (SELECT * FROM TABLE(STATUSID_ARR));
END;
END TESTTT;

<强> 调用:

DECLARE
var  TESTTT.NUMBER_ARRAY;
v_out sys_refcursor;
num  NUMBER;

BEGIN

var(1):= '1';
var(2):= '2';

 TESTTT.GetReadingStatus(STATUSID_ARR=>var,
                         P_RETURNS =>v_out);

 Loop
 fetch v_out INTO num;
 exit WHEN v_out%notfound;
 dbms_output.put_line('Return From Procdure--'||num);
 end loop;

end;

<强> 输出:

Return From Procdure--1
Return From Procdure--2

答案 1 :(得分:1)

从Oracle 12c升级到19c后,我遇到了相同或类似的问题。我不确定为什么Oracle升级会引起问题,而且我也不太了解我的修复程序为什么起作用!

在我的存储过程中,将Oracle的TABLE函数应用于某些存储过程输入时,出现错误:“ ORA-21700:对象不存在或被标记为删除”。

但是,在将Oracle的TABLE函数应用于存储过程中的局部变量的地方,没有错误。因此,我的解决方法只是在使用TABLE函数之前将存储过程输入分配给局部变量,从而以某种方式解决了该问题!

CREATE OR REPLACE PACKAGE my_types IS
  TYPE integers IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
  TYPE reals    IS TABLE OF FLOAT INDEX BY BINARY_INTEGER;
END my_types;
/

CREATE OR REPLACE PROCEDURE order_list
(
  i_order_numbers  IN  my_types.integers,
  o_order_numbers  OUT my_types.integers,
  o_order_values   OUT my_types.reals
)
IS

  r_order_numbers  my_types.integers;

  CURSOR order_list_cur (p_order_numbers my_types.integers)
      IS
  SELECT order_number, order_value
    FROM orders
   WHERE order_number IN (SELECT * FROM TABLE(p_order_numbers))
  ;
  order_list_rec  order_list_cur%ROWTYPE;

  rec_no BINARY_INTEGER;

BEGIN

  r_order_numbers := i_order_numbers;

  rec_no := 0;

  OPEN order_list_cur(r_order_numbers);
  LOOP
    FETCH order_list_cur INTO order_list_rec;
    EXIT WHEN order_list_cur%NOTFOUND;
      rec_no := rec_no + 1;
       o_order_numbers(rec_no) := order_list_rec.order_number;
       o_order_values(rec_no) := order_list_rec.order_value;
  END LOOP;
  CLOSE order_list_cur;

END order_list;

答案 2 :(得分:0)

这个问题很像我的情况,当我在12.2中遇到相同的错误,但没有12.1时出现相同的错误。我已经发布了答案here,因为该答案是使用包而不是模式定义的类型。也许这个问题可以用同样的方法解决。只需尝试添加相同类型的temp变量并为其分配参数即可。