| VC下异构数据源数据共享的实现 |
| [ 作者:佚名 转贴自:网络转载 阅读次数:50 更新时间:2007-3-21 14:04:00 录入:刘光勇 ] 热 |
|
|
|
摘要:本文介绍了数据库异构的主要特性,讨论了异构数据源互联要解决的问题和基本方法,以及在VC++环境下,基于ODBC技术的多源异构数据库的访问共享方法。
关键词:异构数据库 ODBC SQL 1.引言
1.1异构数据库概述
异构数据库系统是相关的多个数据库系统的集合,可以实现数据的共享和透明访问。每个数据库系统在加入异构数据库系统之前就已经存在,拥有自己的DBMS,异构数据库的各个组成部分具有自身的自治性,在实现数据共享的同时,每个数据库系统仍保有自己的应用特性、完整性控制和安全性控制,异构数据库系统的异构性主要体现在以下几个方面:
(1)计算机体系结构的异构:各个参与数据库系统的可以分别运行在大型机、小型机、工作站、PC或嵌入式系统中。
(2)基础操作系统的异构:各个数据库系统的基础操作系统可以是UNIX、WINDOWSNT、DOS等。
(3)DBMS本本身的异构:可以是同为关系型数据库系统的Oracle、SQL Server等,也可以是不同数据类型的数据库,如关系、模式、层次、网络、面向对象、函数型数据库共同组成一个异构数据库系统。
在系统集成和进一步开发的过程中,常常面临的一个突出的问题就是:一个管理信息系统中往往存在两种以上不同的数据库环境。在复杂的环境中,如何实现不同数据库间数据信息资源合并和共享、如何保护已经建立的资源、充分利用各部门已经使用的数据库,实现不同数据库之间的连接、数据交换和数据共享,已经成为基于异构数据库的管理信息系统开发是否成功的关键。目前,我们的研究工作主要针对DBMS异构。
1.2异构数据库互联要解决的问题
由于数据库的多重性,导致数据库管理系统管理软件,系统硬件,以及支持异构数据库的费用给企业带来了巨大的负担。为了高效率的运行,需要在异构数据库和数据库管理软件之间进行资源共享。
异构型数据库互联可以对网络上各个不同的局部DBMS进行统一管理,实现不同数据库之间的数据信息资源合并和共享。尽管各个局部物理数据库在地理上存储在网络的各个不同结点或场地上,但逻辑上把它们视为一个逻辑库进行处理。这样,通过对异构型数据库DBMS的互联可以达到异构型数据库间的数据共享。
对于数据库异构集成主要侧重于异构分布式数据库集成研究。这种集成技术是将参与数据库的有关信息在逻辑上继承为一个属于异构分布式数据库的全局概念模式,以达到信息共享的目的。
2.异构数据库的转换方法
对于异构数据库系统,要实现数据共享应当达到两点,一是实现数据转换,二是实现数据的透明访问。在数据库转换过程中,原来旧的数据库系统不能废弃,而要转换到新系统中继续发挥作用,对资源再利用。
在不同数据库间将数据库中的数据转换到目的数据库中。为了实现在异构环境中的信息交流和共享,人们采用了诸多方法来实现异构环境的集成处理。其主要转换方式有以下三种:
(1).利用数据库厂商的专业工具目前很多数据库厂家都提供专门的数据转换工具。专用数据工具具有考虑充分,构造完备的特点 ,但造价高、使用面较窄。
(2).利用前台开发工具。通过对不同数据库采用不同接口(ODBC或专用接口)的形式同时支持多种数据库,实现前台开发工具和后台数据库间的连接。
(3).用动态sql语句。不同数据库间数据转换的实现方法各有利弊。动态sql语句方法灵活多变,适用面广,但实现复杂,需编制可视界面。对于较普遍的关系型数据库,数据量较小情况下,可以利用动态sql语句进行数据转换。
综上所述,充分利用前台开发工具(ODBC或专用接口)对有关数据进行处理是一种较好的选择。 3.利用ODBC技术实现多源以异构数据库的集成
ODBC是Microsoft公司提供的标准的应用程序接口。利用它可以实现一个应用程序访问不同的数据源。ODBC数据源驱动是实现ODBC驱动来访问一个特定的数据源。ODBC屏蔽了底层数据库系统的不同,数据开发者可以直接利用sql语句实现对不同数据库中数据的操纵。
3.1 ODBC技术概述
ODBC是为客户应用程序访问关系数据库时提供的一个标准接口,对不同的数据库, ODBC提供了一套统一的API,使得应用程序可以应用所提供的API,访问任何提供了ODBC驱动程序的数据库。它使用结构化查询语言(SQL)作为其数据库访问语言。ODBC通过使用数据库驱动程序(Driver)来提供数据库的独立性。驱动程序是用以支持ODBC函数调用的模块(通常是一个DLL),ODBC通过调用驱动程序所支持的函数来对数据库进行操作。
在Visual C++开发环境中,大部分的ODBC功能都被封装到两个类中,即Cdatabase类和CRecordset类,另外还有一个CRecordView类。Cdatabase类包含有数据库的连接信息,提供了对数据源的连接,可以在整个应用程序中共享这些信息。CRecordset类封装了一组数据库记录,通常用于两种形式:动态行集(dynasets)和快照集(snapshots)。CRecordset类允许指定要运行的SQL查询,它还将运行查询并维护自数据库返回的记录集,且所做的更改可反馈给数据库。CRecordView类能以控制的形式显示数据库记录。这个视图是直接连到一个CRecordset类对象的表视图。
3.2 实现多源异构数据库的访问技术的必要性
一般情况下,使用ODBC进行单一数据源的连接是比较方便的,本文主要讨论如何利用ODBC技术实现多源数据库的访问技术。
目前市场上流行的各种数据库管理系统(DBMS)相互之间存在着很大的不同。这些DBMS 采用不同的数据存储格式存取数据,采用不同的管理方法管理数据,并且拥有各自的用户群。尽管关系数据库(RDB)理论与结构化查询语言(SQL)的出现初步统一了各个RDBMS的基本操作,但是如何同时对存储在多个不同DBMS下的数据进行操作,如何以最小的代价集成原有DBMS上的数据等异构型数据库互联问题仍然是数据库技术研究的一个重要课题。
目前对异构型数据库互联有三种成熟的策略:公共编程界面、公共数据网关和公共协议。从各种数据库产品所提供的异种数据集成的机制来看,数据网关和公共编程界面是当今集成异种数据库的主要方法。但这种异种数据库的集成通常都是单向的、主从式的,一种产品一般只提供从自己的DBMS访问异种数据库的机制和产品。到目前为止,一直没有一种通用的数据库互联工具来简化人们的数据库互联工作。因此,我们希望通过研究,能提供一种通用的数据库互联工具,解决互联系统中的一些实际问题。
实现异构数据库的集成,首先要对加入的数据库资源实现完全透明的访问,既要保证全局数据的共享,又要保证各数据库管理系统的自治,确保基于异种系统平台实现对异构数据库的查询和联合使用,提供一个独立于特定的数据库管理系统的统一编程界面。
3.3 数据源的连接
在Visual C++程序中使用建立的数据源之前,必须建立一个到数据源的连接。在MFC中到数据源的连接封装于Cdatabase类中。在同一个程序中可以使用多个数据源,或者多个连接对应同一个数据源。
(1)连接一个已经配置好的数据源可用以下方法:
CDatabase m_database; If(!m_database.IsOpen()) { If(!m_database.IsOpen(_T(“Test”))) Assert(“不能打开该数据源”); } m_database.Close(); | 更为完整的代码表述如下:
CDatabase *pDb=new CDatabase; BOOL bStatus=FALSE; PDb->SetLoginTimeout(3); try { bStatus=pDB->OpenEx(“Test”); if(bStatus) TRACE(“\n DB opened successfully.\n”); Else TRACE(“\n Open DSN failed.\n”); } catch(CmemoryException *pEx) //处理内存异常 { pEx->ReportError(); } catch(CDBExpception *pDBEx) //处理数据库异常 { pDBEx->ReportError(); TRACE(“RetCode:%d strError[%s] strState:[%s]\n”, PDBEx->m_nRetCode, PDBEx->m_strError, PDBEx->m_strStateNativeOrigin); } pDB->Close(); | (2)动态连接数据库
由于与数据库的连接是通过Cdatabase类对象来实现的,所以可以通过赋予CrecordSet类对象参数m_pDatabase以连接不同数据库的Cdatabase对象指针,就可以动态地连接数据库,示例代码如下:
void CDB::ChangeConnect() { Cdatabase*pdb=m_pSet->m_pDatabase; Pdb->close(); Switch(m_id) { case 0: if(pdb->Open(_T(“Super_ES”))) { AfxMessageBox(“数据源Super_ES打开失败”,”请检查相应的ODBC连接’,MB_OK|MB_ICONWARNING); EXIT(0); } m_id=1; break; case 1: if(!pdb->Open(_T(“Motor”))) { AfxMessageBox(“数据源Motor打开失败”,”请检查相应的ODBC连接”,MB_OK|MB_ICONWANING); Exit(0); } m_id=0; break; } } | (3)动态连接表
表的动态连接可以利用在调用CrecordSet::Open()函数时指定SQL语句来实现。同一个记录集对象只能访问具有相同结构的表,否则查询结果将无法与变量相对应。解决的办法是在不同的情况下使用不同的SQL语句,示例代码如下:
void CDB::ChangeTable() { if(m_pSet->IsOpen()) m_pSet->Close(); switch(m_id) { case 0: m_pSet->Open(AFX_DB_USE_DEFAULT_TYPE,”SELECT * FROM SLOT0”);//连接表SLOT0 m_id=1; break; case 1: m_pSet->Open(AFX_DB_USE_DEFAULT_TYPE,”SELECT * FROM SLOT1”);//连接表SLOT1 m_id=0; break; } } | (4)对数据库的其他操作
添加记录可以使用AddNew()函数,要求数据库必须是以允许增加方式打开。
m_recordset1.addnew(); m_recordset1.Update(); m_recordset1.Requery(); / | 修改记录可以使用Edit()函数(m_pSet是指向结果集m_recordset2的指针)
m_pSet->Edit(); m_pSet->m_type=”完成”; …… m_pSet->Update(); m_pSet->Requery(); | 查询记录
查询记录可以使用CRecordSet::Open()和CRecordSet::Requery()成员函数。在使用CrecordSet类对象之前,必须使用CRecordSet::Open()函数来获得有效的记录集。一旦已经使用过CRecordSet::Open()函数,则下一次查询时就可以用CRecordSet::Requery()函数了。
在调用CRecordSet::Open()时,如果已经将一个已经打开的Cdatabase对象指针传给CrecordSet类对象的m_pDatabase成员变量,那么就可以使用该数据库对象建立ODBC连接;否则就需要新建一个CDatabase类对象并使其缺省的数据源相连,然后进行CrecordSet类对象的初始化。缺省数据源由GetDefaultConnect()函数获得。查询方法如下:
1)通过SQL语句打开记录集
SQL语句中包含查询条件
LPCTSTR strSQL; //strSQL是包含查询条件的SQL语句 m_recordset1.Open(strSQL)Requery(); | 2)使用m_strFilter和m_strSort
查询过程中也可以利用CrecordSet的成员变量m_strFilter和m_strSort来执行条件查询和结果排序:
EMPLOYEE_AGE是参数值
_itoa(EMPLOYEE_AGE,ch,8); //EMPLOYEE m_recordset1.m_strFilter=”EMP_AGE=”+Cstring(ch); m_recordset1.m_strSort=”EMP_ID ASC” m_recordset1.Requery(); | 对应的SQL语句为
SELECT * FROM PERSONNEL WHERE EMP_AGE= EMPLOYEE_AGE ORDER BU EMP_ID ASC; | 3)参数查询
利用参数查询可以更直观、更方便地完成条件查询任务。
声明参变量
int EMPLOYEE_AGE; Cstring strDept; | 在构造函数中初始化参变量
EMPLOYEE_AGE=24; StrDept=_T(“Manufacture”); //Manufacture为员工所在的部门。 m_nParams=2; | 将列与参数进行绑定
pFX->SetFeildType(CfieldExchange::param) RFX->Int(pFX,_T(“EMP_AGE”),EMPLOYEE_AGE); RFX_Text(pFX,_T(“DEPT_NAME”),strDept); | 完成以上步骤后就可以利用参变量进行条件查询了:
m_recordset1->m_strFilter=”EMP_AGE=?AND DEPT_NAME=?”; m_recordset1->EMP_AGE=24; m_recordset1->DEPT_NAME=”Manufacture”; m_recordset1->Requery(); | 参变量的值按绑定的顺序替换查询字串中的“?”适配符
如果查询结果是多条记录,可以用CrecordSet类的函数MoveFirst()和MoveNext()等函数来取得结果集中相对应的记录。
删除记录
应用Delete()函数,且在调用Delete() 函数后不需要再调用Update() 函数。
撤销操作
如果用户选择了增加或修改记录后希望放弃当前操作。可以在调用Update()函数之前调用CrecordSet::Move(AFX_MOVE_REFRESH)来撤销增加或修改模式,并恢复在增加或修改模式之前的当前记录。其中参数AFX_MOVE_REFRESH的值为0。
(5)SQL语句的直接执行
通过CrecordSet类可以完成大多数的查询操作,但有时需要对数据库建立新表、删除表和建立新的字段等,这就需要用到Cdatabase类直接执行SQL语句的机制。这可以通过Cdatabase::ExecuteSQL()函数来完成。
//下面是为自己创建的类Ctry编写执行SQL的函数MyExcuteSQL BOOL Ctry::MyExecuteSQL(const Cstring&strSQL) { TRY { m_database->ExecuteSQL(strSQL);//直接执行SQL语句 } CATCH(CDBException *e) { Cstring strMsg; StrMsg.LoadString(IDS_EXECUTE_SQL_FAILED); StrMsg+=strSQL; return FALSE; } END_CATCH return TRUE } | Visual C++中的ODBC类库可以帮助程序员完成绝大多数的数据库操作。利用ODBC技术可以使程序员从具体的DBMS中解脱出来,从而极大地减少了软件开发的工作量,提高了效率并增强了软件的可靠性
4 .结束语
随着信息技术的高速发展,实现异构数据库的数据共享,可以最大限度的减少不必要的开支,用VC++的ODBC技术,可以很好的解决DBMS本身异构的多源异构数据库的共享问题。
|
|
|