ORA-22905 - 为表运算符使用DBMS_SQL.Number_Table时

时间:2018-02-13 16:33:36

标签: oracle plsql oracle12c

所有

这是我试图完成的简化版本。我没有声明自己的类型,而是使用了dbms_sql包中的Number_Table类型。 首先,我创建了一个简单的测试表:

CREATE TABLE collect_test(id NUMBER(38), other_info VARCHAR2(5));

然后,用少量数据填充表格:

INSERT INTO collect_test
SELECT rownum, chr(rownum+60)
FROM dual
CONNECT BY rownum <= 10;

最后,我尝试使用PL / SQL在集合中选择一些行,然后使用该集合从表中删除行:

DECLARE
  l_tIDList DBMS_SQL.Number_Table;
BEGIN
  SELECT ct.id
  BULK COLLECT INTO l_tIDList
  FROM collect_test ct
  WHERE mod(ct.id, 2) = 0;

  DELETE FROM (SELECT ct.id
               FROM collect_test ct
               INNER JOIN table(l_tIDList) ids ON ct.id = ids.column_value);

  ROLLBACK;
END;
/

但是,当我运行此PL / SQL块时,我收到以下错误:

ORA-06550: line 11, column 33:
PLS-00382: expression is of wrong type 
ORA-06550: line 11, column 27:
PL/SQL: ORA-22905: cannot access rows from a non-nested table item
ORA-06550: line 9, column 3: PL/SQL: SQL Statement ignored

在我发现的所有其他问题/文章中,似乎编码器要么尝试使用本地类型,要么忘记使用BULK COLLECT。我感谢你提出的任何建议。

N.B。:我意识到我可以使用单个DELETE语句来执行此特定功能。我的实际情况更复杂,无法用一个语句完成。

2 个答案:

答案 0 :(得分:0)

我用光标尝试了这个,它对我有用。请尝试如下。

    DECLARE
      l_tIDList DBMS_SQL.Number_Table;
      CURSOR c
      IS
        SELECT ct.id FROM collect_test ct WHERE mod(ct.id, 2) = 0;
    BEGIN
      OPEN c;
      LOOP
    FETCH c bulk collect INTO l_tIDList;
    forall i IN 1 .. l_tIDList.count
    DELETE FROM collect_test t WHERE t.id = l_tIDList(i);
    EXIT
  WHEN c%notfound;
  END LOOP;
  COMMIT;
  CLOSE c;
END ;
/ 

答案 1 :(得分:0)

虽然目前还不清楚你要完成什么,但你的pl / sql块有两个错误。

  • 您可以对集合的变量使用TABLE()函数 模式中定义的类型,而不是本地定义的类型

  • 运行DML(删除)语句的方式是错误的,它会抛出错误“

  

ORA-22841:不支持PL / SQL集合上的DML。

因此,在模式中创建一个集合TYPE,并在PL / SQL块中声明该类型的集合,并为删除使用IN条件

CREATE OR REPLACE TYPE idlisttable as TABLE OF NUMBER;

DECLARE l_tidlist idlisttable;

BEGIN
    SELECT ct.id BULK collect
    INTO l_tidlist
    FROM collect_test ct
    WHERE MOD(ct.id, 2) = 0;

    DELETE
    FROM collect_test ct
    WHERE ct.id IN (
            SELECT ids.column_value
            FROM TABLE (l_tidlist) ids
            );

    ROLLBACK;
END;
/

`