4

我正在尝试在 IN 子句中将一组输入值用于我的过程,作为游标 where 子句的一部分。我知道以前有人问过这个问题,但是我还没有看到如何使我的语法正确编译。

在封装规范中,类型为

TYPE t_brth_dt IS TABLE OF sourceTable.stdt_brth_dt%TYPE INDEX BY PLS_INTEGER;

sourceTable.std_brth_dt是表中的日期列。

我的光标的简化版本在包体中是 -

 cursor DataCursor_Sort( p_brth_dt in t_brth_dt) is
    SELECT *
      FROM sourceTable 
     WHERE a.brth_dt IN (select column_value 
                           from table(p_brth_dt))

当我尝试编译它时,我收到以下错误。

  • [1]:(错误):PLS-00382:表达式类型错误
  • [2]:(错误): PL/SQL: ORA-22905: 无法访问非嵌套表项中的行

我知道这看起来与其他问题相似,但我不明白语法错误是什么。

4

3 回答 3

4

为了在from查询的子句中使用定义为嵌套表或关联数组的集合,正如@Alex Poole 正确指出的那样,您应该创建一个模式级别(SQL)类型或使用一个,您可以通过ODCIConst包 -odcidatelist因为您打算使用日期列表。例如,您的游标定义可能如下所示:

cursor DataCursor_Sort(p_brth_dt in sys.odcidatelist) is
  select *
    from sourceTable 
   where a.brth_dt IN (select column_value 
                         from table(p_brth_dt))

或者

cursor DataCursor_Sort(p_brth_dt in sys.odcidatelist) is
  select s.*
    from sourceTable      s
    join table(p_brth_dt) t
      on (s.brth_dt = t.column_value)

注意:在执行日期比较时,您应该考虑日期的时间部分。如果您只想比较日期部分,则使用trunc()函数摆脱时间部分可能会很有用。

于 2013-09-24T19:12:59.247 回答
2

可以在 PL/SQL 包中的语句的子句中间接使用 PL/SQL 定义的嵌套表类型(与 SQL 定义的嵌套表类型相反) 。您必须使用函数作为中介。写起来感觉有点聪明,但我不相信它的基本用途。INSELECTPIPELINED

CREATE OR REPLACE PACKAGE so18989249 IS

   TYPE date_plsql_nested_table_type IS TABLE OF DATE;
   dates date_plsql_nested_table_type;

   FUNCTION dates_pipelined RETURN date_plsql_nested_table_type PIPELINED;

   PROCEDURE use_plsql_nested_table_type;

END so18989249;
/

CREATE OR REPLACE PACKAGE BODY so18989249 IS

   FUNCTION dates_pipelined RETURN date_plsql_nested_table_type
      PIPELINED IS
   BEGIN
      IF (dates.count > 0)
      THEN
         FOR i IN dates.first .. dates.last
         LOOP
            IF (dates.exists(i))
            THEN
               PIPE ROW(dates(i));
            END IF;
         END LOOP;
      END IF;
   END;

   PROCEDURE use_plsql_nested_table_type IS
   BEGIN
      dates := NEW date_plsql_nested_table_type();

      -- tweak these values as you see fit to produce the dbms_output results you want
      dates.extend(5);
      dates(1) := DATE '2013-12-25';
      dates(2) := DATE '2013-01-01';
      dates(3) := DATE '2013-07-01';
      dates(4) := DATE '2013-09-03';
      dates(5) := DATE '2008-11-18';

      FOR i IN (SELECT o.owner,
                       o.object_name,
                       o.object_type,
                       to_char(o.last_ddl_time, 'YYYY-MM-DD') AS last_ddl
                  FROM all_objects o
                 WHERE trunc(o.last_ddl_time) IN 
                       (SELECT column_value FROM TABLE(dates_pipelined)) 
                       --uses pipeline function which uses pl/sql-defined nested table
      )
      LOOP
         dbms_output.put_line('"' || i.owner || '"."' || i.object_name || '" ("' || i.object_type || ') on ' || i.last_ddl);
      END LOOP;

   END;

END so18989249;
/

begin so18989249.use_plsql_nested_table_type; end;
/
于 2013-10-02T21:36:12.627 回答
1

The type has to be created at SQL level, not in a package. An SQL query doesn't know how to use any types defined in PL/SQL. So you'd have to do:

CREATE OR REPLACE TYPE t_brth_dt IS TABLE OF date;
/

... and remove the type from your package specification. (Or give them different names, at least, and they won't be interchangeable in use). Because it's at SQL level, you also can't use sourceTable.stdt_brth_dt%TYPE in the declaration, unfortunately.

于 2013-09-24T18:35:53.627 回答