Генерация OracleType Oracle с нулевыми значениями от триггера до расширенной очереди - PullRequest
2 голосов
/ 17 декабря 2010

Добрый день.

Я работал с Oracle Advanced Queues, чтобы создать систему обмена сообщениями, которую мы можем использовать для определения, когда новые строки передаются в базу данных, когда происходят обновления и когда происходят удаления.

Я использую одну очередь потребителей и использую корреляции для управления тем, какие данные ищутся в определенное время, а моя полезная нагрузка имеет тип xml.

Для генерации xml я изначально использовал последовательность xml для генерациисообщение, как показано ниже.

<MESSAGE>
<LOCATIONS>
  <LOCATION_ID>9999</LOCATION_ID>
  <LOC_TYPE>S</LOC_TYPE>
  <NAME>Test Location</NAME>
  <RETAILER_UNIT_CODE>T&amp;L</RETAILER_UNIT_CODE>
  <REGION_CODE>SA</REGION_CODE>
  <DELETE_FLAG>N</DELETE_FLAG>
  <EXTERNAL_WHSE_FLAG>N</EXTERNAL_WHSE_FLAG>
  <CREATED_BY>SYSADMIN</CREATED_BY>
  <CREATED_DATE>04/MAR/08</CREATED_DATE>
  <STATE_CODE>SA</STATE_CODE>
  <ADDRESS>223 Road Ridsonville</ADDRESS>
  <POSTCODE>1234</POSTCODE>
  <PHONE_NUM>08 </PHONE_NUM>
  <LAST_MODIFIED_BY>SYSADMIN</LAST_MODIFIED_BY>
  <LAST_MODIFIED_DATE>21/APR/09</LAST_MODIFIED_DATE>
  <POS_CODE>TRANS</POS_CODE>
  <SOP_FLAG>N</SOP_FLAG>
</LOCATIONS>
</MESSAGE>

Однако до меня дошло, что xmlsequence пропускает нулевые элементы, что не является идеальным, как, например, когда приходит время подбирать сообщения на другом конце., они не могут быть легко отображены в поле данных.Чтобы попытаться обойти это, я попытался использовать DBMS_XMLGEN в моем триггере, поскольку он позволяет обрабатывать пустые значения именно так, как я бы хотел, чтобы он обрабатывался.

ctx := dbms_xmlgen.newContext('SELECT * FROM LOCATIONS WHERE LOCATION_ID = ' || :new.LOCATION_ID);
dbms_xmlgen.setrowsettag(ctx, 'MESSAGE');
dbms_xmlgen.setrowtag(ctx, 'LOCATIONS');
dbms_xmlgen.setnullhandling(ctx, dbms_xmlgen.EMPTY_TAG);
l_xml:=dbms_xmlgen.getxmltype(ctx);

Проблема с этимПодход заключается в том, что он будет генерировать исключение, поскольку он пытается работать с той же таблицей, из которой был выполнен триггер.

ORA-04091: table RIT.LOCATIONS is mutating, trigger/function may not see it

Поэтому я перешел к попытке использовать новые и старые объекты дляполучить данные и поместить их в контекст, но я работаю с несколькими сбоями со значениями, которые являются нулевыми, поскольку они играют хаос, когда я объединяю их в строку запроса.

...
REFERENCING NEW AS NEW OLD AS OLD
for each row 
DECLARE
l_xml   xmltype;
ctx       dbms_xmlgen.ctxHandle;
begin
ctx := dbms_xmlgen.newContext('SELECT   '||:new.id||'as id, '||:new.nullfield||' as nullfield from dual');
dbms_xmlgen.setrowsettag(ctx, 'MESSAGE');
dbms_xmlgen.setrowtag(ctx, 'INT_CREDIT_CLAIMS');
dbms_xmlgen.setnullhandling(ctx, dbms_xmlgen.EMPTY_TAG);
l_xml:=dbms_xmlgen.getxmltype(ctx);
...
end;

Итак, мой вопрос: как я могу решить эту проблему, чтобы я мог видеть свои пустые элементы для моего типа xml?

Я также открыт для предложений по пути, как это решить, и будуследите за любыми разъяснениями.

1 Ответ

2 голосов
/ 17 декабря 2010

для генерации простой строки в XML вы можете использовать xmlelement:

SQL> CREATE TABLE emp AS SELECT * FROM scott.emp;

Table created

SQL> CREATE TABLE message (xml XMLTYPE);

Table created

SQL> CREATE OR REPLACE TRIGGER trg_b4_emp
  2     BEFORE UPDATE ON emp
  3     FOR EACH ROW
  4  BEGIN
  5     INSERT INTO message VALUES (
  6       xmlelement("MESSAGE",
  7           xmlelement("EMP",
  8              xmlelement("empno", :new.empno),
  9              xmlelement("comm", :new.comm)
 10           )
 11        )
 12     );
 13  END;
 14  /

SQL> update emp set comm=NULL;

14 rows updated

SQL> select * from message where rownum = 1;

XML
----------------------------------------------------------------
<MESSAGE><EMP><empno>7369</empno><comm></comm></EMP></MESSAGE>
...