【YashanDB知识库】oracle dblink varchar类型查询报错记录

简介: 这篇文章主要介绍了 Oracle DBLINK 查询崖山 DB 报错的相关内容,包括 ODBC 安装配置、数据源配置、dblink 环境配置、问题原因分析及规避方法。问题原因是 dblink 连接其他数据库时 varchar 类型转换导致的,还介绍了 long 类型限制、char 等类型区别,规避方法是修改参数 MAX_STRING_SIZE 支持 32K。

问题单:Oracle DBLINK查询崖山DB报错

oracle服务器上ODBC安装

unixodbc安装:yum -y install unixODBC

mysql

配置安装对应版本的odbc

myodbc-installer -d -a -n "MySQL8.0" -t "DRIVER=/home/oracle/tools/mysql-connector-odbc-8.0.20/lib/libmyodbc8w.so;SETUP=/home/oracle/tools/mysql-connector-odbc-8.0.20/lib/myodbc8S.so"

yashandb

安装yasdb-odbc

安装yasdb-client

配置odbc驱动:

sudo vi /etc/odbcinst.ini
[YashanDB] Description=ODBC for yashanDB
Driver=/home/oracle/xp/yashandb-odbc/libyas_odbc.so
Setup=/home/oracle/xp/yashandb-odbc/libyas_odbc.so
Driver64=/home/oracle/xp/yashandb-odbc/libyas_odbc.so
Setup64=/home/oracle/xp/yashandb-odbc/libyas_odbc.so FileUsage=1

[ODBC]
Trace=NO/YES #yes打开odbc日志
TraceFile=/home/oracle/xp/odbc.log

添加环境变量:

vi .bashrc
export LD_LIBRARY_PATH=​LD_LIBRARY_PATH:/home/oracle/xp/yashandb-odbc

配置数据源

sudo vi /etc/odbc.ini
[YASDBODBC]
Description = YASODBC
Driver = YashanDB
SERVER = 192.168.18.207 PORT = 8688
USER = sys
PWD = yasdb_123

[MYSQLDB]
Description = MySQL ODBC 5.0 Unicode Driver
Driver = MySQL8.0
Server = 192.168.7.134
Database = zabbix
Port = 3306
USER = zabbix
Password = 123456
Option = 3
CHARSET = UTF8

配置oracle dblink环境

监听文件配置

/data/app/oracle/product/19.3/dbhome_1/network/admin

vi listener.ora

新增:

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = YASDBODBC)
(ORACLE_HOME = /data/app/oracle/product/19.3/dbhome_1)
(PROGRAM = dg4odbc)
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = MYSQLDB)
(ORACLE_HOME = /data/app/oracle/product/19.3/dbhome_1)
(PROGRAM = dg4odbc)
)
)

坑1:

配置这个后,oracle的远程连接报错。

修改如下:

listener.ora有三个部分

详解各个属性:

1、LISTENER部分包含协议地址列表,每个实例一个入口,监听名称,可以配置多个监听,多个监听的端口号要区分开来

2、SID_LIST_LISTENER部分标识全局数据库名称、标识监听程序正在服务的每个实例的Oracle软件主目录以及实例或SID。

3、SID_LIST描述用于静态数据库注册、保持和以前的版本兼容性以及供Oracle Enterprise Manager使用,因为我本地有三个数据库

把SID_DESC 放到SID_LIST_LISTENER中

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = oracledb)
      (ORACLE_HOME = /data/app/oracle/product/19.3/dbhome_1)
      (SID_NAME = oracledb)
    )

    (SID_DESC =
      (SID_NAME = YASDBODBC)
      (ORACLE_HOME = /data/app/oracle/product/19.3/dbhome_1)
      (PROGRAM = dg4odbc)
    )

    (SID_DESC =
      (SID_NAME = MYSQLDB)
      (ORACLE_HOME = /data/app/oracle/product/19.3/dbhome_1)
      (PROGRAM = dg4odbc)
    )
  )

