问:使用OCN检测表上的插入/更新/删除,并将“real_id”传递给回调中的UTL_HTTP.REQUEST?

时间:2018-03-06 13:43:16

标签: oracle

我正在尝试检测表格上的插入,更新或删除。我知道我不能使用QRCN,所以我试图使用OCN。我想要实现的是......当检测到插入/更新时,当检测到删除时调用“callback_iu”调用'callback_d'。

DECLARE

  qosflags      NUMBER;
  reginfo_iu    cq_notification$_reg_info;
  reginfo_d     cq_notification$_reg_info;
  regid_iu      NUMBER;
  regid_d       NUMBER;
  v_cursor      SYS_REFCURSOR;  
  opfilter_iu   NUMBER;
  opfilter_d    NUMBER;

BEGIN
   qosflags := DBMS_CQ_NOTIFICATION.QOS_ROWIDS;
   opfilter_iu := DBMS_CQ_NOTIFICATION.INSERTOP + DBMS_CQ_NOTIFICATION.UPDATEOP;
   opfilter_d := DBMS_CQ_NOTIFICATION.DELETEOP;


   reginfo_iu := cq_notification$_reg_info('callback_iu', qosflags,0, opfilter_iu, 0);
   regid_iu := DBMS_CQ_NOTIFICATION.NEW_REG_START(reginfo_iu);

        OPEN v_cursor FOR 
           SELECT DBMS_CQ_NOTIFICATION.QOS_ROWIDS, department_id, department_name, manager_id, location_id
           FROM HR.departments
        CLOSE v_cursor;

   DBMS_CQ_NOTIFICATION.REG_END;

   reginfo_d := cq_notification$_reg_info('callback_d', qosflags,0, opfilter_d, 0);
   regid_d := DBMS_CQ_NOTIFICATION.NEW_REG_START(reginfo_d);

        OPEN v_cursor FOR 
           SELECT DBMS_CQ_NOTIFICATION.QOS_ROWIDS, department_id, department_name, manager_id, location_id
           FROM HR.departments
        CLOSE v_cursor;

   DBMS_CQ_NOTIFICATION.REG_END;

END;

我知道我可以使用QRCN获得ROWID和“real_id”

CREATE OR REPLACE PROCEDURE chnf_callback
  (ntfnds IN CQ_NOTIFICATION$_DESCRIPTOR)
IS

  event_type      NUMBER;
  tbname          VARCHAR2(60);
  numtables       NUMBER;
  operation_type  NUMBER;
  numrows         NUMBER;
  row_id          VARCHAR2(2000);
  numqueries      NUMBER;
  qid             NUMBER;
  real_id         NUMBER;

BEGIN

  event_type := ntfnds.event_type;

  numqueries :=0;
  IF (event_type = DBMS_CQ_NOTIFICATION.EVENT_QUERYCHANGE) THEN
      numqueries := ntfnds.query_desc_array.count;
      FOR i in 1..numqueries LOOP

         qid := ntfnds.QUERY_DESC_ARRAY(i).queryid;
         numtables := 0;
         numtables := ntfnds.QUERY_DESC_ARRAY(i).table_desc_array.count;
         FOR j IN 1..numtables LOOP
           tbname := ntfnds.QUERY_DESC_ARRAY(i).table_desc_array(j).table_name;
           operation_type := ntfnds.QUERY_DESC_ARRAY(i).table_desc_array(j).Opflags;

           IF (bitand(operation_type, DBMS_CQ_NOTIFICATION.ALL_ROWS) = 0)
           THEN
             numrows := ntfnds.query_desc_array(i).table_desc_array(j).numrows;
           ELSE
             numrows :=0;   /* ROWID INFO NOT AVAILABLE */
           END IF;

            /* The body of the loop is not executed when numrows is ZERO */
            FOR k IN 1..numrows LOOP
               Row_id := ntfnds.query_desc_array(i).table_desc_array(j).row_desc_array(k).row_id;

               select department_id into real_id from hr.departments where rowid = Row_id;
               -->INSERT IN NFROWCHANGES<--
               INSERT INTO nfrowchanges VALUES(qid, tbname, Row_id, real_id);

            END LOOP;  /* loop over rows */
         END LOOP;     /* loop over tables */
       END LOOP;        /* loop over queries */
  END IF;
  COMMIT;
END;

我也知道我可以检查 operation_type 以了解它是Insert(2)还是Update(4),但我无法使用Delete。

那么如何使用OCN获取ROWID和“real_id”并将其传递给回调中的UTL_HTTP.REQ?

