简体   繁体   English

在XMLTYPE列中插入子节点

[英]Inserting a child node in an XMLTYPE column

I have a simple query: 我有一个简单的查询:

WITH xtbl AS (
  SELECT XMLTYPE ('<a><b>1</b></a>') AS xcol 
    FROM DUAL
)
SELECT XMLQUERY ('copy $tmp := . 
                    modify 
                       insert node <c>2</c>
                         into $tmp/a/b
                       return $tmp'
                 PASSING xcol 
               RETURNING CONTENT) AS newxcol
  FROM xtbl;

What I'm trying to do is to insert a node <c> after <b> inside the node <a> but Oracle 12c is throwing this error: 我想要做的是在节点<a> <b>之后插入节点<c>但是Oracle 12c抛出了这个错误:

ORA-19114: XPST0003 - error during parsing the XQuery expression: 
           LPX-00801: XQuery syntax error at 'EOF'
           5   -
           -  ^

I want the output as: 我希望输出为:

NEWXCOL
-------------
<a>
    <b>1</b>
    <c>2</c/>
</a>

I have tried looking in Oracle Docs for a replacement of appendChildXML and follow that example but only got the error. 我已经尝试在Oracle Docs中寻找appendChildXML的替代品并遵循该示例但只得到了错误。

I know it is very basic and I'm missing something obvious. 我知道这是非常基本的,我错过了一些明显的东西。 Please help. 请帮忙。

Following code should be working for 11 and 12 (deprecated): 以下代码应适用于11和12(不建议使用):

SELECT insertXMLafter(XMLType('<a><b>1</b><c>3</c></a>'),
                 '/a/b', XmlType('<c>2</c>'))
  FROM dual;

Same code using new XMLQuery syntax: 使用新XMLQuery语法的相同代码:

SELECT XMLQuery('copy $tmp := . modify insert node 
                 <c>2</c>
                 after $tmp/a/b 
                 return $tmp'
                PASSING XmlType('<a><b>1</b><c>3</c></a>') RETURNING CONTENT)
  FROM dual;

More details regarding XMLQuery and also the old deprecated functions can be found here: http://docs.oracle.com/database/121/ADXDB/app_depr_upd.htm#ADXDB6160 有关XMLQuery以及旧的已弃用函数的更多详细信息,请访问: http//docs.oracle.com/database/121/ADXDB/app_depr_upd.htm#ADXDB6160

One ugly but possible way to use only one SQL query that works correctly on older and current database versions would be to use the CASE method in SQL: 一种丑陋但可能的方法是只使用一个在旧版和当前数据库版本上正常工作的SQL查询,就是在SQL中使用CASE方法:

WITH tbl AS
 (SELECT SUBSTR(MAX(version),1,2) as ver, XMLType('<a><b>1</b><c>3</c></a>') as xcol
    FROM v$instance)
SELECT 
   CASE WHEN ver < '12' THEN
      insertXMLafter(xcol,
                 '/a/b', XmlType('<c>2</c>'))
   ELSE
      XMLQuery('copy $tmp := . modify insert node 
                 <c>2</c>
                 after $tmp/a/b 
                 return $tmp'
                PASSING xcol RETURNING CONTENT) 
   END
FROM tbl;

Of course that won't help you if the insertXMLafter method gets removed in future releases of the database. 当然,如果在将来的数据库版本中删除insertXMLafter方法,那将无济于事。 That would produce an invalid SQL. 这会产生无效的SQL。 But for now you would be good and use the right method on the right versions. 但是现在你会很好并且在正确的版本上使用正确的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM