自动 CSV 文件生成,在 Oracle 10g 中具有不同列数的两个标题级别的标题

Posted

技术标签:

【中文标题】自动 CSV 文件生成,在 Oracle 10g 中具有不同列数的两个标题级别的标题【英文标题】:Automatic CSV file generation, with header in two title levels with different number of columns with Oracle 10g 【发布时间】:2021-04-09 21:38:00 【问题描述】:

我们有一个使用 Oracle 10g R. 10.2.0.4.0 的应用程序。我需要创建一个过程,将给定查询的数据导出到特定布局的 CSV 文件中,以便可以将其导入到另一个应用程序中。

我发现以下链接对我有很大帮助。此过程使用utl_file 并允许我将所需的查询放在l_query 字段中。

Export to CSV - By Ask TOM

我需要生成的文件结构如下:

Title;9999
FIELD1;FIELD2;FIELD3;FIELD4;FIELD5
1234;30032021;0400;093000;123000
1235;30032021;0400;133000;183000

我在两个级别中创建了标题,一个是为包含两个字段的文件添加标题,另一个是应用程序将加载的数据列的标题。我使用UNION ALL 实现了这一点。但是,我发现了两个我无法解决的问题:

    我无法从查询块中删除标题

    当我使用UNION ALL 时,第一个阻塞查询迫使我拥有在以下查询中生成信息所需的字段数(五个字段),因此生成的文件有两个标题,在第二个中生成三个我需要删除的;;;

    标题;9999;'';'';''; --我需要删除这个标题 职称;9999; ; ; --我需要去掉三个“;;;” 字段 1;字段 2;字段 3;字段 4;字段 5 1234;08042021;123;224130;044130 1235;08042021;123;224130;044130 1236;08042021;123;224130;044130

这是我使用在变量 l_query 中创建的查询调整的过程。

create or replace procedure dump_table_to_csv(p_dir in varchar2, p_filename in varchar2 )
is
l_output utl_file.file_type;
l_theCursor integer default dbms_sql.open_cursor;
l_columnValue varchar2(4000);
l_status integer;
l_query varchar2(4000)
default 
  'SELECT ''Title'' AS "Title",  ''9999'' AS "9999" , '' '', '' '', '' ''  from DUAL 
   UNION ALL
   SELECT TO_CHAR(''FIELD1'') AS FIELD1, TO_CHAR(''FIELD2'') AS FIELD2, TO_CHAR(''FIELD3'') AS FIELD3, TO_CHAR(''FIELD4'') AS FIELD4, TO_CHAR(''FIELD5'') AS FIELD5 FROM DUAL
   UNION ALL
   SELECT
   TO_CHAR(''9999'') AS FIELD1
   ,TO_CHAR(SYSDATE, ''DDMMYYYY'') AS FIELD2 
   ,''123'' AS FIELD3
   ,LPAD(TO_CHAR(SYSDATE, ''HH24MISS''), 6, 0) AS FIELD4
   ,LPAD(TO_CHAR(SYSDATE + INTERVAL ''6:00'' HOUR TO MINUTE, ''HH24MISS''), 6, 0) AS FILED5 
 FROM DUAL';
    
l_colCnt number := 0;
l_separator varchar2(1);
l_descTbl dbms_sql.desc_tab;
begin
l_output := utl_file.fopen( p_dir, p_filename, 'w', 4000 ); 
execute immediate 'alter session set nls_date_format=''DD-MM-YYYY HH24:MI:SS'' ';
dbms_sql.parse( l_theCursor, l_query, dbms_sql.native );
dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );

