从Oracle表变量/数组中选择值?

Son*_*Boy 11 oracle plsql

继我的上一个问题(Oracle PL/SQL中的表变量?)之后......

一旦你有一个数组/表中的值,你如何让它们再次退出?最好使用select语句或类似的东西?

这是我到目前为止所得到的:

declare
    type array is table of number index by binary_integer;
    pidms array;
begin
    for i in    (
                select distinct sgbstdn_pidm
                from sgbstdn
                where sgbstdn_majr_code_1 = 'HS04'
                and sgbstdn_program_1 = 'HSCOMPH'
                )
    loop
        pidms(pidms.count+1) := i.sgbstdn_pidm;
    end loop;

    select *
    from pidms; --ORACLE DOESN'T LIKE THIS BIT!!!
end;
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用dbms_output.putline()输出它们,但我希望得到一个像我从任何其他表中选择的结果集.

先谢谢,马特

Pau*_*ulJ 15

您可能需要一个GLOBAL TEMPORARY TABLE.

在Oracle中,这些是一次创建的,然后在调用时,数据对您的会话是私有的.

Oracle文档链接

尝试这样的事......

CREATE GLOBAL TEMPORARY TABLE temp_number
   ( number_column   NUMBER( 10, 0 )
   )
   ON COMMIT DELETE ROWS;

BEGIN 
   INSERT INTO temp_number
      ( number_column )
      ( select distinct sgbstdn_pidm 
          from sgbstdn 
         where sgbstdn_majr_code_1 = 'HS04' 
           and sgbstdn_program_1 = 'HSCOMPH' 
      ); 

    FOR pidms_rec IN ( SELECT number_column FROM temp_number )
    LOOP 
        -- Do something here
        NULL; 
    END LOOP; 
END; 
/
Run Code Online (Sandbox Code Playgroud)

  • 链接已经死了 (2认同)

Dav*_*sta 11

在Oracle中,PL/SQL和SQL引擎保持一定的分离.当您在PL/SQL中执行SQL语句时,它将被传递给SQL引擎,而SQL引擎不了解像INDEX BY表这样的PL/SQL特定结构.

因此,您需要在数据库模式中创建等效的集合类型,而不是在PL/SQL块中声明类型:

CREATE OR REPLACE TYPE array is table of number;
/
Run Code Online (Sandbox Code Playgroud)

然后你可以在PL/SQL中的这两个例子中使用它:

SQL> l
  1  declare
  2    p  array := array();
  3  begin
  4    for i in (select level from dual connect by level < 10) loop
  5      p.extend;
  6      p(p.count) := i.level;
  7    end loop;
  8    for x in (select column_value from table(cast(p as array))) loop
  9       dbms_output.put_line(x.column_value);
 10    end loop;
 11* end;
SQL> /
1
2
3
4
5
6
7
8
9

PL/SQL procedure successfully completed.

SQL> l
  1  declare
  2    p  array := array();
  3  begin
  4    select level bulk collect into p from dual connect by level < 10;
  5    for x in (select column_value from table(cast(p as array))) loop
  6       dbms_output.put_line(x.column_value);
  7    end loop;
  8* end;
SQL> /
1
2
3
4
5
6
7
8
9

PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)

基于评论的附加示例

根据您对我的答案和问题本身的评论,我认为这是我实施它的方式.使用包,以便可以从实际表中获取记录一次并存储在私有包全局中; 并有一个返回打开引用游标的函数.

CREATE OR REPLACE PACKAGE p_cache AS
  FUNCTION get_p_cursor RETURN sys_refcursor;
END p_cache;
/

CREATE OR REPLACE PACKAGE BODY p_cache AS

  cache_array  array;

  FUNCTION get_p_cursor RETURN sys_refcursor IS
    pCursor  sys_refcursor;
  BEGIN
    OPEN pCursor FOR SELECT * from TABLE(CAST(cache_array AS array));
    RETURN pCursor;
  END get_p_cursor;

  -- Package initialization runs once in each session that references the package
  BEGIN
    SELECT level BULK COLLECT INTO cache_array FROM dual CONNECT BY LEVEL < 10;
  END p_cache;
/
Run Code Online (Sandbox Code Playgroud)