Оракул xmltype генерация с нулевыми значениями от триггера до расширенной очереди
Вопрос
Добрый день.
Я работал с Oracle Advanced Ofeues, чтобы создать систему обмена сообщениями, которую мы можем использовать, чтобы определить, когда новые линии передаются в базу данных, когда происходят обновления и когда происходят удаления.
Я использую одну очередь потребителей и использую корреляции для контроля того, какие данные ищут в определенное время, и моя полезная нагрузка имеет Xmltype.
Чтобы сгенерировать XML, я изначально использовал XML -посылку для генерации сообщения, как показано ниже.
<MESSAGE>
<LOCATIONS>
<LOCATION_ID>9999</LOCATION_ID>
<LOC_TYPE>S</LOC_TYPE>
<NAME>Test Location</NAME>
<RETAILER_UNIT_CODE>T&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>
Тем не менее, мое внимание привлекло к тому, что XML -последовательность оставляет нулевые элементы, что не является идеальным, так как когда настало время для того, чтобы сообщения были подняты на другом конце, их нельзя легко нанести на карту на поле данных. Чтобы попытаться обойти это, я попытался использовать использование 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?
Я также открыт для предложений по пути, как его решить, и буду проверять любые запросы на разъяснения.
Решение
Чтобы сгенерировать простую строку в 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>