oracle - 在 Oracle 中使用多个命名空间更新 CLOB 列
问题描述
我正在尝试更新 oracle DB 中的 clob 列内的元素。
我面临的第一个挑战是我的 clob xml 有 2 个命名空间,我无法让它工作。
<?xml version="1.0"?>
<esbmsg:EsbMessage xmlns:esbmsg="http://www.test.com/esb/message/1.0">
<esbmsg:Body>
<Transaction xmlns="http://test.com">
<test-element>
<finalElement>false</finalElement>
</test-elemen>
</Transaction>
</esbmsg:Body>
</esbmsg:EsbMessage>
select x.* from cc_messagehistory y
cross join xmltable(
xmlnamespaces('http://www.test.com/esb/message/1.0' as "esbmsg",
'http://test.com ' ),
'/esbmsg:EsbMessage'
passing xmltype.createxml(y.payload)
factext varchar2(10) path '/esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement'
) x;
ORA-19102:XQuery 字符串文字预期为 19102。00000 - “XQuery 字符串文字预期” *原因:包含 XQuery 表达式的字符串文字丢失。*操作:将 XQuery 表达式指定为字符串文字。行错误:64 列:99
解决方案
ORA-01902 的直接原因是您错过了default
关键字:
xmlnamespaces('http://www.test.com/esb/message/1.0' as "esbmsg",
default 'http://test.com'),
我已经删除了 URI 末尾的多余空格,这会在以后引起问题。但是您也缺少columns
关键字,您可以简化 CLOB 值到 XMLType 的转换。
将它们放在一起,并使用 CTE 提供您的(更正后的)示例 XML:
-- CTE for sample data
with cc_messagehistory(payload) as (
select to_clob('<?xml version="1.0"?>
<esbmsg:EsbMessage xmlns:esbmsg="http://www.test.com/esb/message/1.0">
<esbmsg:Body>
<Transaction xmlns="http://test.com">
<test-element>
<finalElement>false</finalElement>
</test-element>
</Transaction>
</esbmsg:Body>
</esbmsg:EsbMessage>') from dual
)
-- actual query
select x.*
from cc_messagehistory y
cross join xmltable (
xmlnamespaces (
'http://www.test.com/esb/message/1.0' as "esbmsg",
default 'http://test.com'
),
'/esbmsg:EsbMessage'
passing xmltype(y.payload)
columns factext varchar2(10)
path '/esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement'
) x;
FACTEXT
----------
false
对于更新,您可以执行以下操作:
update cc_messagehistory y
set payload = XMLSerialize(document
XMLQuery('declare default element namespace "http://test.com"; (: :)
declare namespace esbmsg="http://www.test.com/esb/message/1.0"; (: :)
copy $i := $xml modify (
for $j in $i//esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement
return replace value of node $j with $new
)
return $i'
passing xmltype(y.payload) as "xml",
'true' AS "new"
returning content
)
indent size=2
)
where xmlexists('declare default element namespace "http://test.com"; (: :)
declare namespace esbmsg="http://www.test.com/esb/message/1.0"; (: :)
$xml//esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement[text()="false"]'
passing xmltype(y.payload) as "xml");
它将源 CLOB 转换为:
<?xml version="1.0"?>
<esbmsg:EsbMessage xmlns:esbmsg="http://www.test.com/esb/message/1.0">
<esbmsg:Body>
<Transaction xmlns="http://test.com">
<test-element>
<finalElement>true</finalElement>
</test-element>
</Transaction>
</esbmsg:Body>
</esbmsg:EsbMessage>
db<>fiddle(在 18c 上工作;在 11gR2 上出现错误,但补丁级别可能会有所不同;也在 12cR1 的其他地方成功测试过)
推荐阅读
- java - 如何自动接受安卓的蓝牙配对通知
- django - 如何使用 Django 微服务实现 OPA?
- caching - 防止 Aurelia Bundle 浏览器缓存
- sql - SQL查询与上一日期相比的百分比变化
- terraform - AKS 通过 Terraform 错误:代码 =“CustomRouteTableWithUnsupportedMSIType”
- sql - Oracle SQL Developer - 禁用模式中的所有约束
- java - 使用 Java 从 SSH 直接流式传输文件
- php - 我想通过教练和工作时间之间的关系来显示日期和日期
- javascript - 如何在 metro.config 中添加多个 babelTransformerPath
- java - 无法将工件 com.squareup.okhttp3:mockwebserver:pom:4.9.1 从/传输到中央(https://repo.maven.apache.org/maven2)