【问题标题】:procedure is not getting executed程序没有被执行
【发布时间】:2020-12-01 07:48:52
【问题描述】:

尝试运行以下程序,但临时表未使用 TEMP_JOB_ID_FROM_JOB_DOC_' 和日期进行更新。

create or replace PROCEDURE scheduler_cleanup
(P_IN_DATE IN DATE)
IS
BEGIN
    EXECUTE IMMEDIATE 'create table TEMP_ID_STAT_TIME_FRM_JOB_DOC as select JOB_ID, last_update_time_utc, status from J_DOC where 
LAST_UPDATE_TIME_UTC <= TRUNC(SYSDATE) - 90 and status=''Sent''';

    EXECUTE IMMEDIATE 'DELETE hub_sign 
                        WHERE job_id IN ( SELECT JOB_ID
                                            FROM TEMP_ID_STAT_TIME_FRM_JOB_DOC )';

    EXECUTE IMMEDIATE 'DELETE j_doc 
                        WHERE job_id IN ( SELECT JOB_ID
                                            FROM TEMP_ID_STAT_TIME_FRM_JOB_DOC )';

    --EXECUTE IMMEDIATE 'RENAME TABLE TEMP_ID_STAT_TIME_FRM_JOB_DOC TO TEMP_JOB_ID_FROM_JOB_DOC_1119';
    --BEGIN
       -- EXECUTE IMMEDIATE 'DROP TABLE TEMP_JOB_ID_FROM_JOB_DOC_1119';
    --EXCEPTION
        --WHEN OTHER THEN
          --  NULL;
   -- END;
    EXECUTE IMMEDIATE 'ALTER TABLE TEMP_ID_STAT_TIME_FRM_JOB_DOC RENAME TO   || TO_CHAR(P_IN_DATE, 'MMYY');
END;

【问题讨论】:

  • 在程序中将日期参数传递为 30-11-2020。

标签: sql oracle plsql oracle-sqldeveloper plsqldeveloper


【解决方案1】:

这是最后一个ALTER;您正在将表重命名为 TO_CHAR(30-11-2020, 'MMYY') - 当执行时 - 这样做:

SQL> alter table temp rename to to_char(sysdate, 'mmy');
alter table temp rename to to_char(sysdate, 'mmy')
                                  *
ERROR at line 1:
ORA-14047: ALTER TABLE|INDEX RENAME may not be combined with other operations

应该只是RENAME,而不是ALTER

SQL> begin
  2    execute immediate 'rename temp to temp_' || to_char(sysdate, 'mmy');
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL> select * From tab where tname like 'TEMP%';

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
TEMP_120                       TABLE

SQL>

但是,您真的真的想这样做吗?在Oracle 中,我们通常不会动态创建表。重命名它们以使它们包含 date 组件 缩放为一只会飞的山羊(即根本不缩放)。您将如何针对名称与“日期”后缀不同的一堆表编写查询?又是动态SQL?好吧,祝你好运。

我能想到的另外两个选择:

  • 带有日期列的“普通”表;通过将该列包含在 WHERE 子句中来过滤行(不要忘记为该列编制索引)
  • 分区

【讨论】:

    【解决方案2】:

    正如 Littlefoot 所建议的那样,您可以通过最少的动态查询来实现所需的行为。

    如果你真的想存储中间数据,那么你可以使用GLOBAL TEMPORARY TABLEPL/SQL collections

    我将举例说明如何使用全局临时表,如下所示:

    创建全局临时表:

    -- use the data type of the column as per requirement
    CREATE GLOBAL TEMPORARY TABLE GT_TABLE (
        JOB_ID                 NUMBER,
        LAST_UPDATE_TIME_UTC   TIMESTAMP,
        STATUS                 VARCHAR2(100)
    ) ON COMMIT DELETE ROWS; 
    

    在过程中使用全局临时表:

    CREATE OR REPLACE PROCEDURE SCHEDULER_CLEANUP (
        P_IN_DATE IN DATE
    ) IS
    BEGIN
        INSERT INTO GT_TABLE
            SELECT JOB_ID,
                   LAST_UPDATE_TIME_UTC,
                   STATUS
              FROM J_DOC
             WHERE LAST_UPDATE_TIME_UTC <= TRUNC(SYSDATE) - 90
               AND STATUS = 'Sent';
    
        DELETE FROM HUB_SIGN
         WHERE JOB_ID IN (
            SELECT JOB_ID
              FROM GT_TABLE
        );
    
        DELETE FROM J_DOC
         WHERE JOB_ID IN (
            SELECT JOB_ID
              FROM GT_TABLE
        );
    
        EXECUTE IMMEDIATE 'create table TEMP_JOB_ID_FROM_JOB_DOC_' || TO_CHAR(P_IN_DATE,'MMYY')
                          || ' as  select JOB_ID, last_update_time_utc, status from GT_TABLE ';
    END;
    /
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多