Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment obtenir une notification de base de données vers une application C++

Une approche consiste à utiliser Advanced Queuing d'Oracle . Pour cela, vous devez configurer une file d'attente (et une table de file d'attente) et écrire une procédure PL/SQL qui attend le prochain message dans la file d'attente.

Le côté C++ appelle alors la procédure PL/SQL, qui revient lorsque l'événement suivant s'est produit.

Côté Oracle, vous devrez utiliser DBMS_SCHEDULER ou une installation similaire pour créer l'événement , c'est-à-dire insérer un nouveau message dans la file d'attente au moment opportun.

C'est toujours une approche de sondage. Cependant, il n'y a absolument aucune activité entre deux événements.

Mise à jour :

Voici un exemple de code.

Configuration initiale de la file d'attente (le message contient une valeur numérique et une valeur textuelle) :

grant AQ_ADMINISTRATOR_ROLE to appuser;
grant EXECUTE ON DBMS_AQ to appuser;
grant EXECUTE ON DBMS_AQ to appuser;


CREATE TYPE sample_payload_type AS OBJECT
(
  cmd  VARCHAR2(20),
  id   NUMBER
);


BEGIN
  DBMS_AQADM.CREATE_QUEUE_TABLE (
    queue_table        => 'sample_queue_table',
    queue_payload_type => 'sample_payload_type',
    sort_list          => 'ENQ_TIME',
    compatible         => '10.0'
  );
END;
/

BEGIN
  DBMS_AQADM.CREATE_QUEUE (
    queue_name         => 'sample_queue',
    queue_table        => 'sample_queue_table'
  );

  DBMS_AQADM.START_QUEUE (
    queue_name         => 'sample_queue'
  );
END;
/

En-tête du paquet :

create or replace package sample_queue_pkg
as

  procedure get_next_msg(
    i_max_wait      number
   ,o_cmd      out  varchar2
   ,o_id       out  number
  );


  procedure put_msg(
    i_cmd           varchar2
   ,i_id            number
  );

end sample_queue_pkg;
/

Corps du paquet :

create or replace package body sample_queue_pkg
as

  procedure get_next_msg(
    i_max_wait      number
   ,o_cmd      out  varchar2
   ,o_id       out  number
  )
  is
    dequeue_options dbms_aq.dequeue_options_t;
    message_properties dbms_aq.message_properties_t;
    message_handle RAW(16);
    message sample_payload_type;

    NO_MESSAGE_RECEIVED EXCEPTION;
    PRAGMA EXCEPTION_INIT(NO_MESSAGE_RECEIVED, -25228);

  begin
    dequeue_options.wait := i_max_wait;
    DBMS_AQ.DEQUEUE (
      queue_name => 'appuser.sample_queue',
      dequeue_options => dequeue_options,
      message_properties => message_properties,
      payload => message,
      msgid => message_handle
    );

    o_cmd := message.cmd;
    o_id := message.id;

  exception
    when NO_MESSAGE_RECEIVED then
      o_cmd := null;
      o_id := null;

  end get_next_msg;


  procedure put_msg(
    i_cmd           varchar2
   ,i_id            number
  )
  is
    enqueue_options dbms_aq.enqueue_options_t;
    message_properties dbms_aq.message_properties_t;
    message_handle RAW(16);
    message sample_payload_type;
    message_id NUMBER;

  begin
    message := sample_payload_type(i_cmd, i_id);
    DBMS_AQ.ENQUEUE(
      queue_name => 'appuser.sample_queue',
      enqueue_options => enqueue_options,
      message_properties => message_properties,
    payload => message,
      msgid => message_handle
    );
  end put_msg;

end sample_queue_pkg;
/

Le serveur de base de données peut envoyer un message en utilisant le code suivant :

sample_queue_pkg.put_msg('run_task', 8234);
commit;

Le serveur C++ peut attendre un message (et le recevoir) en appelant le sample_queue_pkg.get_next_msg stocké . Le paramètre i_max_wait spécifie le temps maximum d'attente du prochain message en secondes. Vous souhaitez probablement implémenter une boucle qui attend le prochain message et le traite jusqu'à ce qu'il reçoive un signal indiquant que le serveur est sur le point de quitter.