如何在使用 DBMS_SCHEDULER.CREATE_JOB 创建的作业中运行复杂的 PL/SQL 代码
Posted
技术标签:
【中文标题】如何在使用 DBMS_SCHEDULER.CREATE_JOB 创建的作业中运行复杂的 PL/SQL 代码【英文标题】:How to run a complex PL/SQL code in a Job created with DBMS_SCHEDULER.CREATE_JOB 【发布时间】:2012-08-01 00:00:34 【问题描述】:我正在尝试在 Job 中运行 PL/SQL 代码,但即使它运行(如 user_scheduler_jobs 上所示),它也不会进行查询。请注意,如果查询是独立运行的,则该查询有效。
Begin
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'INSERT_LOG',
job_type => 'PLSQL_BLOCK',
job_action => 'Begin
INSERT INTO PORT_ACCIONES (ACCI_USUARIO, ACCI_NOMBRE_APLICACION, ACCI_ID_PAGINA, ACCI_NOMBRE_PAGINA, ACCI_FECHA, ACCI_HORA)
SELECT APEX_USER, APPLICATION_NAME, PAGE_ID, PAGE_NAME, TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''DD-MM-YYYY''), TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''HH24:MI:SS'')
FROM apex_workspace_activity_log
WHERE APEX_USER, APPLICATION_NAME, PAGE_ID, PAGE_NAME, TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''DD-MM-YYYY''), TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''HH24:MI:SS'')
NOT IN (SELECT ACCI_USUARIO, ACCI_NOMBRE_APLICACION, ACCI_ID_PAGINA, ACCI_NOMBRE_PAGINA, ACCI_FECHA, ACCI_HORA FROM PORT_ACCIONES)
End;',
repeat_interval => 'FREQ=MINUTELY;INTERVAL=1',
start_date => SYSTIMESTAMP,
enabled => TRUE,
comments => 'Llenado de la tabla de logs de manera automatizada');
End;
这是用来填的
CREATE TABLE "PORT_ACCIONES" (
"ACCI_USUARIO" VARCHAR2(255),
"ACCI_NOMBRE_APLICACION" VARCHAR2(255) NOT NULL ENABLE,
"ACCI_ID_PAGINA" NUMBER,
"ACCI_NOMBRE_PAGINA" VARCHAR2(255),
"ACCI_FECHA" VARCHAR2(255),
"ACCI_HORA" VARCHAR2(255)
);
使用 ApEx 提供的日志,确保它不会重复条目并从当前正在使用的应用程序中获取它们。
如果没有,我也可以尝试在 APEX_WORKSPACE_ACTIVITY_LOG 上进行新插入时将注册表添加到 PORT_ACCIONES 表中的触发器作为解决方案,但是当我尝试时
Create or Replace TRIGGER "PORT_LOGS_BI"
before insert on apex_workspace_activity_log
,它给了我信息
ORA-25001: cannot create this trigger type on this type of view. Any suggestions would be of great help.
提前非常感谢大家:)
【问题讨论】:
【参考方案1】:您如何处理:APP_ALIAS
绑定变量?可能是在提交作业之前它没有初始化。
另外,我可以在第一个 TO_CHAR()
上看到 single quote
不匹配
TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), 'DD-MM-YYYY')
这应该如下,因为整个 PLSQL 块是一个字符串文本 (VARCHAR
)
TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''DD-MM-YYYY'')
【讨论】:
我在代码运行时给它一个值,但在开发之前肯定会改变。尽管如此,如果 WHERE 子句中没有该位,作业仍会执行但未完成。 好的,所以我更新了我的答案。请尝试一下,让我知道它是否有效。【参考方案2】::APP_ALIAS 是一个 oracle 顶点变量,它为在顶点会话期间运行代码的应用程序提供指定的别名。但是,计划作业将不在会话中,因此在运行查询时此变量将为空。
但请注意:APP_ALIAS
不等于应用程序名称!如果您没有更改应用程序属性中的别名,则它们的别名将与名称不匹配。
从顶点(页面或应用程序)进程启动作业的更好方法是使用APP_ID
,并在查询中使用application_id
。这样不会出错。
如果您想手动启动作业,那么您需要自己提供正确的值,因为您无法在 apex 会话之外访问 apex 替换字符串。
您应该更改为作业提供的 sql。假设您在 apex 会话中运行作业创建,请将 id 连接到:
job_action => 'Begin
INSERT INTO PORT_ACCIONES (ACCI_USUARIO, ACCI_NOMBRE_APLICACION, ACCI_ID_PAGINA, ACCI_NOMBRE_PAGINA, ACCI_FECHA, ACCI_HORA)
SELECT APEX_USER, APPLICATION_NAME, PAGE_ID, PAGE_NAME, TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), 'DD-MM-YYYY'), TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''HH24:MI:SS'')
FROM apex_workspace_activity_log
WHERE application_id='||:APP_ID ||'
AND (APEX_USER, APPLICATION_NAME, PAGE_ID, PAGE_NAME, TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''DD-MM-YYYY''), TO_CHAR(SYSTIMESTAMP - SECONDS_AGO / (60*60*24), ''HH24:MI:SS''))
NOT IN (SELECT ACCI_USUARIO, ACCI_NOMBRE_APLICACION, ACCI_ID_PAGINA, ACCI_NOMBRE_PAGINA, ACCI_FECHA, ACCI_HORA FROM PORT_ACCIONES)
End;'
或者,如果您想通过名称引用:
WHERE application_name='''|| variable_holding_application_name ||'''
【讨论】:
等等,它连接到什么?对不起,我有点迷路了哈哈哈。 顺便说一句,谢谢你的回答!但即使取出“WHERE application_name=''''||:APP_ALIAS||''''”,作业也会执行但未完成。 你从哪里开始这份工作?您是否在 apex 应用程序的页面进程中运行它?您的应用程序有别名吗?让我们退后一步::APP_ALIAS
不是应用程序名称!应用程序名称没有内置替换字符串。
其实,我还是第一次尝试找个地方运行这个工作——现在我只是想尽可能多地解决sn-ps的代码,然后将应用程序构建为一个整体。它只需要运行一次,对吗?我不知道是否将其放入页面进程中;你会推荐什么?我相信该应用程序有一个别名。到目前为止,该查询已使用别名 vs apex_workspace_activity_log.application_name。在最坏的情况下,我可以在部署之前将 :APP_ALIAS 替换为最终的 application_name。
除非您打算将应用程序的名称复制到别名中(这并不总是有效,例如空格),否则 app_alias 在某些时候将不起作用。您可以使用 APP_ID,或通过 ID 检索应用程序的名称,但无论如何您都将使用 ID。问题仍然存在:这些替换字符串仅在顶点会话中填写。在此上下文之外,您不会有 APP_ID 或 ALIAS。这取决于您希望如何开始工作。在sql developer中自己做吗?然后不要使用bind var,而是自己输入。如果是用户驱动的,请使用页面进程来启动它。【参考方案3】:
:APP_ALIAS 看起来像一个绑定变量。替代从何而来?也许它是在它工作的环境中定义的。
另外,作业调度程序日志中有什么内容吗?您在调度程序中以与客户端相同的用户身份运行吗?
【讨论】:
是的,我忘了说我把它用作“练习模式”的东西,但即使把它去掉,在 WHERE 子句中,它仍然被执行但没有完成。以上是关于如何在使用 DBMS_SCHEDULER.CREATE_JOB 创建的作业中运行复杂的 PL/SQL 代码的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Firebase 在 Web 上托管 Flutter?它的效果如何?
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]
如何使用 Java 在 selenium webdriver 中打开新选项卡,或者如何使用 selenium webdriver 使用动作类在 selenium 中按 ctrl + T [重复]