DECLARE req  UTL_HTTP.REQ;
        resp UTL_HTTP.RESP;
BEGIN
    req := utl_http.begin_request(
            url    => 'localhost:3000/departments/'||real_id,
            method => 'GET'
        );

    resp := utl_http.get_response(r => req);

    utl_http.end_response(r => resp);

END;

1 个答案:

答案 0 :(得分:1)

我仍然不知道如何使用OCN,在这个解决方案中我使用的是QRCN。由于删除行时无法获取row_id,因此我创建了一个名为“Active”的新列,而不是删除行,所以当我想“删除”一行时,我将“Active”从“Yes”更改为“No” ”。

所以这是使用UTL_HTTP从Inserted / Updated /“Deleted”行发送“real_id”的解决方案。

匿名阻止:

DECLARE

   l_reginfo CQ_NOTIFICATION$_REG_INFO;
   l_cursor  SYS_REFCURSOR;
   l_regid   NUMBER;
   qosflags  NUMBER;

BEGIN

    qosflags := DBMS_CQ_NOTIFICATION.QOS_QUERY + DBMS_CQ_NOTIFICATION.QOS_ROWIDS;
    l_reginfo := cq_notification$_reg_info ('query_callback', qosflags, 0, 0, 0);

    l_regid := dbms_cq_notification.new_reg_start(l_reginfo);

    OPEN l_cursor FOR
        SELECT
            id,
            city_name,
            country_name,
            votes,
            active
        FROM hr.jsao_super_cities
        WHERE active = 'YES';
    CLOSE l_cursor;

    dbms_cq_notification.reg_end;

END;
/

回调:

CREATE OR REPLACE PROCEDURE query_callback
  (ntfnds IN CQ_NOTIFICATION$_DESCRIPTOR)
IS

  event_type      NUMBER;
  numtables       NUMBER;
  operation_type  NUMBER;
  numrows         NUMBER;
  row_id          VARCHAR2(2000);
  is_active       VARCHAR2(20);
  numqueries      NUMBER;
  real_id         NUMBER;
  l_req  UTL_HTTP.REQ;
  l_resp UTL_HTTP.RESP;

BEGIN 

  event_type := ntfnds.event_type;

  numqueries :=0;
  IF (event_type = DBMS_CQ_NOTIFICATION.EVENT_QUERYCHANGE) THEN
      numqueries := ntfnds.query_desc_array.count;
      FOR i in 1..numqueries LOOP

         numtables := 0;
         numtables := ntfnds.QUERY_DESC_ARRAY(i).table_desc_array.count;
         FOR j IN 1..numtables LOOP

           operation_type := ntfnds.QUERY_DESC_ARRAY(i).table_desc_array(j).Opflags;

           IF (bitand(operation_type, DBMS_CQ_NOTIFICATION.ALL_ROWS) = 0)
           THEN
             numrows := ntfnds.query_desc_array(i).table_desc_array(j).numrows;
           ELSE
             numrows :=0;
           END IF;


            FOR k IN 1..numrows LOOP

               Row_id := ntfnds.query_desc_array(i).table_desc_array(j).row_desc_array(k).row_id;

               --getting "real_id"
               select id into real_id from hr.jsao_super_cities where rowid = Row_id;

                -- 2 = insert
                IF(operation_type = 2) THEN
                    l_req := utl_http.begin_request(
                        url    => 'localhost:3000/city/'||real_id,
                        method => 'GET'
                    );

                    l_resp := utl_http.get_response(r => l_req);

                    utl_http.end_response(r => l_resp);

                -- 4 = update
                ELSIF (operation_type = 4) THEN

                    select active into is_active from hr.jsao_super_cities where id = real_id;

                    IF (is_active = 'YES') THEN

                        l_req := utl_http.begin_request(
                            url    => 'localhost:3000/city/'||real_id,
                            method => 'GET'
                        );

                        l_resp := utl_http.get_response(r => l_req);

                        utl_http.end_response(r => l_resp);

                    ELSIF (is_active = 'NO') THEN

                        l_req := utl_http.begin_request(
                            url    => 'localhost:3000/delete/'||real_id,
                            method => 'GET'
                        );

                        l_resp := utl_http.get_response(r => l_req);

                        utl_http.end_response(r => l_resp);

                    END IF;
                END IF;
            END LOOP;  /* loop over rows */
         END LOOP;     /* loop over tables */
       END LOOP;        /* loop over queries */
  END IF;



END query_callback;
/

我希望这可以帮助别人。