【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博客

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

相关推荐
bksczm40 分钟前
Redis 持久化:RDB 快照与 AOF 日志
数据库·redis·mybatis
.痞老板.1 小时前
mysql初阶--数据库设计
数据库·mysql·oracle
Decay__3 小时前
SQL Server 数据库全栈运维实战系列 — 合集索引(24 篇)
运维·数据库·sql·mysql·架构
Thanks_ks3 小时前
SQL 的 GROUP BY 与聚合函数:从会写 SELECT 到会做统计
数据库·sql·mysql·group by·数据统计·聚合函数·having
Decay__11 小时前
12_MySQL InnoDB 内存与锁调优 —— Buffer Pool、redo log、隔离级别与锁等待
运维·数据库·sql·mysql·架构
笃行35012 小时前
AI数据库的库内四层结构,KingbaseES 产品拆解
数据库
我是大猴子13 小时前
redis
数据库·redis·缓存
苏宸啊15 小时前
MySQL(一)
数据库·mysql
2603_9696948516 小时前
JDBC 基础学习笔记:API 核心原理解析与 CRUD 代码实操
数据库·笔记·mysql·学习方法·database·sql注入
这个DBA有点耶16 小时前
库内语义构建 vs 外挂向量库:业务语义缺失,才是RAG“胡说八道”的根源
数据库·mysql·aigc