如何在AQADMIN中动态清除表

问题描述 投票:1回答:1

当我试图动态清除QUEUE表时,我收到一个错误.Below是代码

 set serveroutput on;
declare
l_stmt varchar2(2000):='';
po_t dbms_aqadm.aq$_purge_options_t;
BEGIN
for i in (select NAME,queue_table from all_Queues where owner='AQADMIN') loop
--dbms_output.put_line(i.queue_table);
l_stmt:='DBMS_AQADM.PURGE_QUEUE_TABLE ('''||i.queue_table||''',''trunc(enq_time)<sysdate-90'',block => po_t)';
execute immediate l_stmt;
--dbms_output.put_line(l_stmt);
commit;
end loop;
END;
/

错误信息:

Error report -
ORA-00900: invalid SQL statement
ORA-06512: at line 8
00900. 00000 -  "invalid SQL statement"
*Cause:    
*Action:

要知道我的查询是否正确构建,我注释掉了执行立即部分并取消注释了DBMS_OUTPUT命令,结果发布在sql developer中并且执行完美,(下面是代码输出)。所以查询是正确的,不是确定我的代码有什么问题,

输出:

anonymous block completed

    DBMS_AQADM.PURGE_QUEUE_TABLE ('HEARTBEAT_MSG_QT','trunc(enq_time)<sysdate-90',block => po_t)

然后我在单独的SQL块中执行上面的输出,它运行正常.Below

declare
po_t dbms_aqadm.aq$_purge_options_t;
begin
DBMS_AQADM.PURGE_QUEUE_TABLE ('HEARTBEAT_MSG_QT','trunc(enq_time)<sysdate-90',po_t);
end;
/

匿名块完成

oracle plsql
1个回答
3
投票

当你调用execute immediate时,它是expecting dynamic SQL,而不是PL / SQL。要运行PL / SQL命令,您需要将其包装在匿名块中,就像您手动运行它时一样:

l_stmt:='DECLARE po_t dbms_aqadm.aq$_purge_options_t; BEGIN DBMS_AQADM.PURGE_QUEUE_TABLE ('''||i.queue_table||''',''trunc(enq_time)<sysdate-90'',block => po_t); END;';

或分成多行,使其更容易阅读:

l_stmt:='DECLARE po_t dbms_aqadm.aq$_purge_options_t;'
  || 'BEGIN '
  || 'DBMS_AQADM.PURGE_QUEUE_TABLE ('''||i.queue_table||''','
  || '''trunc(enq_time)<sysdate-90'',block => po_t);'
  || 'END;';

请注意,您必须在该块中重新声明po_t,因为原始声明超出了动态SQL调用的范围(实际上,原始声明现在是多余的...)。

您不需要使用动态SQL,您可以将游标值直接传递给过程:

DECLARE
  l_po dbms_aqadm.aq$_purge_options_t;
BEGIN
  for i in (select NAME,queue_table from all_Queues where owner='AQADMIN') 
  loop
    DBMS_AQADM.PURGE_QUEUE_TABLE (queue_table => i.queue_table,
      purge_condition => 'trunc(enq_time)<sysdate-90'
      purge_options=> l_po);
  end loop;
END;
/

我也删除了commit,因为它是多余的; from the docs

此过程在自治事务中提交批量消息。

© www.soinside.com 2019 - 2024. All rights reserved.