Oracle:将Cursor转换为TABLE以进行连接

时间:2018-01-15 15:42:50

标签: sql oracle plsql cursor sys-refcursor

我有树不同的表,等于数据类型。

我必须假脱机文件,但首先我必须将每个表连接到其他表并创建带有结果的文件。

示例:

TAB1

ID|CODE
-------
1 | A
2 | B
3 | A

TAB2

ID|CODE
-------
1 | C
2 | C
3 | A

TAB3

ID|CODE
-------
1 | C
2 | B
3 | B

NOM_CODES

CODE|DESC
A   | desc1
B   | desc1
C   | desc1
D   | desc1

这是树之一(每个表一个)程序:

procedure proc_tab1 is

  l_File_Handle Utl_File.File_Type;
  v_File_Name   VARCHAR2(100);

begin
  v_File_Name := 'TAB_1.TXT';

  IF Utl_File.Is_Open(l_File_Handle) THEN
    Utl_File.Fclose(l_File_Handle);
  END IF;

  l_File_Handle := Utl_File.Fopen(l_DIR, v_File_Name, 'W', l_Len);

  for c in (select t.ID||','||t.code||','||c.desc
            from tab1 t
            join nom_codes c
              on t.code = c.code) loop
    Utl_File.Put_Line(l_File_Handle,
                      Convert(c.file_line, 'CL8MSWIN1251') || l_cr);
  end loop;

  Utl_File.Fclose(l_File_Handle);

end proc_tab1 ;   

我想在一个新程序中重复(打开文件,加入,put_line,关闭文件)。

这样的事情:

procedure proc_tab1 is

  v_File_Name   VARCHAR2(100);

begin
  v_File_Name := 'TAB_1.TXT';

  spool_file(v_File_Name, cursor(select t.id, t.code from t1));

end proc_tab1 ;  

这个新程序:

procedure spool_file (p_file_name varchar2, p_curr sys_refcursor) is

  l_File_Handle Utl_File.File_Type;

begin 

  IF Utl_File.Is_Open(l_File_Handle) THEN
    Utl_File.Fclose(l_File_Handle);
  END IF;
l_File_Handle := Utl_File.Fopen(l_DIR, p_file_name , 'W', l_Len);

  for c in (select t.ID||','||t.code||','||c.desc
            from table(p_curr) t
            join nom_codes c
              on t.code = c.code) loop
    Utl_File.Put_Line(l_File_Handle,
                      Convert(c.file_line, 'CL8MSWIN1251') || l_cr);
  end loop;

  Utl_File.Fclose(l_File_Handle);
end spool_file ;

我想以某种方式将行集从 tab1 (以及tab2和tab3)传递给 spool_file 。在spool_file中将此行集转换为表并使其连接和其他常见的思考。

实际上我尝试了这个但是我无法将SYS_REFCURSOR转换为TABLE。我可以创建一个返回流水线结果的函数,但我认为这不是一个好主意,因为我将不得不对数据进行两次迭代(一个用于管道,一个用于循环)。

我愿意接受想法。

1 个答案:

答案 0 :(得分:1)

你可以在Oracle中做一些疯狂的事情,但这通常意味着架构是错误的:

declare
    l_cur1 SYS_REFCURSOR;
    l_cur2 SYS_REFCURSOR;
begin
--test data
open l_cur1 for select 1 id, 'A' code from dual union all select 2 id, 'B' code from dual;
open l_cur2 for select 'A' code, 'A-VALUE' name from dual union all select 'B' code, 'B-VALUE' name from dual;

--convert cursors in xml and parse and joins
for c in ( 
    select tab1.id, tab1.code, tab2.NAME
    from ( 
            select extractvalue( value( src1 ), 'ROW/ID' ) ID, extractvalue( value( src1 ), 'ROW/CODE' ) CODE 
            from table( xmlsequence( xmltype( l_cur1 ).extract( 'ROWSET/ROW' ) ) ) src1 ) tab1
    left join (
            select extractvalue( value( src2 ), 'ROW/CODE' ) CODE, extractvalue( value( src2 ), 'ROW/NAME' ) NAME 
            from table( xmlsequence( xmltype( l_cur2 ).extract( 'ROWSET/ROW' ) ) ) src2 ) tab2 on tab1.CODE = tab2.CODE
) 
loop
        dbms_output.put_line( c.id );
        dbms_output.put_line( c.code );
        dbms_output.put_line( c.name );
        dbms_output.put_line( '---------------' );
end loop;

end;