在 Oracle XMLQuery 中组合 "Transform" 和 FLWOR 表达式

Combining "Transform" and FLWOR expressions in Oracle XMLQuery

在下面的代码中,我试图将 oldXml2 中的 "name" 元素插入到 oldXml 中,并将 oldXml 中的 "test" 属性值更新为 "newTest",得到的组合输出是新的XML。 代码成功更改了属性值但是,当我添加:

let $newName := $b/users/user/name

从 oldXml2 获取名称元素的子句停止工作。 有人能解决这个问题吗?

我正在使用 Oracle 11g,它使用 xquery 1.0。

WITH myXml AS (select 1 id, xmltype(
 '<users>
  <user test="oldvalue">
   <userid>id1</userid>
   <name>dave</name>
  </user>
</users>
'
 ) oldXml
 from dual),
myXml2 AS (select 1 id,xmltype(
 '<users>
  <user>
   <userid>id2</userid>
   <name>steve</name>
  </user>
</users>
'
 ) oldXml2
 from dual)
  SELECT oldXml,oldXml2,
XMLQuery(' copy $c := $a
       (: let $newName := $b/users/user/name :)  (: If you add this clause it doesnt work:)
         modify ( rename node $c/users/user/@test as "newTest")
        return $c'
                PASSING a.oldXml as "a" ,b.oldXml2 as "b" RETURNING CONTENT)  newXml
   FROM myXml a
   JOIN myXml2 b
   ON a.id = b.id;

newXml 中要求的输出是:

<users>
        <user test="newTest">
           <userid>id1</userid>
           <name>dave</name>
        </user>
       <user>
           <userid>id2</userid>
           <name>steve</name>
      </user>
</users>

您需要先执行 let 并为其提供自己的 return 子句,然后在其中执行 copy/modify:

SELECT oldXml, oldXml2,
  XMLQuery('
    let $newName := $b/users/user/name
    return 
      copy $c := $a
      modify (rename node $c/users/user/@test as "newTest")
      return $c'
  PASSING a.oldXml as "a", b.oldXml2 as "b" RETURNING CONTENT) newXml
FROM myXml a
JOIN myXml2 b
ON a.id = b.id;

然后您可以参考 copy/modify 部分中的 $newName,但不清楚您要如何使用它;或者为什么你想要那个变量而不是直接引用 $b/users/user/name ,除非你的真实代码将在 for 循环中。


你不需要let做你想做的,你可以直接插入$b/users/user节点;使用 XMLSerialize 只是为了格式化输出:

SELECT oldXml, oldXml2,
  XMLSerialize(CONTENT XMLQuery('
    copy $c := $a
    modify (rename node $c/users/user/@test as "newTest",
      insert nodes $b/users/user after $c/users/user)
    return $c'
  PASSING a.oldXml as "a", b.oldXml2 as "b" RETURNING CONTENT)
  AS VARCHAR2(4000) INDENT SIZE=2) newXml
FROM myXml a
JOIN myXml2 b
ON a.id = b.id;

OLDXML                         OLDXML2                        NEWXML                        
------------------------------ ------------------------------ ------------------------------
<users>                        <users>                        <users>                       
  <user test="oldvalue">         <user>                         <user newTest="oldvalue">   
   <userid>id1</userid>           <userid>id2</userid>            <userid>id1</userid>      
   <name>dave</name>              <name>steve</name>              <name>dave</name>         
  </user>                        </user>                        </user>                     
</users>                       </users>                         <user>                      
                                                                  <userid>id2</userid>      
                                                                  <name>steve</name>        
                                                                </user>                     
                                                              </users>                      

如果你添加一个 return,你可以使用 let,就像答案的第一部分一样,但不确定它在这个例子中对你有什么好处 - 也许它在你的实际中更有用场景 - 制作 Xquery:

let $newUser := $b/users/user
return
  copy $c := $a
  modify (rename node $c/users/user/@test as "newTest",
    insert nodes $newUser after $c/users/user)
  return $c