繁体   English   中英

更新Oracle 12c中的非模式XMLType列?

[英]Update a non-schema XMLType column in Oracle 12c?

如果xmltype对象不是基于架构的,即在Oracle数据库外部生成的,是否有任何方法可以更新Oracle 12c中的XMLType列? 我正在尝试只更新Oracle数据库中一个XML记录中的一个字段。 对于简单的xml,例如:

<a>
  <b>
    <c>
      <d1>foo</d1>
      <d2>bar</d2>
       ...
    </c>
  </b>
</a>

我想将字段d1的文本从foo更改为newText 因此,我尝试了:

UPDATE myXmlTable
  SET myXmlColumn = updatexml(myXmlColumn ,
                              '/a/text()',
                              updatexml(extract(myXmlColumn , '/a/ *'),
                                        'b/c/d1/text()',
                                        'newText')
                              )

  WHERE rowid = 'AAAHUBAAoAAAA0SAAA';

但是我得到了错误:

SQL Error: ORA-19030: Method invalid for non-schema based XML Documents.
ORA-06512: at "SYS.XMLTYPE", line 354
ORA-06512: at "DIC_OWNER.XML_TRIG", line 8
ORA-04088: error during execution of trigger 'DIC_OWNER.XML_TRIG'
19030. 00000 -  "Method invalid for non-schema based XML Documents."
*Cause:    The method can be invoked on only schema based xmltype objects.
*Action:   Don't invoke the method for non schema based xmltype objects.

如何将我的代码泛化为适用于我的非模式xml文件?

[编辑]这是正在使用的触发器-我没有创建此触发器

create or replace trigger xml_trig before insert
or update on myXmlTable
for each row

declare

  newxml XMLType;

begin

  newxml := :new.OBJECT_VALUE;
  XMLType.schemavalidate(newxml);

end;

您的触发器正在验证架构。 您的示例XML没有架构。 假设您的真实XML实际上并没有您已省略的架构并且该更新正在删除,那么大概是在创建触发器之前将其插入到表中。

您似乎有三个选择:

  1. 更新XML以包括有效模式。

  2. 删除触发器。

  3. 修改触发器以跳过对非架构XML的验证:

create or replace trigger xml_trig
before insert or update on myXmlTable
for each row
begin
  if :new.myxmlcolumn.isschemabased() = 1 then
    XMLType.schemavalidate(:new.myxmlcolumn);
  end if;
end;
/

或者,如果您想确保所有新条目基于架构,则仅在更新时进行检查:

  if inserting or :new.myxmlcolumn.isschemabased() = 1 then
    XMLType.schemavalidate(:new.myxmlcolumn);
  end if;

但这并不能阻止将现有的基于架构的值更新为基于非架构的值。

您的更新语句有效,但不影响xml。 如果删除多余的第二个UPDATEXML,它将执行应做的事情。

CREATE TABLE myXmlTable (myXmlColumn XMLTYPE);

INSERT INTO myXmlTable (myXmlColumn) VALUES (XMLTYPE('<a>
                                                        <b>
                                                          <c>
                                                            <d1>foo</d1>
                                                            <d2>bar</d2>
                                                             ...
                                                          </c>
                                                        </b>
                                                      </a>'));

COMMIT; 

UPDATE myXmlTable
SET myXmlColumn = updatexml(myXmlColumn,
                          'a/b/c/d1/text()',
                                    'newText'),
COMMIT;

SELECT XMLSERIALIZE(DOCUMENT myXmlColumn INDENT)
FROM myXmlTable;

我已经使用Oracle 11.2对此进行了测试。

您可以简化您的声明:

样本数据

CREATE TABLE yourtable ( yourxmlcolumn ) AS
  SELECT XMLTYPE( '<a><b><c><d1>foo</d1><d2>bar</d2></c></b></a>' ) FROM DUAL;

更新

UPDATE yourtable
SET yourxmlcolumn = UPDATEXML(
                      yourxmlcolumn,
                      '/a/b/c/d1/text()',
                      'newText'
                    );

输出

UPDATEDXML
-------------------------------------------------
<a><b><c><d1>newText</d1><d2>bar</d2></c></b></a>

暂无
暂无

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

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