一次做几个修改操作

Do several modify operations at once

在下面的代码中,首先需要添加一个元素,在其余代码中创建或更新名为 t 的属性。

declare
  LOG_REFERENCE xmltype:=xmltype('<log  />');
begin

  select  XMLQuery('
    copy $p := $p1 modify insert node <update data="{$p2}" />
              as last into $p/log
    return $p
    ' PASSING LOG_REFERENCE AS "p1", to_char(systimestamp) AS "p2" RETURNING CONTENT)
      INTO LOG_REFERENCE from dual;

  select  XMLQuery('
    copy $i := $p1 modify(
      if (fn:exists($i/log[1]/@t)) then (
        replace value of node $i/log[1]/@t with $p2
      ) else (
        insert node attribute  t {$p2} into $i/log[1]
      )
    )
    return $i
    ' PASSING LOG_REFERENCE AS "p1", to_char(systimestamp) AS "p2" RETURNING CONTENT)
      INTO LOG_REFERENCE from dual;

  dbms_output.PUT_LINE(LOG_REFERENCE.getClobVal());
end;

我的问题是我想像这样将两个修改合并为一个 xquery 调用

declare
  LOG_REFERENCE xmltype:=xmltype('<log  />');
begin

  select  XMLQuery('
    copy $p := $p1 modify(
     insert node <update data="{$p2}" />
              as last into $p/log
    )

    copy $i := $p modify(
      if (fn:exists($i/log[1]/@t)) then (
        replace value of node $i/log[1]/@t with $p2
      ) else (
        insert node attribute  t {$p2} into $i/log[1]
      )
    )

    return $i
    ' PASSING LOG_REFERENCE AS "p1", to_char(systimestamp) AS "p2" RETURNING CONTENT)
      INTO LOG_REFERENCE from dual;

  dbms_output.PUT_LINE(LOG_REFERENCE.getClobVal());
end;

在我看来这是正确的,但显然我遗漏了什么。还是不能在oracle xquery中完成?

给出的错误信息:

ORA-19114: XPST0003 - Error during parsing the XQuery expression: LPX-00801: XQuery syntax error at 'copy' 7 copy $i := $p modify( - ^ ORA-06512: em line 5

您可以在单个修改子句中组合这两个操作:

declare
  LOG_REFERENCE xmltype:=xmltype('<log  />');
begin

  select  XMLQuery('
    copy $p := $p1 modify(
     insert node <update data="{$p2}" />
              as last into $p/log,
      if (fn:exists($p/log[1]/@t)) then (
        replace value of node $p/log[1]/@t with $p2
      ) else (
        insert node attribute  t {$p2} into $p/log[1]
      )
    )

    return $p
    ' PASSING LOG_REFERENCE AS "p1", to_char(systimestamp) AS "p2" RETURNING CONTENT)
      INTO LOG_REFERENCE from dual;

  dbms_output.PUT_LINE(LOG_REFERENCE.getClobVal());
end;
/

<log t="19-JUN-17 21.25.56.434586 +01:00"><update data="19-JUN-17 21.25.56.434586 +01:00"/></log>

PL/SQL procedure successfully completed.

这似乎与您的原始块得到相同的结果,有或没有现有的 t 属性。

顺便说一下,您目前依靠 NLS 会话设置将时间戳格式化为字符串;最好明确地做,例如

...
    ' PASSING LOG_REFERENCE AS "p1",
        to_char(systimestamp, 'YYYY-MM-DD"T"HH24:MI:SS.FF6') AS "p2"
      RETURNING CONTENT)
      INTO LOG_REFERENCE from dual;

获得类似

的输出
<log t="2017-06-19T21:28:54.896506"><update data="2017-06-19T21:28:54.896506"/></log>