繁体   English   中英

Oracle使用程序包绑定变量和动态PL / SQL

[英]Oracle Bind Variables and Dynamic PL/SQL with Package

我不熟悉在包中使用动态SQL,并且在下面的代码片段的WHERE子句的左侧使用绑定变量时遇到了一个问题,特别是“ WHERE TRUNC(:parm_rec.SRC_DATE_COLUMN)”:

 'WHERE TRUNC( :parm_rec.SRC_DATE_COLUMN ) < ADD_MONTHS( ' ||
 'ADD_MONTHS ( TRUNC (  NVL ( TO_DATE ( :parm_rec.SYS_OFFSET ) , SYSDATE) - ( :parm_rec.DAY_OFFSET )), ' ||

我试图将“列名”作为绑定变量传递给创建日期,该列的名称在CREATEDATE,CREATE_DATE,LOAD_DATE等之间可能有所不同。

如果WHERE子句具有硬编码的实际列名(在此特定情况下为CREATEDATE),并且所有其他绑定变量似乎都绑定到其相应的标识符,则动态SQL执行不会出现问题。 parm_rec.SRC_DATE_COLUMN变量的数据类型为VARCHAR2。

当执行失败时,我没有收到特定的错误消息。 仅代码失败的行如下:

EXECUTE IMMEDIATE arc_sql USING seq_val, parm_rec.SRC_DATE_COLUMN, parm_rec.SYS_OFFSET, parm_rec.DAY_OFFSET, parm_rec.MON_OFFSET, kNEGATIVE, parm_rec.YR_OFFSET, kANNUM; 

我已经用尽了所有的研究选择,试图找出无法解决问题的原因。 我以为这是我做错的事情,但我无法弄清楚这是什么。

我将以下整个过程包括在内:

PROCEDURE ArchiveDynamic
IS         
BEGIN
DBMS_OUTPUT.PUT_LINE('ArchiveDynamic - ENTER');
    FOR i in tbl_cur
    LOOP
    /*** DYNAMIC SQL DECLARATIONS ***/
        arc_sql := 'DECLARE ' ||
                    /*** DYNAMIC %ROWTYPE SELECT ***/
                        'CURSOR arc_cur IS ' ||
                        'SELECT * '||
                        'FROM '  || i.ARC_TABLE_NAME || '; '||               --obtain ARCHIVE ARC_SCHEMA_NAME.ARC_TABLE_NAME
                        'TYPE arc_cur_type IS TABLE OF arc_cur%ROWTYPE; ' || -- dynamically set archive record cursor %ROWTYPE for BULK COLECT as table collection 
                        'arc_rec    arc_cur_type; ' ||                       -- define archive record as TABLE OF cursor.%ROWTYPE

                    /*** ARCHIVE PARAMETERS CURSOR ***/
                        'CURSOR parm_cur IS '||
                        'SELECT :seq_val AS ARCHIVE_ID, '||
                        'A.*, ' ||
                        'SYSDATE AS ARCHIVE_DATE ' ||
                        'FROM ' || srcSchemaTable || ' A ' ||                -- archive SRC_SCHEMA_NAME.SRC_TABLE_NAME (source table not archive table)
                        'WHERE TRUNC( :parm_rec.SRC_DATE_COLUMN ) < ADD_MONTHS( ' ||
                                                      'ADD_MONTHS ( TRUNC (  NVL ( TO_DATE ( :parm_rec.SYS_OFFSET ) , SYSDATE) - ( :parm_rec.DAY_OFFSET )), ' ||
                                                      '( :parm_rec.MON_OFFSET * :kNEGATIVE ) ), ' ||
                                                      '( :parm_rec.YR_OFFSET * ( :kANNUM * :kNEGATIVE ) ) ); ' ||
               /*** DYNAMIC SQL STATEMENT BODY ***/
                   'BEGIN '||
                        'IF parm_cur%ISOPEN THEN CLOSE parm_cur; ' ||
                        'END IF; ' ||
                        'OPEN parm_cur; ' ||
                        'LOOP ' ||
                            'FETCH parm_cur ' ||
                            'BULK COLLECT INTO arc_rec LIMIT 500; ' ||
                            'EXIT WHEN arc_rec.COUNT = 0; ' ||
                            'FORALL i IN 1..arc_rec.COUNT ' ||
                                'INSERT INTO ' || arcTable ||
                                ' VALUES arc_rec( i );' ||
                                'DBMS_OUTPUT.PUT_LINE( ''ARC_REC_COUNT: '' || arc_rec.COUNT ); ' ||
                        'END LOOP; ' ||
                        'CLOSE parm_cur; ' ||                                   
                        'dbms_output.put_line(''SUCCESS...''); '||
                    'END; ';

    DBMS_OUTPUT.PUT_LINE('ArchiveDynamic - INSIDE LOOP: ' || arc_sql );
        EXECUTE IMMEDIATE arc_sql USING seq_val, parm_rec.SRC_DATE_COLUMN, parm_rec.SYS_OFFSET, parm_rec.DAY_OFFSET, parm_rec.MON_OFFSET, kNEGATIVE, parm_rec.YR_OFFSET, kANNUM;                       
    END LOOP;

END ArchiveDynamic

您可以提供的任何帮助将不胜感激。

谢谢!

按照Kaushik Nayak的建议,将以下代码更改为使用文字串联而不是绑定变量:

'WHERE TRUNC( ' || parm_rec.SRC_DATE_COLUMN || ' ) < ADD_MONTHS( ' ||  'ADD_MONTHS ( TRUNC (  NVL ( TO_DATE ( :parm_rec.SYS_OFFSET ) , SYSDATE) - ( :parm_rec.DAY_OFFSET )), ' ||  '( :parm_rec.MON_OFFSET * :kNEGATIVE ) ), ' ||  '( :parm_rec.YR_OFFSET * ( :kANNUM * :kNEGATIVE ) ) ); ' ||

完整的程序代码在这里:

PROCEDURE ArchiveDynamic
IS         
BEGIN
DBMS_OUTPUT.PUT_LINE('ArchiveDynamic - ENTER');
    FOR i in tbl_cur
    LOOP
    /*** DYNAMIC SQL DECLARATIONS ***/
        arc_sql := 'DECLARE ' ||
                    /*** DYNAMIC %ROWTYPE SELECT ***/
                        'CURSOR arc_cur IS ' ||
                        'SELECT * '||
                        'FROM '  || i.ARC_TABLE_NAME || '; '||               --obtain ARCHIVE ARC_SCHEMA_NAME.ARC_TABLE_NAME
                        'TYPE arc_cur_type IS TABLE OF arc_cur%ROWTYPE; ' || -- dynamically set archive record cursor %ROWTYPE for BULK COLECT as table collection 
                        'arc_rec    arc_cur_type; ' ||                       -- define archive record as TABLE OF cursor.%ROWTYPE

                    /*** ARCHIVE PARAMETERS CURSOR ***/
                        'CURSOR parm_cur IS '||
                        'SELECT :seq_val AS ARCHIVE_ID, '||
                        'A.*, ' ||
                        'SYSDATE AS ARCHIVE_DATE ' ||
                        'FROM ' || srcSchemaTable || ' A ' ||                -- archive SRC_SCHEMA_NAME.SRC_TABLE_NAME (source table not archive table)
                        'WHERE TRUNC( ' || parm_rec.SRC_DATE_COLUMN || ' ) < ADD_MONTHS( ' ||
                                                      'ADD_MONTHS ( TRUNC (  NVL ( TO_DATE ( :parm_rec.SYS_OFFSET ) , SYSDATE) - ( :parm_rec.DAY_OFFSET )), ' ||
                                                      '( :parm_rec.MON_OFFSET * :kNEGATIVE ) ), ' ||
                                                      '( :parm_rec.YR_OFFSET * ( :kANNUM * :kNEGATIVE ) ) ); ' ||
               /*** DYNAMIC SQL STATEMENT BODY ***/                   
                   'BEGIN '||
                        'IF parm_cur%ISOPEN THEN CLOSE parm_cur; ' ||
                        'END IF; ' ||
                        'OPEN parm_cur; ' ||
                        'LOOP ' ||
                            'FETCH parm_cur ' ||
                            'BULK COLLECT INTO arc_rec LIMIT 500; ' ||
                            'EXIT WHEN arc_rec.COUNT = 0; ' ||
                            'FORALL i IN 1..arc_rec.COUNT ' ||
                                'INSERT INTO ' || arcTable ||
                                ' VALUES arc_rec( i );' ||
                                'DBMS_OUTPUT.PUT_LINE( ''ARC_REC_COUNT: '' || arc_rec.COUNT ); ' ||
                        'END LOOP; ' ||
                        'CLOSE parm_cur; ' ||                                   
                        'dbms_output.put_line(''SUCCESS...''); '||
                    'END; ';

    DBMS_OUTPUT.PUT_LINE('ArchiveDynamic - INSIDE LOOP: ' || arc_sql );
        EXECUTE IMMEDIATE arc_sql USING seq_val, parm_rec.SYS_OFFSET, parm_rec.DAY_OFFSET, parm_rec.MON_OFFSET, kNEGATIVE, parm_rec.YR_OFFSET, kANNUM;                    
    END LOOP;

END ArchiveDynamic

谢谢您的帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM