C++:MFC通过ODBC操作Orcale数据库的说明

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dashumak/article/details/83795684

本文通过ODBC方式连接Oracle数据库,使用MFC进行数据库操作的关键函数。详细介绍了配置ODBC的方法和其中遇到的各项困难,以及最终几个的关键函数。

1. ODBC数据源连接数据库方式

1.1 使用odbc数据源的好处

  • 客户端无需知道数据库所在的IP地址。只要在数据库中配置好监听,客户端配置好文件tnsnames.ora。客户端电脑中的程序即可通过数据源直接访问Orcale数据库口程序的开发人员只需调用ODBC相关的函数即可实现通信。
  • 在系统中直接配置监听TNS、用户名UID、密码PSW,可以避免数据库密码等信息维护,客户端电脑上接口程序的修改,程序开发人员也不需要知道密码。
  • 一个数据库可以配置多个ns。

1.2 客户端安装orcale的驱动

为了方便,我们将Oracle数据库所在电脑称作服务器,将配置ODBC的电脑称作客户端。需要注意的是只有客户端需要在windows系统中配置odbc数据源,服务器只需要在Oracle数据库内部配置好监听即可,不需要配置odbc数据源。现在假设Oracle数据库服务器配置的服务命名orcl,如下图所示。
在这里插入图片描述
​​首先要明确Oracle_ODBC驱动有32位和64位之分。理论上讲,客户端电脑安装的的驱动一定要和服务器安装的Orcale数据库的位数一致。如果不一致会出现 “在指定的DSN中,驱动程序和应用程序之间的体系结构不匹配” 的问题。
Microsoft 会默认自带一个 32位Oracle ODBC的ODBC驱动文件,但是我们在这个驱动文件上创建数据源的话会报错 一般会提示 “未发现Oracle™客户端和网络组件。”的错误。我们需要这样的情况下我们要重新下载安装手动配置32位ODBC数据驱动。

  • (1) 首先把我提供的instantclient_12_1 文件放在 C:\ProgramFiles 目录下。

  • (2) 用记事本打开“C:\ProgramFiles\instantclient_12_1\network\ADMIN\tnsnames.ora”文件将主机名"HOST"填写你要连接的IP地址(这条是针对客户端的电脑,服务器侧的电脑不用动),其它不用动。
    在这里插入图片描述

  • (3) 添加环境变量(右键单击我的电脑—属性—高级选项卡—环境变量)TNS_ADMIN,变量值指向ADMIN目录,我的配置是c:\Program Files\instantclient_12_1\NETWORK\ADMIN;新建的变量名填写TNS_ADMIN 变量值填写c:\Program Files\instantclient_12_1\NETWORK\ADMIN
    在这里插入图片描述

  • (4) 双击instantclient_12_1目录下的odbc_install.exe完成安装。注:安装时出现DOC框,并一闪而过,你可能无法判断是不是正确安装。其实你可以cmd进入instantclient_12_1目录,并.\odbc_install.exe手动安装。

  • 32位Oracle ODBC驱动安装包及安装教程地址:https://download.csdn.net/download/dashumak/10421614 (压缩包中是xp下的安装方法,win7下的安装方法见 本文)

  • 64位Oracle ODBC驱动安装包地址(安装方式很简单,找到odbc_install.exe右键管理员方式运行即可):https://download.csdn.net/download/dashumak/10421608

  • 这两个都是在没有安装过Oracle的电脑上安装的驱动,如果安装过Oracle的电脑是有相应的驱动的,但是也要检查一下驱动的版本(好像32位的Oracle装的是32位的驱动,64位的甲骨文装的是64位的驱动)。

1.3 Win7电脑配置ODBC数据源管理器

通过“运行”进入32位或者64位ODBC数据源管理器的方法是如下(这里文件夹名和软件的位数拧着呢,不知为什么):

  • 64位: C:\windows\system32\odbcad32.exe
  • 32位: C:\Windows\SysWOW64\odbcad32.exe
    客户端需要配置ODBC数据源,配置界面如下图所示。
    在这里插入图片描述
    各项参数说明如下(这里的代码是后续提到的CDatabase::OpenEx中的参数):
  • Data Source Name(即是代码中用到的DSN),取值是客户端自行设定。
  • Description只是一个描述,取值无所谓,可不做任何配置
  • ODBC中的User ID(即是代码中的UID),取值是由Oracle数据库配置,本次配置是sms。
  • TNS Service Name要(即是代码中的DBQ),是由客户端所在电脑tnsnames.ora配置文件中确定的,通过查询下图所示的文件,我们可以发现ORCLA和ORCLCYJ均与数据库的orcl绑定,因此客户端配置ODBC数据源中的TNS Service Name位ORCLA和ORCLCYJ均可。tnsnames.ora文件一般在orcale驱动的位置,如E:\app\dgax\product\11.2.0\client_1\network\admin。
    在这里插入图片描述

然后点击测试,输入数据库配置好的对应UID的密码,出现下图表明连接成功
在这里插入图片描述

1.4 Xp电脑配置ODBC数据库源管理器

配置方法:开始菜单>>ODBC,截图如下
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.4 解决MySQl(或者ODBC测试时)出现”no lisnter“问题

首先在运行中输入services.msc进入服务,启动OracleOraDb11g_home1TNSListener服务(右键属性选择自动方式,这样每次重启后会自动打开,但是因为防火墙这个服务不是每次都能自动打开)。
在这里插入图片描述
启动完后,刷新一下,可能出现服务启动后又自动关闭的问题,这是由于数据库配置监听文件的问题,需要修改”listener.ora“文件。比如我的lisnter.ora文件所在路径是“C:\Oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN”,不用管那些bak文件。
在这里插入图片描述

右键记事本打开(最好先备份一下),检查这个问题是不是有问题,往往是HOST不对,HOST应该与计算机的名称一致,修改后保存,重新到services.msc中启动“OracleOraDb11g_home1TNSListener”服务,这样应该就可以启动了。至于”listener.ora“文档中记录的各种文件地址,对一般监听影响不大,倘若修改完之后上述服务扔是启动之后仍是立刻自动关闭,就应该回到这个文档中,讲文件地址检查一遍,修改为正确的地址。
在这里插入图片描述
在这里插入图片描述
这样问题就解决了,可以到cmd中输入lsnrctl命令
在这里插入图片描述
输入status,查看数据库监听状态,出现下图表示监听成功
在这里插入图片描述


2. MFC借助ODBC操作数据库

2.1 利用CDatabase::OpenEx打开数据库连接

CDatabase db_Smartfuel;
BOOL bOpenDbSucc=FALSE;
try{
	db_Smartfuel.OpenEx(_T("DSN=orcl;UID=sms;PWD=123321;DBQ=ORCLCYJ ;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;"),CDatabase::noOdbcDialog);
	}
catch(CDBException*e){
		AfxMessageBox(e->m_strError);//弹窗显示错误信息
		e->delete();
	}

CDatabase::OpenEx()msdn官方说明,这里我简要介绍一下参数。

  • 第一个参数是一个含有连接关系的字符串,要参照ODBC配置填入相关参数,
    • (1)DSN和Data Source Name取值一致
    • (2)User ID要和代码中的UID保持一致
    • (3)TNS Service Name要和代码中的DBQ取值对应一致,
  • 第二个参数 CDatabase::noOdbcDialog表示无弹窗提示

2.2 利用CRecordset::m_strFilter进行数据筛选

CRecordset类有两个公共数据成员m_strFilter和m_strSort用来设置对记录的过滤和排序。在调用Open或Requery前,如果在这两个数据成员中指定了过滤或排序,那么Open和Requery将按这两个数据成员指定的过滤和排序来查询数据源。
成员m_strFilter用于指定过滤器.m_strFilter实际上包含了SQL的WHERE子句的内容,但它不含WHERE关键字.使用m_strFilter的一个例子为:

BOOL CSMST_BSAMPLE::SearchRecord(CString value1,CString value2){
//搜索stopflag=value1,newflag=value2。结果为空时,BOOL CSMST_BSAMPLE::SearchRecord返回结果为0
	m_strFilter = L"stopflag= '" + value1 + L"' and newflag = '" + value2 +L"'";
	Requery();
	m_strFilter=L"";
	return !IsEOF();
}

成员m_strSort用于指定排序.m_strSort实际上包含了ORDERBY子句的内容,但它不含ORDER BY关键字.m_strSort的一个例子为

m_pSet->m_strSort=“CourseIDDESC”; //按CourseID的降序排列记录
m_pSet->Open();

事实上,Open函数在构造SELECT语句时,会把m_strFilter和m_strSort的内容放入SELECT语句的WHERE和ORDERBY子句中.如果在Open的lpszSQL参数中已包括了WHERE和ORDERBY子句,那么m_strFilter和m_strSort必需为空。
调用无参数成员函数Close可以关闭记录集.在调用了Close函数后,程序可以再次调用Open建立新的记录集.CRecordset的析构函数会调用Close函数,所以当删除CRecordset对象时记录集也随之关闭。

猜你喜欢

转载自blog.csdn.net/dashumak/article/details/83795684