【Oracle专栏】解决clob+dblink 插入报错 ORA-22992

Oracle && OceanBase 相关文档,希望互相学习,共同进步

风123456789~-CSDN博客


1.背景

今天需要将远端的一张表中的clob字段,插入本地的表字段中。发现单表插入可以,但是再带一个本库表的限制条件,就会报下面的错误:

(clob+dblink "ORA-22992:无法使用从远程表选择的 LOB定位符")

2. 实验

2.1 表准备

表 ANNEX_TMP :其中 attachments字段为clob,准备存放远端@xxx 表的clob字段。

表 TBL_EXTRACT_BANK_ALL :存放 bank_code 字段的范围

sql 复制代码
create table ANNEX_TMP
(
  kid         VARCHAR2(32) not null,
  attachments CLOB,
  bank_code   VARCHAR2(32) not null
);

2)远端:表 ZCS_DIS@xxx

表 ZCS_DIS@xxx:其中 pro_atta_down 字段为clob,存放的逗号分隔的 xxids 字符串。

sql 复制代码
select t.kid,t.pro_atta_down,t.bank_code,to_char(pro_atta_down) bb
  from zcs_dis@zcs t
 where t.pro_atta_down is not null
 and kid='1803966222369718273'

2.2 查询

本地查询:带exists 条件 和不带它 都 ok

sql 复制代码
--带条件查询 ok
select t.kid,t.pro_atta_down,t.bank_code,to_char(pro_atta_down) bb
  from zcs_dis@zcs t
 where t.pro_atta_down is not null
 and kid='1803966222369718273'
and EXISTS (SELECT 1 FROM TBL_EXTRACT_BANK_ALL P
         WHERE P.END_DT = DATE '3000-12-31'
           AND P.BANK_CODE = t.BANK_CODE);

截图: 可以出结果 ok

2.3 插入

1)插入本地表 ORA-22992

在查询的基础上,加上插入:

sql 复制代码
insert into ANNEX_TMP
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code--,to_char(pro_atta_down) bb
  from zcs_dis@zcs t
 where t.pro_atta_down is not null
 and kid='1803966222369718273'
and EXISTS (SELECT 1 FROM TBL_EXTRACT_BANK_ALL P
         WHERE P.END_DT = DATE '3000-12-31'
           AND P.BANK_CODE = t.BANK_CODE);

结果: 报错 ORA-22992 无法使用从远程表选择的 LOB定位符

2)插入本地表 去掉exists, 插入ok

在插入的基础上,去掉 and exists 条件,再次插入

sql 复制代码
insert into ANNEX_TMP
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code--,to_char(pro_atta_down) bb
  from zcs_dis@zcs t
 where t.pro_atta_down is not null
 and kid='1803966222369718273'
/*and EXISTS (SELECT 1 FROM TBL_EXTRACT_BANK_ALL P
         WHERE P.END_DT = DATE '3000-12-31'
           AND P.BANK_CODE = t.BANK_CODE)*/;

结果: 插入ok

3)插入本地表 加上 exists 条件 + 去掉clob条件,插入 ok

在插入的基础上,加上 exists 条件 + 去掉clob条件,再次插入 ok

sql 复制代码
insert into ANNEX_TMP
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code--,to_char(pro_atta_down) bb
  from zcs_dis@zcs t
 where /*t.pro_atta_down is not null
 and*/ kid='1803966222369718273'
and EXISTS (SELECT 1 FROM TBL_EXTRACT_BANK_ALL P
         WHERE P.END_DT = DATE '3000-12-31'
           AND P.BANK_CODE = t.BANK_CODE);

结果:ok

问题出现:远端clob字段是可以插入本地clob字段中的,可以带clob字段的条件,但是不能跨库。改为and exists 为远端的限制条件,再次测试:

4)插入本地表 加上 远端exists 条件 + clob条件,插入 ok

在插入的基础上,加上 远端exists 条件 + clob条件,再次插入 ok

sql 复制代码
insert into ANNEX_TMP
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code
  from zcs_dis@zcs t
 where t.pro_atta_down is not null
 and kid='1803966222369718273'
and EXISTS (SELECT 1 FROM ZCS_DIS@ZCS P
         WHERE  P.BANK_CODE = t.BANK_CODE)

结果:ok

同一个dblink的远端限制条件,才被认为是同样的远端。用户.表 这种格式也会被认为是分布式查询。分布式查询的where 子句+ 直接传递 lob定位器 不支持。

5)插入本地表 加上 远端另一个库的exists 条件 + clob条件,报错

在插入的基础上,加上 远端另一个库的exists 条件 + clob条件,再次插入 报错

sql 复制代码
insert into ANNEX_TMP
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code
  from zcs_dis@zcs t
 where t.pro_atta_down is not null
 and kid='1803966222369718273'
and EXISTS (SELECT 1 FROM sys_bank@basic P
         WHERE  P.BANK_CODE = t.BANK_CODE)

结果:插入报错,但是单独查询是可以的,只是插入报错

6)插入本地表 任何dblink + 去掉clob字段条件 ok

sql 复制代码
insert into ANNEX_TMP
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code
  from zcs_dis@zcs t
 where /*t.pro_atta_down is not null
 and*/ kid='1803966222369718273'
