Plsql 在PL/SQL中创建队列订阅服务器的语法是什么?
我试图创建一个队列和一个回调,当消息排队时触发,但我无法触发回调。我做错了什么 我有一个使消息排队的触发器,我可以在queue message表中看到它,我可以手动将它排队并处理它,我只是无法让回调在排队时触发Plsql 在PL/SQL中创建队列订阅服务器的语法是什么?,plsql,callback,queue,Plsql,Callback,Queue,我试图创建一个队列和一个回调,当消息排队时触发,但我无法触发回调。我做错了什么 我有一个使消息排队的触发器,我可以在queue message表中看到它,我可以手动将它排队并处理它,我只是无法让回调在排队时触发 BEGIN DBMS_AQADM.CREATE_QUEUE_TABLE ( queue_table => 'queue_message_table', queue_payload_type => 'queue_message_type', m
BEGIN
DBMS_AQADM.CREATE_QUEUE_TABLE (
queue_table => 'queue_message_table',
queue_payload_type => 'queue_message_type',
multiple_consumers => TRUE);
DBMS_AQADM.CREATE_QUEUE (
queue_name => 'message_queue',
queue_table => 'queue_message_table');
DBMS_AQADM.START_QUEUE (queue_name => 'message_queue');
END;
CREATE OR REPLACE PROCEDURE queue_callback(
context RAW, reginfo SYS.AQ$_REG_INFO, descr SYS.AQ$_DESCRIPTOR, payload RAW, payloadl NUMBER) AS
queue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
my_message queue_message_type;
ret varchar2(200);
message_id RAW(16);
BEGIN
DBMS_OUTPUT.PUT_LINE('Callback');
queue_options.msgid := descr.msg_id;
queue_options.consumer_name := descr.consumer_name;
DBMS_AQ.DEQUEUE(
queue_name => descr.queue_name,
dequeue_options => queue_options,
message_properties => message_properties,
payload => my_message,
msgid => message_id );
ret := handle_message(my_message);
commit;
END;
BEGIN
DBMS_AQADM.ADD_SUBSCRIBER (queue_name => 'message_queue',
subscriber => SYS.AQ$_AGENT('queue_subscriber', 'message_queue',NULL));
DBMS_AQ.REGISTER (
SYS.AQ$_REG_INFO_LIST(
SYS.AQ$_REG_INFO(
'MESSAGE_QUEUE:QUEUE_SUBSCRIBER',
DBMS_AQ.NAMESPACE_AQ,
'plsql://QUEUE_CALLBACK',
HEXTORAW('FF')
)
), 1
);
END;
乍一看,您似乎既没有启动队列(
dbms\u aqadm.start\u queue
),也没有将任何内容排入队列(dbms\u aq.enqueue
)
我建议您遵循这一点。您需要小心使用数据库版本。一些bug已经被报道过了。 特别是,我构建了自己的示例,在Oracle 11gR2企业数据库中执行演示。我能够进入队列、退出队列、清除队列,但使用Dbms_Aq.Register创建的侦听器无法工作。 我下载了一个Oracle11GR2XE数据库,运行了相同的示例,它成功了 同一个示例在Oracle 10gR2实例中运行,效果非常好 在使用aq时,您需要注意以下几点:
- 使用适当的参数添加订阅服务器
- 使用适当的命名空间将侦听器注册到Dbms_Aq.Register
- 使用多个使用者标志声明队列表
- 对包和队列使用适当的权限
- 在某些情况下,如果队列不起作用,请使用队列的限定名称
connect / as sysdba
-- @?/rdbms/admin/dbmsaqad.sql --(install if you don't have aq installed yet)
-- create the user and permissions
create user aqadmin identified by aqadmin default tablespace users temporary tablespace temp;
GRANT create session TO aqadmin;
grant connect, resource to aqadmin;
GRANT aq_administrator_role TO aqadmin IDENTIFIED BY aqadmin;
GRANT execute ON dbms_aq TO aqadmin;
GRANT execute ON dbms_aqadm TO aqadmin;
创建ddl对象
CREATE TABLE demo_queue_message_table
( message VARCHAR2(4000) );
创建aq对象
create or replace type demo_queue_payload_type as object(message varchar2(4000)) ;
/
begin
DBMS_AQADM.CREATE_QUEUE_TABLE (queue_table => 'demo_queue_table', queue_payload_type => 'demo_queue_payload_type',multiple_consumers => TRUE);
DBMS_AQADM.CREATE_QUEUE (queue_name => 'demo_queue', queue_table => 'demo_queue_table');
DBMS_AQADM.START_QUEUE('demo_queue');
end;
/
CREATE or replace PROCEDURE demo_queue_callback_procedure(
context RAW,
reginfo SYS.AQ$_REG_INFO,
descr SYS.AQ$_DESCRIPTOR,
payload RAW,
payloadl NUMBER
) AS
r_dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
v_message_handle RAW(16);
o_payload demo_queue_payload_type;
BEGIN
r_dequeue_options.msgid := descr.msg_id;
r_dequeue_options.consumer_name := descr.consumer_name;
DBMS_AQ.DEQUEUE(
queue_name => descr.queue_name,
dequeue_options => r_dequeue_options,
message_properties => r_message_properties,
payload => o_payload,
msgid => v_message_handle
);
INSERT INTO demo_queue_message_table ( message )
VALUES ( 'Message [' || o_payload.message || '] ' ||
'dequeued at [' || TO_CHAR( SYSTIMESTAMP,
'DD-MON-YYYY HH24:MI:SS.FF3' ) || ']' );
COMMIT;
END;
/
BEGIN
DBMS_AQADM.ADD_SUBSCRIBER (
queue_name => 'demo_queue',
subscriber => SYS.AQ$_AGENT(
'demo_queue_subscriber',
NULL,
NULL )
);
DBMS_AQ.REGISTER (
SYS.AQ$_REG_INFO_LIST(
SYS.AQ$_REG_INFO(
'DEMO_QUEUE:DEMO_QUEUE_SUBSCRIBER',
DBMS_AQ.NAMESPACE_AQ,
'plsql://DEMO_QUEUE_CALLBACK_PROCEDURE',
HEXTORAW('FF')
)
),
1
);
END;
/
最后测试队列
DECLARE
r_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;
r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
v_message_handle RAW(16);
o_payload demo_queue_payload_type;
BEGIN
o_payload := demo_queue_payload_type(
TO_CHAR(SYSTIMESTAMP, 'DD-MON-YYYY HH24:MI:SS.FF3' )
);
DBMS_AQ.ENQUEUE(
queue_name => 'demo_queue',
enqueue_options => r_enqueue_options,
message_properties => r_message_properties,
payload => o_payload,
msgid => v_message_handle
);
COMMIT;
END;
/
肯定有消息进入队列,我可以看到它们。回调创建语法有问题。我注意到在对AQ API的调用中没有对queue_回调的引用。在AQ.REGISTER调用中有对queue_回调的引用,它在REG_INFO构造函数中。这似乎是在线演示的方式,但显然我遗漏了一些东西。你知道回调的引用在哪里吗?你修复了吗?我也有同样的问题: