“ORA-00902:无效数据类型”的运行时错误我做错了什么?

问题描述 投票:0回答:1

我有一个从 Web 服务调用的包/过程。它返回一个引用器。 我正在尝试优化过滤,因为它实际上有很多过滤选项,下面只是一个小例子。这是为了限制以后使用的记录。

我收到运行时错误: 第 1 行错误 ORA-00902: 无效的数据类型 ORA-06512: 在“MARK.PKG_PRODUCTS”,第 13 行 ORA-06512: 在第 9 行 当它只是一个 select 语句时它有效,但是当我将其更改为插入到表中时,我现在收到此错误。

如下设置和打包

CREATE TABLE PRODUCTS (PRODUCT_ID VARCHAR2(10), VENDOR VARCHAR2(10), ITEM VARCHAR(10));
CREATE TABLE PRODUCT_FILTER (PRODUCT_ID VARCHAR2(10));
CREATE TABLE PRODUCT_LOG (LOG_DATE DATE, LOG_TEXT VARCHAR2(4000));

CREATE OR REPLACE PACKAGE PKG_PRODUCTS AS
  TYPE t_filter IS TABLE OF VARCHAR2(250)
    INDEX BY BINARY_INTEGER;

  PROCEDURE SET_FILTER(p_vendor IN t_filter, p_item IN t_filter);
END PKG_PRODUCTS;
/

CREATE OR REPLACE PACKAGE BODY PKG_PRODUCTS AS
  PROCEDURE SET_FILTER(p_vendor IN t_filter, p_item IN t_filter)
  IS
  v_text VARCHAR2(4000);
  
  BEGIN
    SELECT LISTAGG(Column_Value, ', ' ON OVERFLOW TRUNCATE '...' WITHOUT COUNT) WITHIN GROUP (ORDER BY 1) INTO v_text FROM TABLE(p_vendor);
    INSERT INTO PRODUCT_LOG (LOG_DATE, LOG_TEXT) VALUES (SYSDATE, 'p_vendor:'||v_text);

    SELECT LISTAGG(Column_Value, ', ' ON OVERFLOW TRUNCATE '...' WITHOUT COUNT) WITHIN GROUP (ORDER BY 1) INTO v_text FROM TABLE(p_item);
    INSERT INTO PRODUCT_LOG (LOG_DATE, LOG_TEXT) VALUES (SYSDATE, 'p_item:'||v_text);

    INSERT INTO PRODUCT_FILTER (PRODUCT_ID)
      SELECT PRODUCT_ID FROM PRODUCTS
        WHERE
            (p_vendor(1) IS NULL 
            OR VENDOR IN (SELECT * FROM TABLE(p_vendor)))
          AND
            (p_item(1) IS NULL
            OR ITEM IN (SELECT * FROM TABLE(p_item)));
  END SET_FILTER;
END PKG_PRODUCTS;
/
-- To run 
declare
  P_VENDOR PKG_PRODUCTS.t_filter;
  P_ITEM PKG_PRODUCTS.t_filter;

begin
  P_VENDOR(1) := 'Vendor1';
  P_ITEM(1) := 'Item1';

  PKG_PRODUCTS.SET_FILTER(
      P_VENDOR,
      P_ITEM
  );
end;

我在运行时收到此错误: 第 1 行错误 ORA-00902: 无效的数据类型 ORA-06512: 在“MARK.PKG_PRODUCTS”,第 13 行 ORA-06512: 在第 9 行

我正在使用 Oracle 19c

如有任何帮助,我们将不胜感激

我已将错误限制为“OR VENDOR IN (SELECT * FROM TABLE(p_vendor)))”,但无法找出确切的原因。

oracle plsql plsql-package
1个回答
0
投票
TYPE t_filter IS TABLE OF VARCHAR2(250) INDEX BY BINARY_INTEGER;

声明一个 PL/SQL 关联数组。它不能在 SQL 语句中使用 - 只能在 PL/SQL 语句中使用。

如果您想使用集合,请使用嵌套表类型(或

VARRAY
)并在 SQL 范围中定义它。

CREATE TYPE varchar2_250_list IS TABLE OF VARCHAR2(250);

然后:

CREATE OR REPLACE PACKAGE PKG_PRODUCTS AS
  PROCEDURE SET_FILTER(
    p_vendor IN varchar2_250_list,
    p_item   IN varchar2_250_list
  );
END PKG_PRODUCTS;
/

CREATE OR REPLACE PACKAGE BODY PKG_PRODUCTS AS
  PROCEDURE SET_FILTER(
    p_vendor IN varchar2_250_list,
    p_item   IN varchar2_250_list
  )
  IS
    v_text VARCHAR2(4000);
  
  BEGIN
    INSERT INTO PRODUCT_LOG (LOG_DATE, LOG_TEXT)
      SELECT SYSDATE,
             'p_vendor:'
             || LISTAGG(Column_Value, ', ' ON OVERFLOW TRUNCATE '...' WITHOUT COUNT) WITHIN GROUP (ORDER BY 1)
      FROM   TABLE(p_vendor);


    INSERT INTO PRODUCT_LOG (LOG_DATE, LOG_TEXT)
      SELECT SYSDATE,
             'p_item:'
             ||LISTAGG(Column_Value, ', ' ON OVERFLOW TRUNCATE '...' WITHOUT COUNT) WITHIN GROUP (ORDER BY 1)
      FROM   TABLE(p_item);

    INSERT INTO PRODUCT_FILTER (PRODUCT_ID)
      SELECT PRODUCT_ID
      FROM   PRODUCTS
      WHERE  ( p_vendor IS EMPTY
               OR VENDOR MEMBER OF p_vendor)
      AND    ( p_item IS EMPTY
               OR ITEM MEMBER OF p_item);
  END SET_FILTER;
END PKG_PRODUCTS;
/

注意:如果您决定使用

VARRAY
(而不是嵌套表类型),则
VARRAY
不支持
MEMBER OF
运算符。

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.