自动 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 中具有不同列数的两个标题级别的标题的主要内容,如果未能解决你的问题,请参考以下文章
如何从 oracle 报告应用程序 ERP 生成 excel 文件?