最近看到一篇oracle连接mysql的文章,自己很好奇也尝试了一下,遇到一些问题并解决掉,在这里记录一下。我的环境:OS:windows server 2003、oracle10.2.0和MySql5在同一台主机上。
一、配置mysql
1、创建数据库和表
mysql>create database mysqltest;
mysql>use mysqltest
mysql>create table ttt(
mysql>tid INTEGER,
mysql>tname VARCHAR(20));
mysql>insert into ttt values(1,'111');
mysql>select * from ttt;
2、配置odbc数据源
开始->管理工具->数据源(ODBC)->ODBC数据源管理器->系统DNS->添加->选择数据驱动程序:MySQL ODBC 5.1 Driver
(注意:如果没有安装过mysql的odbc驱动需要先下载odbc驱动安装,本人是在http://download.csdn.net/source/2463889下载的。)
选择驱动程序以后点击“完成”,然后配置odbc数据源信息:
配置好以后点击“Test”测试odbc连接mysql是否成功,如果成功才能进行下一步,点击“ok”完成配置。
注意:这里要在“系统DSN ”里添加配置,如果在“用户DSN”里配置会找不到odbc源,错误信息如下:
二、配置oracle
1、配置HS
在%ORACLE_HOME%/hs/admin/ 路径下添加initmysqltest.ora 里面有两条记录
#这里指定odbc的名称
HS_FDS_CONNECT_INFO = mysql
#指定追逐级别,一般设成OFF,为了方便调试这里设成debug,在%ORACLE_HOME%/hs/trace下查看追逐文件信息
HS_FDS_TRACE_LEVEL = debug
2、配置监听listener.ora
文件路径:%ORACLE_HOME%/NETWORK/ADMIN/
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = D:/oracle/product/10.2.0/db_1)
(PROGRAM = extproc)
)
(SID_DESC =
(PROGRAM =hsodbc) --这里必须是hsodbc,表明采用hsodbc异构连接
(ORACLE_HOME = D:/oracle/product/10.2.0/db_1)
(SID_NAME=mysqltest) --这里指定mysql数据库实例名称
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = cuihaiyang)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
)
)
配置完成重新启动监听。
3、配置tnsnames.ora
文件路径:%ORACLE_HOME%/NETWORK/ADMIN/ ,新增一条记录
MYSQLTEST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
)
(CONNECT_DATA =
(SID = mysqltest) --这里指定mysql数据库实例名称
)
(HS=OK)
)
4、创建数据库链路并测试
SQL> create database link mysql connect to "root" identified by "123" using 'mys
qltest';--注意使用单引号
数据库链接已创建。
SQL> select * from ttt@mysql;
tid
----------
1
SQL> select count(*) from ttt@mysql;
COUNT(*)
----------
49
可见已经可以从mysql中查询出数据。
PS:仔细观察结果发现存在两个问题
1、在mysql下创建表ttt有两个字段tid和tname现在却只查出了一个;
2、只有一条记录,但是count(*)查出来的是49。
SQL> delete from ttt@mysql;
1 row deleted
SQL> select count(*) from ttt@mysql;
COUNT(*)
--------------------
48
对于疑问1:查找了很多资料得出的结论是HSODBC的问题,查看HSODBC的跟踪文件发现存在一句“DB_ODBC_RECORD (1217): ; Skipped field tname, unrecognized datatype.”,说明HSODBC不能识别tname字段的类型,但是tname字段是varchar类型的,oracle中也支持varchar类型,很疑惑为什么不能识别。继续查找发现了一篇帖子:http://forums.oracle.com/forums/thread.jspa?threadID=2172072,楼主也遇到了HS没有返回所有字段的情况,仔细看了跟帖发现是odbc从mysql读取数据后转换成了odbc的数据类型,其中varchar被转换成了SQL_WVARCHAR,而hsodbc不能识别SQL_WVARCHAR,所以才造成了在oracle中不能返回所有字段的情况,HSODBC从2008年开始已经不再支持了,oracle11g中也使用DG4ODBC代替HSODBC,看来要解决这个问题还是需要使用DG4ODBC,干脆换成11g得了。
对于疑问2:在HSODBC的跟踪文件发现“hoastmt.c (304): ; Array fetch size is: 1.”,说明返回的结果是1条,在odbc的isql工具中执行“SELECT COUNT(*) FROM mysqltest.ttt” 返回结果也是1,后来尝试在oracle中执行select count("id") 结果正常了,分析半天日志也没找出什么原因,不过现在能得到正确的记录数量了,暂且到此。
关于oracle HS的深入解析可以参考:http://www.cnblogs.com/wwwiori/archive/2009/06/22/1508068.html