如何根据条件从 Oracle XMLTYPE 中删除节点?
How to delete a node from Oracle XMLTYPE based on a condition?
我有一个 XML 数据存储在 CLOB
列中,我想根据特定条件删除一些节点。
示例XML数据:
<?xml version="1.0" encoding="UTF-8"?>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
<person>
<surname>ABC</surname>
<name>TEST</name>
<salary>1234</salary>
<person>
<surname>Tiger</surname>
<name>Scott</name>
<salary>2222</salary>
</person>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
<person>
<surname>LMN</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
我需要一个 Oracle PLSQL 脚本来删除所有包含 TEST 的人员标签。
最终输出为:
<?xml version="1.0" encoding="UTF-8"?>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
</payment>
提前致谢。
您提供的 XML 没有根,XML 解析器无法解析。
假设它确实如此(比如 payments
),如下所示:
create table t(txt clob);
insert into t values('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
<person>
<surname>ABC</surname>
<name>TEST</name>
<salary>1234</salary>
<person>
<surname>Tiger</surname>
<name>Scott</name>
<salary>2222</salary>
</person>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
<person>
<surname>LMN</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
</payments>');
你可以使用这个:
update t
set txt = to_clob(deletexml(
xmltype(t.txt),
'//payment/person[./name[text()="TEST"]]'
));
生产:
<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
</payment>
</payments>
编辑:
如果要删除没有给定子节点的节点,请使用:
update t
set txt = to_clob(deletexml(
xmltype(t.txt),
'//payment[not(./person)]'
));
它将删除所有没有人的付款标签。
deleteXML() 已被弃用。如果可能,您应该使用 XQuery 更新。如果完整路径是固定的,也尽量避免使用“//”。
with XML_TABLE as
(
select XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
<person>
<surname>ABC</surname>
<name>TEST</name>
<salary>1234</salary>
<person>
<surname>Tiger</surname>
<name>Scott</name>
<salary>2222</salary>
</person>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
<person>
<surname>LMN</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
</payments>') as XML_COLUMN from dual
)
SELECT XMLQuery(
'copy $NEWXML := $XML modify (
delete nodes $NEWXML/payments/payment/person[name[text()=$NAME]]
)
return $NEWXML'
passing XML_COLUMN as "XML",
'TEST' as "NAME"
returning CONTENT
)
from XML_TABLE
/
您可以尝试使用 SQL Workbench 在 livesql.oracle.com
截取此代码
这个有效
with XML_TABLE as
(
select XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
<id>person 4</id>
</payment>
<payment>
<id>person 5</id>
</payment>
</payments>') as XML_COLUMN from dual
)
SELECT XMLQuery(
'copy $NEWXML := $XML modify (
delete nodes $NEWXML/payments/payment[not(person)]
)
return $NEWXML'
passing XML_COLUMN as "XML",
'TEST' as "NAME"
returning CONTENT
)
from XML_TABLE
<?xml version="1.0" encoding="WINDOWS-1252"?>
<payments>
<payment>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
<id>person 4</id>
</payment>
</payments>
SQL>
我有一个 XML 数据存储在 CLOB
列中,我想根据特定条件删除一些节点。
示例XML数据:
<?xml version="1.0" encoding="UTF-8"?>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
<person>
<surname>ABC</surname>
<name>TEST</name>
<salary>1234</salary>
<person>
<surname>Tiger</surname>
<name>Scott</name>
<salary>2222</salary>
</person>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
<person>
<surname>LMN</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
我需要一个 Oracle PLSQL 脚本来删除所有包含 TEST 的人员标签。
最终输出为:
<?xml version="1.0" encoding="UTF-8"?>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
</payment>
提前致谢。
您提供的 XML 没有根,XML 解析器无法解析。
假设它确实如此(比如 payments
),如下所示:
create table t(txt clob);
insert into t values('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
<person>
<surname>ABC</surname>
<name>TEST</name>
<salary>1234</salary>
<person>
<surname>Tiger</surname>
<name>Scott</name>
<salary>2222</salary>
</person>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
<person>
<surname>LMN</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
</payments>');
你可以使用这个:
update t
set txt = to_clob(deletexml(
xmltype(t.txt),
'//payment/person[./name[text()="TEST"]]'
));
生产:
<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
</payment>
</payments>
编辑:
如果要删除没有给定子节点的节点,请使用:
update t
set txt = to_clob(deletexml(
xmltype(t.txt),
'//payment[not(./person)]'
));
它将删除所有没有人的付款标签。
deleteXML() 已被弃用。如果可能,您应该使用 XQuery 更新。如果完整路径是固定的,也尽量避免使用“//”。
with XML_TABLE as
(
select XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>Marco</surname>
<name>Gralike</name>
<salary>2345</salary>
</person>
<person>
<surname>ABC</surname>
<name>TEST</name>
<salary>1234</salary>
<person>
<surname>Tiger</surname>
<name>Scott</name>
<salary>2222</salary>
</person>
</person>
</payment>
<payment>
<person>
<surname>BertJan</surname>
<name>Meinders</name>
<salary>3456</salary>
<salary>125</salary>
</person>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
<payment>
<person>
<surname>Chris</surname>
<name>Gralike</name>
<salary>4567</salary>
</person>
<person>
<surname>LMN</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
</payment>
</payments>') as XML_COLUMN from dual
)
SELECT XMLQuery(
'copy $NEWXML := $XML modify (
delete nodes $NEWXML/payments/payment/person[name[text()=$NAME]]
)
return $NEWXML'
passing XML_COLUMN as "XML",
'TEST' as "NAME"
returning CONTENT
)
from XML_TABLE
/
您可以尝试使用 SQL Workbench 在 livesql.oracle.com
截取此代码这个有效
with XML_TABLE as
(
select XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<payments>
<payment>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
<id>person 4</id>
</payment>
<payment>
<id>person 5</id>
</payment>
</payments>') as XML_COLUMN from dual
)
SELECT XMLQuery(
'copy $NEWXML := $XML modify (
delete nodes $NEWXML/payments/payment[not(person)]
)
return $NEWXML'
passing XML_COLUMN as "XML",
'TEST' as "NAME"
returning CONTENT
)
from XML_TABLE
<?xml version="1.0" encoding="WINDOWS-1252"?>
<payments>
<payment>
<person>
<surname>XYZ</surname>
<name>TEST</name>
<salary>1234</salary>
</person>
<id>person 4</id>
</payment>
</payments>
SQL>