and EXISTS (SELECT 1 FROM sys_bank@basic P
         WHERE  P.BANK_CODE = t.BANK_CODE)

结果: 可以加任何条件,但是不能和clob字段的条件同时存在

2.4 验证结果

通过2.3实验,发现是clob字段条件 不能 和分布式表条件一起用来插入,否则会报错。为了验证,下面改为两个分布式表直接连接,再次验证上面的结果。

1)直接连接 验证问题

sql 复制代码
select t.kid,t.pro_atta_down,t.bank_code
  from zcs_dis@zcs t,TBL_EXTRACT_BANK_ALL P
 where /*t.pro_atta_down is not null
 and*/ t.kid='1803966222369718273'
AND P.END_DT = DATE '3000-12-31'
 AND P.BANK_CODE = t.BANK_CODE

结果: 放开clob条件会报错,注释掉后 正常查询。

网上找资料,显示可能是由于 ‌DBLink 对 LOB 的支持限制 ‌。Oracle 在某些版本中,不支持在分布式查询的 WHERE 子句包含复杂逻辑时直接传递 LOB 定位器。

2)处理解决

解决:创建本地临时表,在本地进行关联过滤和最终插入。将"跨库 LOB 传输"和"本地逻辑判断"分离开,避免了 Oracle 分布式引擎在处理 LOB 时的类型检查冲突*。*

sql 复制代码
--1清空
truncate table ANNEX_TMP;

--2创建临时表1
create table ANNEX_TMP1 as select * from ANNEX_TMP;
sql 复制代码
--3插入临时表1
insert into ANNEX_TMP1
  (kid, attachments, bank_code)   
select t.kid,t.pro_atta_down,t.bank_code
  from zcs_dis@zcs t,TBL_EXTRACT_BANK_ALL@tbl P
 where /*t.pro_atta_down is not null
 and*/ t.kid='1803966222369718273'
AND P.END_DT = DATE '3000-12-31'
 AND P.BANK_CODE = t.BANK_CODE
 ;
commit;

--4插入表
insert into ANNEX_TMP
  (kid, attachments, bank_code)
select * from ANNEX_TMP1;
commit;
sql 复制代码
--查询表
select t.*,to_char(t.attachments) aa,
       DBMS_LOB.SUBSTR(t.attachments,4000,1) bb
 from ANNEX_TMP t;

结果:ok 解决

3.实验总结

总结:解决 clob+dblink 怪异插入 "ORA-22992:无法使用从远程表选择的 LOB定位符"。可以使用创建本地临时表,在本地进行关联过滤和最终插入。将"跨库 LOB 传输"和"本地逻辑判断"分离开,避免了 Oracle 分布式引擎在处理 LOB 时的类型检查冲突*。*

采用"先落地,后处理"策略 ‌:由于涉及 DBLink 和 CLOB,直接带复杂 WHERE 条件的插入容易触发内部类型错误。先将远端数据 INSERT 到本地一个临时表中(这一步通常成功),然后在本地表之间进行 INSERT ... SELECT ... WHERE EXISTS 操作。这是处理跨库大字段最稳定、性能也可控的方法。

实验验证:ok


Oracle其他文档,希望互相学习,共同进步

【Oracle专栏】五类约束命名 && 实践建议

【Oracle专栏】自治事务AT实验、知识点整理

【Oracle专栏】跨服务器调用ORA-02064: 不支持分布式操作

【Oracle专栏】优化慢的查询

【Oracle专栏】字符串截取练习

【Oracle专栏】ORA-02069: global_names 参数

【Linux && Oracle】Linux调用oracle 返回值

【Oracle专栏】密码到期但在宽限期->修改密码

Oracle-找回误删的表数据(LogMiner 挖掘日志)_oracle日志挖掘恢复数据-CSDN博客

oracle 跟踪文件--审计日志_oracle审计日志-CSDN博客

欢迎各位同行点赞、评论、收藏,共同探讨!💪

相关推荐
zyseo84 小时前
谷歌SEO 准首页词挖掘脚本:找出排在第 8-20 名的隐藏流量
大数据·数据库·人工智能
xiaogai_gai6 小时前
仅查询策略实战:从金蝶云·星空旗舰版定时拉取收料通知单
大数据·数据库·python
数据工匠老o6 小时前
异构数据库DDL同步:260条链路的结构变更自动适配方案
数据库·架构
这个DBA有点耶7 小时前
银行业市占率最高的国产数据库是谁?先搞清楚“市占率”的四种口径
数据库·程序员·架构
用户6279947182628 小时前
南大通用GBase 8a之基于审计日志的冷温热数据分析
数据库
数据库小学妹8 小时前
数据库运维五级成熟度:监控、备份、高可用怎么串起来
运维·数据库·监控
一个天蝎座的程序猿8 小时前
为了给报表提速,我把金仓KES的列存储折腾了个遍:聊聊KES的技术能力
数据库
飞越未来云城的霓虹飞猪8 小时前
AI 数据库地图:从 PostgreSQL 到向量数据库,一次看懂 AI 时代的数据底座
数据库
不像程序员的程序媛8 小时前
导出mysql数据结构
数据库·mysql
GlobalTradercrb8 小时前
独立站SEO先写博客还是先优化产品页?看站点阶段
数据库·人工智能·google·pdf·go·seo