for i in 1 .. l_colCnt loop
utl_file.put( l_output, l_separator || '' || l_descTbl(i).col_name || ';' );
dbms_sql.define_column( l_theCursor, i, l_columnValue, 4000 );
l_separator := '';
end loop;
utl_file.new_line( l_output );
l_status := dbms_sql.execute(l_theCursor);
while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) loop
l_separator := '';
for i in 1 .. l_colCnt loop
dbms_sql.column_value( l_theCursor, i, l_columnValue );
utl_file.put( l_output, l_separator || l_columnValue );
l_separator := ';';
end loop;
utl_file.new_line( l_output );
end loop;
dbms_sql.close_cursor(l_theCursor);
utl_file.fclose( l_output );
execute immediate 'alter session set nls_date_format=''dd-MON-yy'' ';
exception
when others then
execute immediate 'alter session set nls_date_format=''dd-MON-yy'' ';
raise;
end;
/



EXEC  dump_table_to_csv('MY_DIRECTORY', 'file_to_export.csv' );

谁能帮我解决这个问题,或者给我指点其他方法来实现我的目标,并以正确的结构生成这个文件?

【问题讨论】:

你可以试试this refcursor to csv converter,虽然我不知道它是否会在 10.2 中工作。 【参考方案1】:

由于第一个标题行似乎不依赖于查询的结构,我只使用一个 utl_file.put_line 先将其打印出来,然后让 Tom 的其余过程基本保持不变

create or replace procedure dump_table_to_csv(p_dir in varchar2, 
                                              p_filename in varchar2 )
is
  l_output utl_file.file_type;
  l_theCursor integer default dbms_sql.open_cursor;
  l_columnValue varchar2(4000);
  l_status integer;
  l_query varchar2(4000) :=
    q'SELECT
           TO_CHAR(''9999'') AS FIELD1
          ,TO_CHAR(SYSDATE, ''DDMMYYYY'') AS FIELD2 
          ,'123' AS FIELD3
          ,LPAD(TO_CHAR(SYSDATE, 'HH24MISS'), 6, 0) AS FIELD4
          ,LPAD(TO_CHAR(SYSDATE + INTERVAL '6:00' HOUR TO MINUTE, 'HH24MISS'), 6, 0) AS FILED5 
      FROM DUAL';
    
  l_colCnt number := 0;   
  l_separator varchar2(1);
  l_descTbl dbms_sql.desc_tab;
begin
  l_output := utl_file.fopen( p_dir, p_filename, 'w', 4000 ); 
  execute immediate 'alter session set nls_date_format=''DD-MM-YYYY HH24:MI:SS'' ';
  dbms_sql.parse( l_theCursor, l_query, dbms_sql.native );
  dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );

  utl_file.put_line( 'Title;9999' );
  for i in 1 .. l_colCnt loop
    utl_file.put( l_output, l_separator || '' || l_descTbl(i).col_name || ';' );
    dbms_sql.define_column( l_theCursor, i, l_columnValue, 4000 );
    l_separator := '';
  end loop;
  utl_file.new_line( l_output );

  l_status := dbms_sql.execute(l_theCursor);
  while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) 
  loop
    l_separator := '';
    for i in 1 .. l_colCnt loop
      dbms_sql.column_value( l_theCursor, i, l_columnValue );
      utl_file.put( l_output, l_separator || l_columnValue );
      l_separator := ';';
    end loop;
    utl_file.new_line( l_output );
  end loop;
  dbms_sql.close_cursor(l_theCursor);
  utl_file.fclose( l_output );
  execute immediate 'alter session set nls_date_format=''dd-MON-yy'' ';
exception
when others then
  execute immediate 'alter session set nls_date_format=''dd-MON-yy'' ';
  raise;
end;
/

【讨论】:

以上是关于自动 CSV 文件生成,在 Oracle 10g 中具有不同列数的两个标题级别的标题的主要内容,如果未能解决你的问题,请参考以下文章

10G的CSV倒入Oracle数据库会占用多少空间?

如何使用pfile文件 修改oracle数据库参数

在 oracle 10g 中添加自动增量和自动减量列

如何从 oracle 报告应用程序 ERP 生成 excel 文件?

安装oracle 10g后用PLSQL Developer成功连接服务,防止中间出现错误的流程

Oracle Forms 10g 自动查询