配置tns文件

vi tnsnames.ora

新增:

YASDBODBC =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.7.134)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = YASDBODBC)
)
(HS = OK)
)
MYSQLDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.7.134)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = MYSQLDB)
)
(HS = OK)
)

配置odbc监听

cd /data/app/oracle/product/19.3/dbhome_1/hs/admin

mysql

添加文件:

touch initMYSQLDB.ora
vim initMYSQLDB.ora

HS_FDS_CONNECT_INFO = MYSQLDB
HS_FDS_TRACE_LEVEL = debug
HS_FDS_SHAREABLE_NAME = /usr/lib64/libodbc.so
HS_LANGUAGE = AMERICAN_AMERICA.US7ASCII
HS_NLS_NCHAR = UCS2
#HS_FDS_SUPPORT_STATISTICS = FALSE

set ODBCINI= /etc/odbc.ini

yashandb

touch initYASDBODBC.ora
vim initYASDBODBC.ora

HS_FDS_CONNECT_INFO = YASDBODBC
HS_FDS_TRACE_LEVEL = debug
HS_FDS_SHAREABLE_NAME = /usr/lib64/libodbc.so
HS_LANGUAGE = AMERICAN_AMERICA.US7ASCII
HS_NLS_NCHAR = UCS2
#HS_FDS_SUPPORT_STATISTICS = FALSE

set ODBCINI= /etc/odbc.ini

重启监听

lsnrctl stop
lsnrctl start
lsnrctl status

创建链接异构数据库连接

在yashandb和mysql上建表如下:

drop table T1;
create table T1(c1 varchar(2001) ,c2 int,c3 double);
insert into T1 values('book1',51,1),('book2',22,2),('book3',66,3),(NULL,71,4),('book4',NULL,5);

mysql

drop database link TEST_MYSQL;
create database link TEST_MYSQL connect to "zabbix" IDENTIFIED by "123456" using 'MYSQLDB' ;

SELECT * FROM T1@TEST_MYSQL;

SELECT * FROM T1@TEST_MYSQL where "c3"=1 ;
SELECT * FROM T1@TEST_MYSQL where "c2"=51 ;
SELECT * FROM T1@TEST_MYSQL where cast("c1" as varchar(200))='book1';

yashandb

drop database link YASDBODBC_TEST;
create database link YASDBODBC_TEST connect to "sys" identified by "yasdb_123" using 'YASDBODBC';

SELECT * FROM T1@YASDBODBC_TEST;

SELECT * FROM T1@YASDBODBC_TEST where c1='book1';
SELECT * FROM T1@YASDBODBC_TEST where c2=51 ;
SELECT * FROM T1@YASDBODBC_TEST where c3=1 ;

问题原因

dblink使用odbc连接其它数据库,如yashandb、mysql等

● 把其它数据库的varchar类型会变成oralce中的nvarchar2类型,如下组图1。

● nvarchar2类型2个字节存储一个字符,超过varchar(2000)的字段类型因为超过了4000个字节,在oracle中变成了long类型,如下组图2。

● long类型不能在where、group by、order by中使用。

问题复现

组图1

mysql中的表类型:

oracle中的表类型:

查询正常:

组图2

mysql中的表类型:

oracle中的表类型:

查询报错:

oracle long类型限制

  • LONG数据类型中存储的是可变长字符串,最大长度限制是2GB。

  • 对于超出一定长度的文本,基本只能用LONG类型来存储,数据字典中很多对象的定义就是用LONG来存储的。

  • LONG类型主要用于不需要作字符串搜索的长串数据,如果要进行字符搜索就要用varchar2类型。

  • 很多工具,包括SQLPlus,处理LONG 数据类型都是很困难的。

  • LONG数据类型的使用中,要受限于磁盘的大小。

能够操作LONG的SQL语句:

  • Select语句

  • Update语句中的SET语句

  • Insert语句中的VALUES语句

限制:

  • 一个表中只能包含一个 LONG 类型的列。

  • 不能索引LONG类型列。

  • 不能将含有LONG类型列的表作聚簇。

  • 不能在SQLPlus中将LONG类型列的数值插入到另一个表格中,如insert into …select。

  • 不能在SQL*Plus中通过查询其他表的方式来创建LONG类型列,如create table as select。

  • 不能对LONG类型列加约束条件(NULL、NOT NULL、DEFAULT除外),如:关键字列(PRIMARY KEY)不能是 LONG 数据类型。

  • LONG类型列不能用在Select的以下子句中:where、group by、order by,以及带有distinct的select语句中。

  • LONG类型列不能用于分布查询。

  • PL/SQL过程块的变量不能定义为LONG类型。

  • LONG类型列不能被SQL函数所改变,如:substr、instr。 因为long类型的数值不能用insert into … select的方法插入,故我们要分两步走,先插入其它字段,最后再插入long类型字段,这可以通过过程来实现.

参考:oracle里long类型的总结_oracle long-CSDN博客

char类型区别

char

1、char的长度是固定的。比如说,你定义了char(20),即使你你插入abc,不足二十个字节,数据库也会在abc后面自动加上17个空格,以补足二十个字节;

2、char是区分中英文的。中文在char中占两个字节,而英文占一个,所以char(20)你只能存20个字母或10个汉字。

char适用于长度比较固定的,一般不含中文的情况。

varchar/varchar2

1、varchar是长度不固定的。比如说,你定义了varchar(20),当你插入abc,则在数据库中只占3个字节。

2、varchar同样区分中英文。这点同char。

3、varchar2基本上等同于varchar。它是oracle自己定义的一个非工业标准varchar,不同在于,varchar2用null代替varchar的空字符串。

varchar/varchar2适用于长度不固定的,一般不含中文的情况。

nvarchar/nvarchar2

1、nvarchar和nvarchar2是长度不固定的;

2、nvarchar不区分中英文。比如说:你定义了nvarchar(20),你可以存入20个英文字母/汉字或中英文组合,这个20定义的是字符数而不是字节数;

3、nvarchar2基本上等同于nvarchar,不同在于nvarchar2中存的英文字母也占两个字节。

大多数情况下,ORACLE中的国家字符集是默认的,以下结论成立:

如果要省存储空间,建表时,字段内容里如果中文占了大多数,就用nvarchar2类型;如果内容是英文和数字为主的字符串,就用varchar2类型。

注意:

  • ORACLE中的国家字符集,只有在数据类型为NCHAR/NVARCHAR/NCLOB时才会被使用,也就是前面带N(national)的字符类型;

  • ORACLE默认国家字符集为AL16UTF16,完全对应UNICODE的UTF-16标准(有别于数据库字符集)

  • ORACLE中的UTF-8,不是标准的UTF-8,而是CESU-8。

参考:Oracle字段类型char、varchar2、nvarchar2的区别与使用_oracle varchar2-CSDN博客

规避方法

varchar最大支持长度为4000字节,通过参数MAX_STRING_SIZE控制 MAX_STRING_SIZE默认为STANDARD,修改成EXTENDED支持32K

修改步骤:

sql> shutdown immediate;
sql> startup upgrade;
sql> alter system set max_string_size=EXTENDED scope=both;
sql> @?/rdbms/admin/utl32k.sql
sql> startup;
sql> @?/rdbms/admin/utlrp.sql
相关文章
|
Oracle 关系型数据库 MySQL
【YashanDB知识库】kettle从DM8的number类型同步到YashanDB的varchar类型,存入是科学计数法形式的数据
【YashanDB知识库】kettle从DM8的number类型同步到YashanDB的varchar类型,存入是科学计数法形式的数据
|
数据库
【YashanDB知识库】含有NUL字节的varchar字符串查询时出现截断
【YashanDB知识库】含有NUL字节的varchar字符串查询时出现截断
|
Oracle 关系型数据库 数据库
数据库数据恢复—服务器异常断电导致Oracle数据库报错的数据恢复案例
Oracle数据库故障: 某公司一台服务器上部署Oracle数据库。服务器意外断电导致数据库报错,报错内容为“system01.dbf需要更多的恢复来保持一致性”。该Oracle数据库没有备份,仅有一些断断续续的归档日志。 Oracle数据库恢复流程: 1、检测数据库故障情况; 2、尝试挂起并修复数据库; 3、解析数据库文件; 4、导出并验证恢复的数据库文件。
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
**简介:** 某客户在使用触发器将表 A 的 varchar(4000 char) 列数据复制到表 B 时,出现数据乱码且不一致的问题。经分析,YashanDB 在处理触发器场景下的 varchar(4000 char) 列数据复制时存在机制错误,影响所有版本。建议将列长度修改为 varchar(2000 char) 或更小以规避问题。通过特定 SQL 可验证该问题是否存在。
|
SQL 存储 关系型数据库
【YashanDB知识库】共享从 MySQL异常处理CONTINUE HANDLER的改写方法
【YashanDB知识库】共享从 MySQL异常处理CONTINUE HANDLER的改写方法
|
SQL 测试技术 数据库
【YashanDB知识库】IMP跨网络导入慢问题
问题现象:290M数据,本地导入2分钟,跨机导入耗时显著增加(最高30分钟)。 原因分析:`imp`逐条SQL通过网络传输至yashanDB执行,交互频繁导致性能下降。 影响版本:客户测试环境22.2.8.3。 解决方法:将导入文件上传至与yashanDB同机后使用`imp`,减少网络延迟。 经验总结:优化`imp`工具,支持直接上传文件至服务器端执行,降低网络依赖。
|
监控 数据库
【YashanDB 知识库】ycm 托管数据库时报错 OM host ip:127.0.0.1 is not support join to YCM
在托管数据库时,若 OM 的 IP 被设置为 127.0.0.1,将导致无法托管至 YCM,并使数据库失去监控。此问题源于安装时修改了 OM 的监听 IP。解决方法包括:将 OM 的 IP 修改为本机实际 IP 或 0.0.0.0,同时更新 env 文件及 yasom 后台数据库中的相关配置。经验总结指出,应避免非必要的后台 IP 修改,且数据库安装需遵循规范,不使用仅限本机访问的 IP(如 127.0.0.1)。
|
监控 网络安全 数据库
YashanDB 知识库:ycm 纳管主机安装 YCM-AGENT 时报错 “任务提交失败,无法连接主机”
在安装 ycm-agent 纳管主机时,可能出现因端口未开放导致的报错问题。此问题会阻止 YCM 对主机和数据库的监控功能,影响版本为 `yashandb-cloud-manager-23.2.1.100-linux-aarch64.tar`。原因是目标主机(如 10.149.223.121)未开放 9070 或 9071 端口。解决方法包括关闭防火墙、添加白名单或开放指定端口,需与管理员确认操作。处理过程涉及网络检查、端口测试等步骤。端口问题解决后,若再次安装报唯一键错误,需先移除失败主机再重试。
|
监控 Java Shell
【YashanDB 知识库】ycm 托管数据库时,数据库非 OM 安装无法托管
本文主要介绍了因数据库未按规范使用 yasboot 安装导致的问题及解决方法。问题表现为无 yasom 和 yasagent 进程,且目录结构缺失,致使 ycm 无法托管与监控。分析发现可能是数据库版本旧或安装不规范引起。解决方法为先生成配置文件,安装 yasom 和 yasagent,再生成并修改托管配置模板,最终通过命令完成托管至 yasom 和 ycm。总结强调了按规范安装数据库的重要性以避免类似问题。

推荐镜像

更多