Oracle PL/SQL 动态更改变量值的问题

Posted

技术标签:

【中文标题】Oracle PL/SQL 动态更改变量值的问题【英文标题】:Oracle PL/SQL Issue in change the variable value dynamically 【发布时间】:2017-10-10 13:46:06 【问题描述】:

我正在尝试使用 Oracle 中的动态查询概念更改查询中的表名。

最初的执行很好。但是一旦用新值修改了表名,即使它显示为旧值。

检查下面的代码......

    CREATE OR REPLACE PROCEDURE Test
AS
BEGIN
  DECLARE
    DELETE_OLD_YEARS NUMBER(2);
    RECORD_COUNT NUMBER(10);
    INTERVAL_UNIT VARCHAR2(4);
    DYNA_QUERY_DEL VARCHAR2(280);
    DYNA_TABLE_NAME VARCHAR(30);

  BEGIN

    INTERVAL_UNIT := 'YEAR';
    RECORD_COUNT := 0;
    DYNA_TABLE_NAME := 'UserData';
    DELETE_OLD_YEARS := 7;

    DYNA_QUERY_DEL := 'SELECT COUNT(*) 
                        FROM ' || DYNA_TABLE_NAME || ' UD 
                        WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2)) 
                        OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';

    -- Delete older than 7 years data
    DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData: ' || DYNA_QUERY_DEL);
    EXECUTE IMMEDIATE  DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
    DBMS_OUTPUT.PUT_LINE('Record Count : ' || RECORD_COUNT);


    -- Delete older than 7 years data from backup table.
    DYNA_TABLE_NAME := 'UserData_Backup';
    DELETE_OLD_YEARS := 7;
    DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData_Backup : ' || DYNA_QUERY_DEL);
    EXECUTE IMMEDIATE  DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
    DBMS_OUTPUT.PUT_LINE('Record Count 2 : ' || RECORD_COUNT);

  END;

END;
/

exec Test;

输出是....

Dynamic Query with UserData : SELECT COUNT(*) 
                        FROM UserData UD 
                        WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2)) 
                        OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC
Record Count : 6220
Dynamic Query with UserData_Backup : SELECT COUNT(*) 
                        FROM UserData UD 
                        WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2)) 
                        OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC
Record Count 2 : 6220

但是这里的第二个查询应该使用 UserData_Backup 表来准备。

请帮我找出问题....

【问题讨论】:

希望我的解决方案能帮到你..检查一下。!! 您没有更改表名,它已经被硬编码到 DYNA_QUERY_DEL 中。您只更改了不再使用的变量的值。使用动态 SQL 有什么具体原因吗? 【参考方案1】:

动态查询将在程序中执行一次,除非您使用 For 循环。如果您不想使用循环,您可以使用相同的查询来进行第二次动态执行,这里我使用的是循环函数。

代码

CREATE OR REPLACE PROCEDURE Test
        AS
        BEGIN
          DECLARE
            DELETE_OLD_YEARS NUMBER(2);
            RECORD_COUNT NUMBER(10);
            INTERVAL_UNIT VARCHAR2(4);
            DYNA_QUERY_DEL VARCHAR2(280);
            DYNA_TABLE_NAME VARCHAR(30);
          BEGIN
            INTERVAL_UNIT := 'YEAR';
            RECORD_COUNT := 0;
            --DYNA_TABLE_NAME := 'UserData';
           -- DYNA_TABLE_NAME := 'UserData_Backup';
            DELETE_OLD_YEARS := 7;
            for c1 in (select 'UserData' as DYNA_TABLE_NAME from dual
                       union all
                       select 'UserData_Backup' as DYNA_TABLE_NAME from dual)
            loop
            DYNA_QUERY_DEL := 'SELECT COUNT(*) 
                                FROM ' || DYNA_TABLE_NAME || ' UD 
                                WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2)) 
                                OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';

            -- Delete older than 7 years data
            DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData: ' || DYNA_QUERY_DEL);
            EXECUTE IMMEDIATE  DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
            RECORD_COUNT := RECORD_COUNT +1;
            end loop;
            DBMS_OUTPUT.PUT_LINE('Record Count 2 : ' || RECORD_COUNT);
          END;
        END;
        /
        exec Test;

【讨论】:

是的,重新分配相同的查询有效。但是我们是否有任何替代方法,例如刷新 DYNA_TABLE_NAME 变量的缓存或会话? 是的...我在代码中更新的备用循环方法检查它。 这对你有帮助吗? 是的,只是寻找替代方法。【参考方案2】:

重新分配变量DYNA_QUERY_DEL尝试这样做

    CREATE OR REPLACE PROCEDURE Test
AS
BEGIN
  DECLARE
    DELETE_OLD_YEARS NUMBER(2);
    RECORD_COUNT NUMBER(10);
    INTERVAL_UNIT VARCHAR2(4);
    DYNA_QUERY_DEL VARCHAR2(280);
    DYNA_TABLE_NAME VARCHAR(30);

  BEGIN

    INTERVAL_UNIT := 'YEAR';
    RECORD_COUNT := 0;
    DYNA_TABLE_NAME := 'UserData';
    DELETE_OLD_YEARS := 7;

    DYNA_QUERY_DEL := 'SELECT COUNT(*) 
                        FROM ' || DYNA_TABLE_NAME || ' UD 
                        WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2)) 
                        OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';

    -- Delete older than 7 years data
    DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData: ' || DYNA_QUERY_DEL);
    EXECUTE IMMEDIATE  DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
    DBMS_OUTPUT.PUT_LINE('Record Count : ' || RECORD_COUNT);


    -- Delete older than 7 years data from backup table.
      DYNA_TABLE_NAME := 'UserData_Backup';

    DYNA_QUERY_DEL := 'SELECT COUNT(*) 
                        FROM ' || DYNA_TABLE_NAME || ' UD 
                        WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2)) 
                        OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';

    DELETE_OLD_YEARS := 7;
    DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData_Backup : ' || DYNA_QUERY_DEL);
    EXECUTE IMMEDIATE  DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
    DBMS_OUTPUT.PUT_LINE('Record Count 2 : ' || RECORD_COUNT);

  END;

END;
/

exec Test;

【讨论】:

是的,我也有同样的想法。但是重新分配对我来说看起来有些奇怪。我是 Java 开发人员,是 PL/SQL 程序的新手。 DYNA_TABLE_NAME 的值发生了变化,这就是您需要再次分配DYNA_QUERY_DEL 的原因。无论如何,你能告诉我第二次执行的输出是什么吗?它包含表名UserData_Backup 对吗? 是的,得到了​​第二个表名。 :-)

以上是关于Oracle PL/SQL 动态更改变量值的问题的主要内容,如果未能解决你的问题,请参考以下文章

用PL/SQL Developer导出表数据的时候,窗口一闪而过解决办法

PL/SQL链接Oracle出现乱码

Oracle pl/sql:在事务中执行动态删除

PL/SQL:, 如何将变量传递给 SELECT 语句并返回所有结果行

Oracle基础进阶

Oracle:使用 SQL 或 PL/SQL 查找动态 SQL 中的错误位置