dbms_aq和dbms_aqadm有关问题

本例要求指定的角色和权限(除了标准CREATE SESSION/TABLE/PROCEDURE/TYPE和表空间配额外)
1、AQ_ADMINISTRATOR_ROLE: 用于创建队列表和队列;
2、EXECUTE ON DBMS_AQ:用于通知案例中启用PLSQL存储过程编译
另外,需要入列/出列消息的标准应用用户要求AQ权限通过DBMS_AQADM[GRANT|REVOKE]_QUEUE_PRIVILIEGE API提供。
以下例子可以运行在任何拥有以上权限的用户下。
1、创建并启动一个队列
AQ处理的消息称为"有效负荷"(payloads) 。消息格式可以是用户自定义对象或XMLType或ANYDATA。当我们创建一个队列,需要告诉oracle
--有效负荷的结构,所以我们先创建一个简单对象类型 
CREATE 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'
      );
END;
/


--接着创建队列并启动:
BEGIN
   DBMS_AQADM.CREATE_QUEUE (
      queue_name  => 'demo_queue',
      queue_table => 'demo_queue_table'
      );
   DBMS_AQADM.START_QUEUE (
      queue_name => 'demo_queue'
      );
END;
/




--至此,我们已经创建了队列有效负荷,队列表和队列。来看下有哪些相关对象:
SELECT object_name, object_type
 FROM   user_objects
 WHERE  object_name != 'DEMO_QUEUE_PAYLOAD_TYPE';


--入列消息 
--我们已经准备好使用DBMS_AQ.ENQUEUE API去入列一个消息。接下来的例子,我们使用ENQUEUE过程入列一个单条消息。
--DBMS_AQ有大范围的记录和数组类型来支持其接口并使我们去修改其行为(我们将在下面的例子看到2个此类引用)。
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('Here is a message');
   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$DEMO_QUEUE_TABLE视图看到多少消息已经入列。正如我们早些看到的,
--该视图是在前面DBMS_AQADM.CREATE_QUEUE创建队列自动生成的。
SELECT COUNT(*) FROM aq$demo_queue_table;




--和我们预期一样,队列中只有一条消息。我们有2种方法可以浏览消息内容:
--1)直接查询视图:
SELECT user_data FROM aq$demo_queue_table;


--2)我们可以使用DBMS_AQ.DEQUEUE API浏览。根据名字可以看出,该过程用于出列消息。为了达到只浏览不删除的目的,我们可以使用
--DBMS_AQ.BROWSE修改出列属性(默认是DBMS_AQ.REMOVE)。
DECLARE
   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.dequeue_mode := DBMS_AQ.BROWSE;
   DBMS_AQ.DEQUEUE(
      queue_name         => 'demo_queue',
      dequeue_options    => r_dequeue_options,
      message_properties => r_message_properties,
      payload            => o_payload,
      msgid              => v_message_handle
      );
   DBMS_OUTPUT.PUT_LINE(
      '*** Browsed message is [' || o_payload.message || '] ***'
      );
END;
/


--再次查询视图可以确定消息确实没被移除:
SELECT user_data FROM   aq$demo_queue_table;


--出列消息(dequeuing messages)
--现在我们将实际出列消息。该操作不要求在同一会话进行(记住入列是AQ基于表的提交事务)。像入列,出列也是一个事务(从队列表移除消息)。
DECLARE
   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
   DBMS_AQ.DEQUEUE(
      queue_name         => 'demo_queue',
      dequeue_options    => r_dequeue_options,
      message_properties => r_message_properties,
      payload            => o_payload,
      msgid              => v_message_handle
      );
   DBMS_OUTPUT.PUT_LINE(
      '*** Dequeued message is [' || o_payload.message || '] ***'
      );
  COMMIT;
END;
/


--再次查询视图发现消息确已出列:
SELECT COUNT(*) FROM   aq$demo_queue_table;


--通知(notification)  
--文章的剩余部分,我们将看一下通过通知自动出列。通过这种方式无论消息何时入列,Oracle都将通知一个代理执行一个注册的PLSQL
--"回调"(callback)过程(可选择地,代理还可以通知一个邮箱地址或HTTP://地址)。
--为了说明,我们将创建和注册一个PLSQL过程以通过通知方式管理我们的出列。这个回调过程将出列消息并写到一个数据库表,以模拟
--标准数据库操作。
--作为开始,我们清理之前创建的对象。
BEGIN
   DBMS_AQADM.STOP_QUEUE(
      queue_name => 'demo_queue'
      );
   DBMS_AQADM.DROP_QUEUE(
      queue_name => 'demo_queue'
      );
   DBMS_AQADM.DROP_QUEUE_TABLE(
      queue_table => 'demo_queue_table'
      );
END;
/


--现在我们重新创建队列表以允许多个消费者(consumers)。一个消费者是一个出列消息代理(agent)启用多个消费者是自动通知实现的前提条件。
BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE (
      queue_table        => 'demo_queue_table',
      queue_payload_type => 'demo_queue_payload_type',
      multiple_consumers => TRUE
      );
END;
/




--接着重新创建并启动我们的队列。
BEGIN
   DBMS_AQADM.CREATE_QUEUE (
      queue_name  => 'demo_queue',
      queue_table => 'demo_queue_table'
      );
   DBMS_AQADM.START_QUEUE (
      queue_name => 'demo_queue'
      );
END;
/


--为了证明通知的异步特点,我们将把出列消息存在一个应用表中。
CREATE TABLE demo_queue_message_table( message VARCHAR2(4000) );


--现在我们有一个应用表,我们可以创建回调PL/SQL。这个过程将出列触发了通知的入列消息。程序参数必须命名并类型化。入列消息将
--包含入列时间戳,这样插入到应用表中我们将看到消息入列和通知出列的异步延迟。
CREATE 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;
/

--我们还未完成通知步骤。我们需要向队列增加一个订阅者(subsriber)并注册订阅者接到通知时的动作(例如将执行我们的回调过程)。
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;
/

--为了查看我们的小时是否自动出列,我们将检查应用表(DEMO_QUEUE_MESSAGE_TABLE)。
SELECT message FROM   demo_queue_message_table;

--进一步阅读
--我们已经在本文接触了AQ的能力。AQ是一个覆盖面巨大的应用,原超出本文的这点介绍。更多信息请参考:
--http://docs.oracle.com/cd/B10501_01/appdev.920/a96587/toc.htm
--ASKTOM:  https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:8760267539329
CREATE USER cedar IDENTIFIED BY cedar DEFAULT TABLESPACE CEDAR_DATA TEMPORARY TABLESPACE TEMP PROFILE DEFAULT ACCOUNT UNLOCK; -- 5 Roles for cedar GRANT DBA TO cedar; GRANT RESOURCE TO cedar WITH ADMIN OPTION; GRANT AQ_ADMINISTRATOR_ROLE TO cedar; GRANT CONNECT TO cedar WITH ADMIN OPTION; GRANT AQ_USER_ROLE TO cedar; ALTER USER cedar DEFAULT ROLE ALL; -- 44 System Privileges for cedar GRANT CREATE ANY DIRECTORY TO cedar WITH ADMIN OPTION; GRANT CREATE PUBLIC SYNONYM TO cedar WITH ADMIN OPTION; GRANT EXECUTE ANY CLASS TO cedar WITH ADMIN OPTION; GRANT DROP ANY VIEW TO cedar WITH ADMIN OPTION; GRANT CREATE CLUSTER TO cedar; GRANT ALTER SYSTEM TO cedar; GRANT UPDATE ANY TABLE TO cedar; GRANT INSERT ANY TABLE TO cedar; GRANT LOCK ANY TABLE TO cedar; GRANT CREATE EXTERNAL JOB TO cedar WITH ADMIN OPTION; GRANT EXECUTE ANY PROGRAM TO cedar WITH ADMIN OPTION; GRANT CREATE JOB TO cedar WITH ADMIN OPTION; GRANT DROP ANY DIRECTORY TO cedar WITH ADMIN OPTION; GRANT ALTER ANY TRIGGER TO cedar; GRANT CREATE DATABASE LINK TO cedar; GRANT DROP ANY TABLE TO cedar WITH ADMIN OPTION; GRANT CREATE TABLE TO cedar WITH ADMIN OPTION; GRANT QUERY REWRITE TO cedar; GRANT ANALYZE ANY TO cedar; GRANT DROP ANY TRIGGER TO cedar; GRANT EXECUTE ANY PROCEDURE TO cedar; GRANT SELECT ANY TABLE TO cedar WITH ADMIN OPTION; GRANT ALTER ANY TABLE TO cedar; GRANT UNLIMITED TABLESPACE TO cedar WITH ADMIN OPTION; GRANT CREATE SESSION TO cedar; GRANT CREATE ANY TRIGGER TO cedar; GRANT DROP ANY PROCEDURE TO cedar WITH ADMIN OPTION; GRANT ALTER ANY PROCEDURE TO cedar; GRANT DROP PUBLIC SYNONYM TO cedar WITH ADMIN OPTION; GRANT DROP ANY SYNONYM TO cedar WITH ADMIN OPTION; GRANT MANAGE SCHEDULER TO cedar WITH ADMIN OPTION; GRANT CREATE ANY PROCEDURE TO cedar; GRANT CREATE PROCEDURE TO cedar WITH ADMIN OPTION; GRANT CREATE SEQUENCE TO cedar; GRANT CREATE VIEW TO cedar WITH ADMIN OPTION; GRANT CREATE SYNONYM TO cedar; GRANT DROP ANY INDEX TO cedar; GRANT DELETE ANY TABLE TO cedar; GRANT CREATE ANY TABLE TO cedar; GRANT CREATE ANY JOB TO cedar WITH ADMIN OPTION; GRANT SELECT ANY DICTIONARY TO cedar WITH ADMIN OPTION; GRANT CREATE ROLE TO cedar; GRANT CREATE ANY SYNONYM TO cedar WITH ADMIN OPTION; GRANT ALTER SESSION TO cedar WITH ADMIN OPTION; GRANT EXECUTE ON sys.dbms_aq TO cedar; GRANT EXECUTE ON sys.dbms_aqadm TO cedar; GRANT EXECUTE ON sys.dbms_network_acl_admin TO cedar; GRANT ALL ON sys.DBMS_LOCK TO cedar; 这个SQL在oracle 能用吗
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值