请问:1、trigger 能否发送消息给外部进程或者管道什么的?
      2、dbms_alert 如何发送消息给外部程序接收?
      能有代码更好,消息的格式是什么?怎样接收?
      在资料上只能查到如下:
      当数据库中发生了一个事件时,用DBMS_ALERT包对一个会话提出警告,用户的会话登记所关心的事件,当该事件发生时,这个警告就给会话发出信号。该包中有以下几个模块。 
名称 说明 
REGISTER 注册登记用户的会话关心一个警告 
REMOVE 告诉数据库用户的会话取消警告关联 
REMOVEALL 从所有的警告注册表中删除用户的会话 
SET_DEFAULTS 设置包开始一个检查循环时的等待事件 
SIGNAL 发出警告已发生的信号 
WAITANY 等待当前会话已注册的全部警告 
WAITONE 等待某个特定警告的信号 
通过DBMS_Alert包的使用,我们可以结合自定义的过程,在其中根据特定的操作执行Alert操作。可以达到很好的汇报目的。

解决方案 »

  1.   

    外部程序要跟DBMS_Alert配合使用一个消息ID,外部程序监听,当有事务发生时,事务处理程序通过DBMS_Alert发送消息到消息队列,外部监听程序自然就会收到。至于具体的消息格式可以自己定义,因为消息管道传送的只是内容不会管你的格式的,你可以用分隔符区分字段。
      

  2.   

    忘了DBMS_Alert发送消息是与dbms_pipe同时使用的。
    可以看看 $ORACLE_HOME/OCI/SAMPLES/READPIPE.C.
    里面有详细的例子。
      

  3.   

    oracle内部提供的在数据库内部和应用程序间通信的方式有一下几种:1.警报,就是DBMS_ALERT包提供的功能;2.管道,由DBMS_PIPE提供;3.高级队列,这个就很复杂,当然提供的功能也是很高级的。当然还可以使用外部过程,比如用PL/SQL封装外部的基于C的DLL或JAVA也能实现数据库和应用程序间的通信。
      要使用这些功能,必须知道各个功能的特点,根据需要选用。
      警报和事务相关的,是异步发送的;管道是与事务无关的,是同步发送的。
    警报的使用:
      简单来说,警报是在服务器端发出,然后在客户端接收,这就需要在客户端有一个线程来监听警报。现在拿SQLPLUS做个例子,打开两个SQLPLUS,分别用提示符SQL1和SQL2表示。首先应先授予用户使用DBMS_ALERT的权限。登录到SYS用户下,执行一下语句:
    GRANT EXECUTE ON DBMS_ALERT TO SCOTT;
    --在一个SQLPLUS中(客户端)...
    SQL1> set serveroutput on
    SQL1> declare
      2    l_status integer;
      3    l_name   varchar2(30);
      4    l_msg    varchar2(100);
      5  begin
      6    dbms_alert.register('a');--注册,对警报名称为'a'的警报感兴趣
      7    dbms_alert.waitany(l_name,l_msg,l_status);
      8    if l_status = 0 then
      9       dbms_output.put_line('name:'||l_name);
     10       dbms_output.put_line('msg:'||l_msg);
     11    end if;
     12    dbms_alert.removeall;
     13  end;
     14  /
    --这时SQL1的会话将处于等待状态。在另一个SQLPLUS中(这是服务器端)
    SQL2> exec dbms_alert.signal('a','bbb');PL/SQL 过程已成功完成。SQL2> commit;--必须提交事务,否则接收不到警报
    --则在第一个SQLPLUS中显示如下:
    name:A
    msg:bbbPL/SQL 过程已成功完成。
    SQL1>
        基本的过程就是这样,具体的说明见Oracle Document。可以这么查看有关DBMS_ALERT包的信息:
    set pagesize 0
    set linesize 100
    select text from all_source where name='DBMS_ALERT' AND TYPE='PACKAGE';在使用警报的过程中应注意以下几点:
    1.客户端的接收线程应采用轮询的方式来监听警报,否则,当主线程退出时,将因为无法正常结束该监听子线程从而非正常退出引发资源泄漏的问题;
    2.警报的名称和信息都是字符串,都是可以自定义的,只要发方和收方约定即可;
    3.在事务非常频繁,在断时间内产生大量警报的时候,警报可能出现会因处理不及时而消失的现象,即如果服务器端连着发出了两个警报(即在很短的时间内提交了两次,警报名称相同,警报内容不同),而客户端来不及处理(比如客户端轮询警报肯定有时间间隔),那么客户端只能接收到后面一个警报,从而产生警报丢失的现象;可以参看SYS.DBMS_ALERT_INFO表,就知道为什么。这张表是用来存放所有要由客户端取走的警报的信息,其主键是(SID,NAME),即会话ID和警报名称,这样,当一客户端不能处理(接收)当前警报的时候,如果再来一个相同名称的警报,那么只有用后一条警报的信息修改前一条警报的信息啦。
    4.一般用一个线程来专门接收警报,稍作处理后(如对警报名称和内容作简单解析),就将解析后的内容传给主线程进行处理,不要在监听线程中执行费时较长的操作。