循环假脱机脚本

Looping spool scripts

我在 Oracle 数据库中有一个很大的 table,我想将其提取为 CSV,以便我可以将其移动到另一个系统(理想情况下这两个系统之间应该有直接连接,但在如果没有,这是下一个最佳解决方案。

因为table很大,我当时是提取一个月的数据。所以查询看起来像这样:

set termout off;
set echo off;
set verify off;
spool "C:\output_path\&&1. events.csv";
select /*csv*/ * from my_database.events
where my_date between to_date(&&1,'yyyy-mm-dd') and to_date(&&2,'yyyy-mm-dd');
spool off
set termout on;
set echo on;

然后我从另一个脚本中调用它,如下所示:

@my_script.sql "'2020-01-01'" "'2020-01-31'"

这会将“2020-01-01”和“2020-01-31”分别替换为 &&1 和 &&2,并将一月份的数据输出到 C:\output_path\'2020-01-01' events.csv

理想情况下,我想把它变成一个循环,这样我就可以有一个像这样的函数(伪-python):

def scrape_range_of_months(start_date, end_date)
    date_range = make_date_range(start_date, end_date)
    for date in date_range:
        scrape_month(date, end_of_month(date))

其中 make_date_range() 和 end_of_month() 是独立的函数。

PL/SQL 是一种比 Python 更神秘的语言,所以虽然我可以找到解决方案的各个部分,但不清楚是否可以 运行 脚本像我想的那样循环。

@justin Cave 是对的,完整的解决方案将使用 UTL_FILE 直接从 PL/SQL.

写入文件

在这个例子中,我写了一些 PL/SQL 来生成代码来逐月提取。我将“between”更改为“>=”和“<”,因为如果有时间部分,您会错过该月最后一天的记录。

DECLARE
    l_date    DATE := DATE '2020-01-01';
    c_spool   VARCHAR2( 512 ) := Q'[spool "C:\output_path\YMD.events.csv";
select /*csv*/ * from my_database.events
where my_date >= to_date('YMD','yyyy-mm-dd') and my_date < add_months(to_date('YMD','yyyy-mm-dd'),1);
]';
BEGIN
    WHILE l_date < SYSDATE
    LOOP
        DBMS_OUTPUT.put_line( REPLACE( c_spool
                                     , 'YMD'
                                     , TO_CHAR( l_date, 'yyyy-mm-dd' ) ) );
        l_date   := ADD_MONTHS( l_date, 1 );
    END LOOP;
END;

示例输出:

spool "C:\output_path20-02-01.events.csv";
select /*csv*/ * from my_database.events
where my_date >= to_date('2020-02-01','yyyy-mm-dd') and my_date < 
add_months(to_date('2020-02-01','yyyy-mm-dd'),1);