perl执行sql文件(DBI oracle)

时间:2013-04-02 08:20:37

标签: sql oracle perl dbi

我有以下问题,我有一个用DBI CPAN模块Perl执行的SQL文件 我在这个网站上看到了两个解决方案来解决我的问题。

  1. Read SQL file line by line

  2. Read SQL file in one instruction

  3. 那么,哪一种更好,哪种解决方案之间真正的区别呢?

    修改

    这是一个图书馆。我需要检索输出返回代码。

    传递的文件类型如下:

        set serveroutput on;
        set pagesize 20000;
        spool "&1."
        DECLARE
            -- Récupération des arguments
            -- &2: FLX_REF, &3: SVR_ID, &4: ACQ_STT, &5: ACQ_LOG, &6: FLX_COD_DOC, &7: ACQ_NEL, &8: ACQ_TYP    
            VAR_FLX_REF VARCHAR2(100):=&2;
            VAR_SVR_ID NUMBER(10):=&3;
            VAR_ACQ_STT NUMBER(4):=&4;
            VAR_ACQ_LOG VARCHAR2(255):=&5;
            VAR_FLX_COD_DOC VARCHAR2(30):=&6;
            VAR_ACQ_NEL NUMBER(10):=&7;
            VAR_ACQ_TYP NUMBER:=&8;
        BEGIN
            INSERT INTO ACQUISITION_CFT 
                (ACQ_ID, FLX_REF, SVR_ID, ACQ_DATE, ACQ_STT, ACQ_LOG, FLX_COD_DOC, ACQ_NEL, ACQ_TYP) 
            VALUES 
                (TRACKING.SEQ_ACQUISITION_CFT.NEXTVAL, ''VAR_FLX_REF'', 
                    ''VAR_SVR_ID'', sysdate, VAR_ACQ_STT, ''VAR_ACQ_LOG'',
                    ''VAR_FLX_COD_DOC'', VAR_ACQ_NEL, VAR_ACQ_TYP);
        END;
    
        /
        exit;
    

    我还有另一个问题要问,再次使用DBI Oracle模块。 我可以为SQL文件和Control文件使用相同的代码吗?

    (SQL控制文件示例)

        LOAD DATA
        APPEND INTO TABLE DOSSIER
        FIELDS TERMINATED BY ';'
        (
        DSR_IDT,
        DSR_CNL,
        DSR_PRQ,
        DSR_CEN,
        DSR_FEN,
        DSR_AN1,
        DSR_AN2,
        DSR_AN3,
        DSR_AN4,
        DSR_AN5,
        DSR_AN6,
        DSR_PI1,
        DSR_PI2,
        DSR_PI3,
        DSR_PI4,
        DSR_NP1,
        DSR_NP2,
        DSR_NP3,
        DSR_NP4,
        DSR_NFL,
        DSR_NPG,
        DSR_LTP,
        DSR_FLF,
        DSR_CLR,
        DSR_MIM,
        DSR_TIM,
        DSR_NDC,
        DSR_EMS NULLIF DSR_EMS=BLANKS "sysdate",
        JOB_IDT,
        DSR_STT,
        DSR_DAQ "CASE WHEN :DSR_DAQ IS NOT NULL THEN SYSDATE ELSE NULL END"
    
        )
    

3 个答案:

答案 0 :(得分:1)

一次一行地读取一个表格会更复杂,但它可以使用更少的内存 - 只要您构建代码以使用每个项目的数据而不需要以后再使用它。

通常,您希望单独处理每个项目(例如,对数据进行处理),在这种情况下,您也可以使用逐行读取方法来定义循环。

我倾向于默认使用单指令方法,但是一旦我关注记录数量(特别是在长时间运行的批处理过程中),或者需要循环数据作为第一个任务,那么我读了记录一个接一个。

答案 1 :(得分:1)

事实上,你引用的两个答案提出了相同的解决方案,逐行阅读和执行(但第一点更清楚)。第二个问题有一个可选的答案,其中文件包含单个语句

如果不逐行执行SQL,则很难捕获任何错误。

答案 2 :(得分:1)

“逐行”仅在每个SQL语句位于一行上时才有意义。您可能的意思是声明。

除此之外,它取决于您的SQL文件的样子以及您想要做的事情。

您的SQL文件有多复杂?它可能包含这样的内容吗?

select foo from table where column1 = 'bar;';   --Get foo; it will be used later.

按语句读取SQL文件语句的简单方法是使用分号(或语句分隔符所用的内容)进行拆分。但是如果你可能在其他地方有分号,例如注释或字符串,则此方法将失败。如果用分号拆分此语句,则会尝试执行以下四个“命令”:

select foo from table where column1 = 'bar;
';
--Get foo; 
it will be used later.

显然,这些都不是有效的。正确处理这样的语句并非易事。您必须完全解析SQL以确定语句是什么。不幸的是,没有现成的模块可以为你做这件事(SQL::Script是一个很好的开始SQL文件处理模块,但根据文档,它只是分裂在分号上。)

如果您的SQL文件很简单,那么在语句或注释中不包含任何语句分隔符;或者如果它以某种其他方式可预测(例如每行有一个语句),则很容易将文件拆分为语句并逐个执行。但是如果你必须处理任意的SQL语法,包括上面的情况,这将是一项复杂的任务。

什么样的任务?

  • 您需要检索输出吗?
  • 检测任何单个语句中的错误是否很重要,或者它只是一个可以运行的批处理作业而不用担心它?

如果这是您可以运行并忘记的事情,您可以让Perl执行系统命令,告诉Oracle处理该文件。这比自己处理所有语句更简单。但是如果你需要在Perl中处理结果或处理错误,那么自己按语句执行它将是必要的。

更新:根据您的响应,您希望编写一个可以处理任意SQL语句的库。在这种情况下,您肯定需要解析SQL并一次执行一个语句。这是可行的,但并不简单。 BEGIN...END块的可能性意味着您必须能够在语句中正确处理分号。

SQL::Statement class of modules可能会有所帮助。