【问题标题】:Best way to run Oracle queries periodically定期运行 Oracle 查询的最佳方式
【发布时间】:2026-01-01 16:30:01
【问题描述】:

我需要知道在 Oracle 上定期运行查询的最佳做法是什么(我使用的是 11g)。

在我的特定用例中,我在表 x 中指定了一个 DUE_DATE。我想要做的是每天 00:01 运行查询以计算某些记录的状态(OK、Warn、Critical 或 Overdue)。特定记录的状态是根据相对于x.DUE_DATE 的今天日期(其中“今天”是运行查询的日期)和一些用户指定的值(表示“警告”和“关键”)计算得出的(包含在表中y)。

  • 好的 --> today < x.DUE_DATE - y.WARN
  • 警告 --> today >= x.DUE_DATE - y.WARN and today < x.DUE_DATE - y.CRITICAL
  • 严重 --> today >= x.DUE_DATE - y.CRITICAL and today <= x.DUE_DATE
  • 过期 --> today > x.DUE_DATE

定期运行此查询的最佳方式是什么?我找到了以下选项,但不确定哪个最适合我的用例:

我知道我可以根据每个用户请求动态计算状态,但由于状态每天只更改一次,我认为每天进行一次计算并缓存后续结果会更有效。

非常感谢。

【问题讨论】:

    标签: oracle oracle11g


    【解决方案1】:
    • 对于运行作业(和查询)DBMS_SCHEDULER 是可供选择的工具。因此,如果您想根据查询结果更新表中的状态,请使用DBMS_SCHEDULER

    例如,您可以安排执行以下更新的作业:

    update x
       set status = (CASE 
                       WHEN sysdate < x.DUE_DATE - y.WARN THEN
                         'Ok'
                       WHEN sysdate >= x.DUE_DATE - y.WARN and today < x.DUE_DATE - y.CRITICAL THEN
                         'Warn'
                       WHEN sysdate >= x.DUE_DATE - y.CRITICAL and sysdate <= x.DUE_DATE THEN
                         'Critical'
                       WHEN sysdate > x.DUE_DATE THEN
                         'Overdue'
                     END)
    ;
    

    创建每天 00:00 安排的作业:

    BEGIN
        dbms_scheduler.create_job(job_name => 'Status Updater',
                                  job_type => 'PLSQL_BLOCK',
                                  job_action => '
                                                 BEGIN 
                                                  update x
                                                    set status = (CASE 
                                                                    WHEN sysdate < x.DUE_DATE - y.WARN THEN
                                                                      ''Ok''
                                                                    WHEN sysdate >= x.DUE_DATE - y.WARN and today < x.DUE_DATE - y.CRITICAL THEN
                                                                      ''Warn''
                                                                    WHEN sysdate >= x.DUE_DATE - y.CRITICAL and sysdate <= x.DUE_DATE THEN
                                                                      ''Critical''
                                                                    WHEN sysdate > x.DUE_DATE THEN
                                                                      ''Overdue''
                                                                  END)
                                                     ;
                                                  END;',
                                  start_date => systimestamp,
                                  repeat_interval => 'FREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;',
                                  enabled => TRUE);
    END;
    /
    
    • 如果您需要准备报告,请在报告工具中安排报告或使用Materialized View 来存储结果集。

    【讨论】:

    • 感谢您的回答,尤其是有用的示例:)
    • 我不得不将名称更改为“Status_Updater”。 Oracle 不喜欢带有空格的名称。
    【解决方案2】:

    您的问题的答案:在 Oracle 中调度程序的最佳方法绝对是:dbms_scheduler。

    在您的特定用例中:为什么要这样做?现在您计划每天为您的数据执行此操作,即使没有人感兴趣。最后,您的状态是一个过程变量,由 sysdate 和其他数据项计算得出。

    【讨论】: