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

时间:2017-09-03 17:45:59

标签: oracle plsql cursor anonymous-function createfile

我有以下匿名块,我使用游标生成结果集并将其保存到PLS-00103: Encountered the symbol "H" when expecting one of the following: := . ( @ % ; 文件中。但是我在使用假脱机的行上得到错误:

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,但不确定,所以我尝试了下面的代码。而且由于生产的安全限制,我不能使用UTL_FILE或UTL_FILE_DIR逻辑。当员工在不同的部门工作时,我想为每个员工生成与其部门相关的单独的csv文件。

无论如何,我可以在哪里打破这段代码并使用spool来生成csv文件或任何其他逻辑?此外,如果无法在匿名块中使用假脱机,那么我可以在执行此代码期间使用它来生成文件吗?

如果无法使用假脱机,那么我是否可以组织我的查询结果,以便在执行此匿名块后将结果导出到单个csv文件中然后我可以将单个csv分开根据员工及其部门手动将文件归档到多个文件中?

Generate-And-Run.sql文件

{{1}}

2 个答案:

答案 0 :(得分:1)

正如OldProgrammer所提到的,您无法在SPOOL内拨打PL/SQL。但您可以从PL/SQL内打印到假脱机文件,并可以将循环预编译/展平为委托中间工作程序脚本,该脚本重复调用csv-generator。

<强>更新即可。为了回应您提供的细节,以下内容适合您。

示例测试数据:

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-generator。 / p>

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

答案 1 :(得分:0)

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