Oracle 打印记录类型表的值,而不知道记录的列名

Oracle 打印记录类型表的值,而不知道记录的列名,oracle,plsql,collections,nested-table,utl-file,Oracle,Plsql,Collections,Nested Table,Utl File,我创建了一个程序,它使用一个视图打印(到CSV中),该视图的所有记录。 任何用户都可以删除并重新创建该视图,因此其列结构可以更改 有没有办法将所有视图记录提取到集合中 并在不知道所有列名/不依赖列的情况下打印该集合的元素 如果有任何方法,那么当我们的表也有数百列时,就可以使用它。 这个问题已经问过我很多次了,但我找不到答案,现在每当我需要将不同的表假脱机到csv文件时,我都必须编辑我的过程 我通常用于假脱机的代码包含所有列名:- cursor c1 is select * from table

我创建了一个程序,它使用一个视图打印(到CSV中),该视图的所有记录。 任何用户都可以删除并重新创建该视图,因此其列结构可以更改

有没有办法将所有视图记录提取到集合中 并在不知道所有列名/不依赖列的情况下打印该集合的元素

如果有任何方法,那么当我们的表也有数百列时,就可以使用它。 这个问题已经问过我很多次了,但我找不到答案,现在每当我需要将不同的表假脱机到csv文件时,我都必须编辑我的过程

我通常用于假脱机的代码包含所有列名:-

cursor c1 is
select * 
from table1 nvr;
  
TYPE alldata_typ IS table of c1%rowtype;
    v_dta       alldata_typ;
  
BEGIN
  
  v_fname  := 'swe_WRF_.csv';

    v_file   := UTL_FILE.FOPEN('CDMP_OUT_DIR', v_fname, 'W');

    v_header :=  'FSA_CODE,FSA_NAME,PROVINCE,MAKE,SERIES,REPORT_YEAR,VEHICLE_COUNT';

    UTL_FILE.PUT_LINE(v_file, v_header);
  
  OPEN c1;
  loop
    FETCH c1 BULK COLLECT

     INTO v_dta LIMIT v_fetch_limit;

     exit when v_dta.count=0 ;

     
    FOR i IN 1..v_dta.count 
    LOOP

        UTL_FILE.PUT_LINE(v_file, 
                            v_dta(i).fsa_code ||', '||
                            v_dta(i).fsa_name ||', '||
                            v_dta(i).province ||', '||
                            v_dta(i).make ||', '||
                            v_dta(i).series ||', '||
                            v_dta(i).report_year ||','||
                            v_dta(i).vehicle_count
                            );

        v_count := v_count + 1;
end loop;
;

如果您使用的是UTL_文件,那么您将在数据库服务器上写入该文件。如果只是CSV,则可以使用调度程序直接从数据库运行SQL*Plus命令

这里有更多细节


但本质上,调度器可以运行SQL*Plus会话,该会话还支持输出上的CSV标记。对于更大的数据量,它可能比UTL_文件快得多。

您需要使用动态SQL将所有列生成csv。 我重写了你的代码如下。希望对你有用

declare
  v_cmd        varchar(4000);
  c1           SYS_REFCURSOR;
  v_tab_name   varchar2(100) := upper('TABLE_NAME');
  v_owner_name varchar2(100) := upper('OWNER_NAME');
  type record_type is record(
    line_data varchar2(4000));
  TYPE alldata_typ IS table of record_type;
  v_dta         alldata_typ;
  v_fname       varchar2(20);
  V_HEADER      varchar2(20);
  V_FETCH_LIMIT integer := 100;
  V_COUNT       integer;
BEGIN

  v_fname := 'swe_WRF_.csv';

  v_file   := UTL_FILE.FOPEN('CDMP_OUT_DIR', v_fname, 'W');

  select listagg(COLUMN_NAME, ',') within group(order by COLUMN_ID)
    into v_header --create header with all column
    from all_tab_columns
   where table_name = v_tab_name
     and OWNER = v_owner_name;

  UTL_FILE.PUT_LINE(v_file, v_header);

  select 'select ' || listagg(COLUMN_NAME, '||'', ''||') within group(order by COLUMN_ID) || ' as line_data from ' || v_tab_name
    into v_cmd --generate select statement
    from all_tab_columns
   where table_name = v_tab_name
     and OWNER = v_owner_name;

  OPEN c1 for v_cmd;
  loop
    FETCH c1 BULK COLLECT
    
      INTO v_dta LIMIT v_fetch_limit;
  
    exit when v_dta.count = 0;
  
    FOR i IN 1 .. v_dta.count LOOP
    
      UTL_FILE.PUT_LINE(v_file, 
                          v_dta(i).line_data
                         );
      --dbms_output.put_line(v_dta(i).line_data);
      v_count := v_count + 1;
    end loop;
  END LOOP;
end;

检查此。更好的一个来自我们的AskTom:)。事实上,我们仍然可以修改您的程序,但我建议按照AskTom的方式进行。干杯最简单的解决方案:使用@apc CSV工具需要花费大量时间来处理百万条记录,因此这不是一个可行的解决方案。感谢您的解决方案,但我没有这些特权:P