简体   繁体   English

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

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

Is there any way to update a XMLType column in Oracle 12c if the xmltype object is not schema based - ie it is generated outside of the Oracle database? 如果xmltype对象不是基于架构的,即在Oracle数据库外部生成的,是否有任何方法可以更新Oracle 12c中的XMLType列? I am trying to update just one field within one XML record in the Oracle database. 我正在尝试只更新Oracle数据库中一个XML记录中的一个字段。 For a simple xml such as: 对于简单的xml,例如:

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

I would like to change the text in field d1 from foo to newText . 我想将字段d1的文本从foo更改为newText Hence I have tried: 因此,我尝试了:

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

  WHERE rowid = 'AAAHUBAAoAAAA0SAAA';

However I obtain the error: 但是我得到了错误:

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.

How can I generalise my code to work for my non-schema xml file? 如何将我的代码泛化为适用于我的非模式xml文件?

[Edit] Here is the trigger that is being used - I didn't create this [编辑]这是正在使用的触发器-我没有创建此触发器

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;

Your trigger is validating the schema. 您的触发器正在验证架构。 Your sample XML doesn't have a schema. 您的示例XML没有架构。 Assuming your real XML doesn't actually have a schema that you've omitted and that the update is removing, then it was presumably inserted into the table before the trigger was created. 假设您的真实XML实际上并没有您已省略的架构并且该更新正在删除,那么大概是在创建触发器之前将其插入到表中。

You seem to have three choices: 您似乎有三个选择:

  1. update the XML to include a valid schema. 更新XML以包括有效模式。

  2. remove the trigger. 删除触发器。

  3. modify the trigger to skip the validation for non-schema XML: 修改触发器以跳过对非架构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;
/

Or if you want to ensure all new entries are schema-based, only do that check on update: 或者,如果您想确保所有新条目基于架构,则仅在更新时进行检查:

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

But that doesn't prevent an existing schema-based value being updated to a non-schema-based value. 但这并不能阻止将现有的基于架构的值更新为基于非架构的值。

Your update statement works but does not affect the xml. 您的更新语句有效,但不影响xml。 If you remove the superfluous second UPDATEXML it does what it is supposed to do. 如果删除多余的第二个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;

I have tested this with Oracle 11.2. 我已经使用Oracle 11.2对此进行了测试。

You can simplify your statement: 您可以简化您的声明:

Sample data : 样本数据

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

Update : 更新

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

Output : 输出

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