在 oracle 的匿名块中使用游标生成 excel 文件

generate excel file using cursor in anonymous block in oracle

我在下面的匿名块中使用游标生成结果集并将其保存到 TEST_REPORT.csv 文件中。但是我在使用 spool 的那一行出现错误:

PLS-00103: Encountered the symbol "H" when expecting one of the following:
   := . ( @ % ;

我相信我不能在 PL/SQL 中使用假脱机但不确定所以我尝试了下面的代码。而且由于对生产的安全限制,我也不能使用 UTL_FILE 或 UTL_FILE_DIR 逻辑。由于员工在不同的部门工作,我想为每个员工的部门生成单独的 csv 文件。

有什么地方可以破解此代码并使用假脱机生成 csv 文件或任何其他逻辑?此外,如果无法在匿名块中使用假脱机,那么我可以在执行此代码期间使用它来生成文件吗?

如果不能使用假脱机,那么我是否可以组织我的查询结果,以便在执行这个匿名块后很容易将结果导出到单个 csv 文件,然后我可以将根据员工所在部门手动将单个 csv 文件分成多个文件?

生成并-Run.sql 文件

SET SERVEROUTPUT ON;
set verify off
SET LONG 100000
SET lines 1000 
SET sqlformat SELECT;
SPOOL C:\Loop-Flattener.sql;

PROMPT VAR V_A VARCHAR2(64);


BEGIN
  FOR TARGET_POINTER IN (select ID,
       name,
       ST_ID      
from TEST_REPORT
where rownum <5)
    LOOP
    DBMS_OUTPUT.PUT_LINE('DEFINE TARGET = '''||TARGET_POINTER.ID||''';');
    DBMS_OUTPUT.PUT_LINE('EXEC :V_A := '''||TARGET_POINTER.ID||'''; ');
    DBMS_OUTPUT.PUT_LINE('@@Target-Csv-Generator.sql;');
  END LOOP;
END;
/

SPOOL OFF;

您不能在 pl/sql 块中调用 spool Spool 是一个 sqlplus 命令,而不是 pl/sql。将语句移动到 DECLARE 语句之前。

正如 OldProgrammer 提到的,您不能在 PL/SQL 内调用 SPOOL。但是您可以从 PL/SQL 中打印到假脱机文件,并且可以 pre-compile/flatten 循环到重复调用 csv 生成器的委托中间工作脚本。

更新。根据您提供的具体信息,以下内容应该适合您。

示例测试数据:

INSERT INTO CSS_BOUTIQUE VALUES ('EUR', 'Belgium', 'a0Hb0000006LLdQ');
INSERT INTO CSS_BOUTIQUE VALUES ('EUR', 'Portugal', 'a0HB0000006LLOG');
INSERT INTO CSS_BOUTIQUE VALUES ('EUR', 'Portugal', 'a0HB0000006LLYu');

INSERT INTO CSS_BOUTIQUE VALUES ('ASIA', 'Korea', 'e0HB0000016MEIi');
INSERT INTO CSS_BOUTIQUE VALUES ('ASIA', 'China', 'e0HB0000026MEIi');
INSERT INTO CSS_BOUTIQUE VALUES ('ASIA', 'Japan', 'e0HB0000036MEIi');

INSERT INTO CSS_BOUTIQUE VALUES ('SA', 'Chile', 's0HB0000016MEIi');
INSERT INTO CSS_BOUTIQUE VALUES ('SA', 'Argentina', 's0HB0000026MEIi');
INSERT INTO CSS_BOUTIQUE VALUES ('SA', 'Equador', 's0HB0000036MEIi');

然后创建以下两个脚本:

Generate-And-Run.sql 该脚本将通过生成一个充满迭代命令的中间脚本来创建一个扁平的伪循环,以设置新的变量名称并调用可重复使用的 csv 生成器。

SET ECHO OFF;
SET FEEDBACK OFF;
SET HEAD OFF;
SET LIN 256;
SET TRIMSPOOL ON;
SET WRAP OFF;
SET PAGES 0;
SET TERM OFF;
SET SERVEROUTPUT ON;

SPOOL Loop-Flattener.sql;

PROMPT VAR V_ZONE_NAME VARCHAR2(64);


BEGIN
  FOR TARGET_POINTER IN (SELECT DISTINCT ZONE FROM CSS_BOUTIQUE)
    LOOP
    DBMS_OUTPUT.PUT_LINE('DEFINE TARGET = '''||TARGET_POINTER.ZONE||''';');
    DBMS_OUTPUT.PUT_LINE('EXEC :V_ZONE_NAME := '''||TARGET_POINTER.ZONE||'''; ');
    DBMS_OUTPUT.PUT_LINE('@@Target-Csv-Generator.sql;');
  END LOOP;
END;
/

SPOOL OFF;

@@Loop-Flattener.sql;

Target-Csv-Generator.sql:此脚本将完成生成单个 csv 的工作。请注意,这里的报告名称是一个简单的 REPORT_FOR...,没有任何其他路径来帮助确保它在工作目录中创建。

SPOOL REPORT_FOR_&&TARGET..csv;

PROMPT zone,market, boutique_id;

select zone||','||
       market||','||
       boutique_id      
from CSS_BOUTIQUE
where rownum <5 and ZONE = :V_ZONE_NAME;

SPOOL OFF;

然后运行它:

将上述两个脚本放入您要创建 CSV 的目录中,然后在该目录中启动 SQLPlus

SQL*Plus: Release 12.2.0.1.0 Production on Sun Sep 10 14:38:13 2017
SQL> @@Generate-And-Run

现在,工作目录有三个新文件:

REPORT_FOR_EUR.csv
REPORT_FOR_SA.csv
REPORT_FOR_ASIA.csv

并且每个都只有其区域的数据。例如:

cat REPORT_FOR_ASIA.csv 

产量:

zone,market, boutique_id
ASIA,Korea,e0HB0000016MEIi
ASIA,China,e0HB0000026MEIi
ASIA,Japan,e0HB0000036MEIi