2

下午好。

我一直在使用 Oracle Advanced Queues 创建一个消息传递系统,我们可以使用它来确定何时将新行传递到数据库中、何时发生更新以及何时发生删除。

我正在使用单个消费者队列并使用相关性来控制在特定时间查找哪些数据,并且我的有效负载是 xmltype。

为了生成 xml,我最初是使用 xmlsequence 来生成消息,如下所示。

<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 类型的空元素?

我也愿意接受有关如何解决它的建议,并将检查是否有任何澄清请求。

4

1 回答 1

2

要在 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>
于 2010-12-17T11:43:44.420 回答