荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: zzt (我命由我不由天), 信区: Program
标  题: Visual C++中的ODBC编程实例
发信站: BBS 荔园晨风站 (Tue Jun  1 17:21:04 1999), 转信


发信人: Fire (无极), 信区: Programme
标  题: Visual C++中的ODBC编程实例
发信站: 网日情怀 (Wed Sep  9 09:38:59 1998) , 站内信件

               Visual C++中的ODBC编程实例

    ODBC是一种使用SQL的程序设计接口,使用ODBC使数据库应用程序
的编写者避免了与数据源相连接的复杂性。这项技术目前已经得到了
大多数DBMS厂商的广泛支持。
    Microsoft Developer Studio为大多数标准的数据库格式提供了
32位ODBC驱动器。这些标准数据格式包括有:SQL Server、Access、P
aradox、dBase、FoxPro、Excel、Or acle以及Microsoft Text。如
果用户希望使用其他数据格式,则需要安装相应的ODBC驱动器及DBMS

    用户使用自己的DBMS数据库管理功能生成新的数据库模式后,就
可以使用ODBC来登录数据源。对用户的应用程序来说,只要安装有驱
动程序,就能注册很多不同的数据库。登录数据库的具体操作参见有
关ODBC的联机帮助。
    MFC提供的ODBC数据库类
    Visual C++的MFC基类库定义了几个数据库类。在利用ODBC编程
时,经常要使用到  CDatabase(数据库类)、CRecordSet(记录集类)和
CRecordView(可视记录集类)。
    CDatabase类对象提供了对数据源的连接,通过它可以对数据源进
行操作。
    CRecordSet类对象提供了从数据源中提取出的记录集。CRecordS
et对象通常用于两种形式:动态行集(dynasets)和快照集(snapshots)
。动态行集能与其他用户所做的更改保持同步,快照集则是数据的一
个静态视图。每种形式在记录集被打开时都提供一组记录,所不同的
是,当在一个动态行集里滚动到一条记录时,由其他用户或应用程序中
的其他记录集对该记录所做的更改会相应地显示出来。
    CRecordView类对象能以控件的形式显示数据库记录,这个视图是
直接连到一个CRec ordSet对象的表视图。
    应用ODBC编程
    应用Visual C++的AppWizard可以自动生成一个ODBC应用程序框
架,步骤是:打开Fil e菜单的New选项,选取Projects,填入工程名,选
择MFC AppWizard (exe),然后按AppWiza rd的提示进行操作。
    当AppWizard询问是否包含数据库支持时,如果想读写数据库,那
么选定Database vi ew with file support;如果想访问数据库的信
息而不想回写所做的改变,那么选定Data base view without file s
upport。
    选择了数据库支持之后,Database Source 按钮会被激活,选中它
去调用Data Optio ns对话框。在Database Options对话框中会显示
出已向ODBC注册的数据库资源,选定所要操作的数据库,如:Super_ES,
单击OK后出现Select Database Tables对话框,其中列举了选中的数
据库包含的全部表;选择要操作的表后,单击OK。在选定了数据库和数
据表之后,就可以按照惯例继续进行AppWizard操作。
    特别需要指出的是:在生成的应用程序框架View类(如:CSuper_ES
View)中,包含一个指向CSuper_ESSet对象的指针m_pSet,该指针由App
Wizard建立,目的是在视表单和记录集之间建立联系,使得记录集中的
查询结果能够很容易地在视表单上显示出来。
    要使程序与数据源建立联系,需用CDatebase::OpenEx()或CDatab
ase::Open()函数来进行初始化。数据库对象必须在使用它构造记录
集对象之前初始化。
    下面举例说明在Visual C++环境中ODBC的编程应用。
    1.查询记录
    查询记录使用CRecordSet::Open()和CRecordSet::Requery()成
员函数。在使用CRe cordSet类对象之前,必须使用CRecordSet::Open
()函数来获得有效的记录集。一旦已经使用过CRecordSet::Open()函
数,再次查询时就可以应用CRecordSet::Requery()函数。
    在调用CRecordSet::Open()函数时,如果将一个已经打开的CData
base对象指针传给CRecordSet类对象的m_pDatabase成员变量,则使用
该数据库对象建立ODBC连接;否则如果m_pDatabase为空指针,就新建
一个CDatabase类对象,并使其与缺省的数据源相连,然后进行CRecord
Set类对象的初始化。缺省数据源由GetDefaultConnect()函数获得。
也可以提供所需要的SQL语句,并以它来调用CRecordSet::Open()函数
,例如:Super_ESSet.Open(A FX_DATABASE_USE_DEFAULT,strSQL);
    如果没有指定参数,程序则使用缺省的SQL语句,即对在GetDefaul
tSQL()函数中指定的SQL语句进行操作:
    CString CSuper_ESSet::GetDefaultSQL()
    {return _T("[BsicData],[MinSize]");}
    对于GetDefaultSQL()函数返回的表名,对应的缺省操作是SELECT
语句,即:
    SELECT * FROM BasicData,MainSize
    在查询过程中,也可以利用CRecordSet的成员变量m_strFilter和
m_strSort来执行条件查询和结果排序。m_strFilter为过滤字符串,
存放着SQL语句中WHERE后的条件串;m_s trSort为排序字符串,存放着
SQL语句中ORDER BY后的字符串。如:
    Super_ESSet.m_strFilter="TYPE=‘电动机’";
    Super_ESSet.m_strSort="VOLTAGE";
    Super_ESSet.Requery();
    对应的SQL语句为:
    SELECT * FROM BasicData,MainSize
    WHERE TYPE=‘电动机’
    ORDER BY VOLTAGE
    除了直接赋值给m_strFilter以外,还可以使用参数化。利用参数
化可以更直观、更方便地完成条件查询任务。使用参数化的步骤如下
:
    S声明参变量:
    CString p1;
    float p2;
    S在构造函数中初始化参变量:
    p1=_T("");
    p2=0.0f;
    m_nParams=2;
    S将参变量与对应列绑定:
    pFX->SetFieldType(CFieldExchange::param)
    RFX_Text(pFX,_T("P1"),p1);
    RFX_Single(pFX,_T("P2"),p2);
    完成以上步骤后就可以利用参变量进行条件查询:
    m_pSet->m_strFilter="TYPE=? AND VOLTAGE=?";m_pSet->p1="
电动机";
    m_pSet->p2=60.0;
    m_pSet->Requery();
    参变量的值按绑定的顺序替换查询字串中的"?"适配符。
    如果查询的结果是多条记录,可以用CRecordSet类的函数Move()
、MoveNext()、Mov ePrev()、MoveFirst()和MoveLast()来移动光标

    2.增加记录
    增加记录使用AddNew()函数,要求数据库必须是以允许增加的方
式打开:
    m_pSet->AddNew(); //在表的末尾增加新记录
    m_pSet->SetFieldNull(&(m_pSet->m_type), FALSE);
    m_pSet->m_type="电动机";
    ……
     //输入新的字段值
    m_pSet->Update();
     //将新记录存入数据库
    m_pSet->Requery();
    //重建记录集
    3.删除记录
    可以直接使用Delete()函数来删除记录,并且在调用Delete()函
数之后不需调用Upd ate()函数:
    m_pSet->Delete();
    if (!m_pSet->IsEOF())
    m_pSet->MoveNext();
    else
    m_pSet->MoveLast();
    4.修改记录
    修改记录使用Edit()函数:
    m_pSet->Edit();
    //修改当前记录
    m_pSet->m_type="发电机";
     //修改当前记录字段值
    ……
    m_pSet->Update();   //将修改结果存入数据库
    m_pSet->Requery();
    5.撤消操作
    如果用户选择了增加或者修改记录后希望放弃当前操作,可以在
调用Update()函数之前调用:
    CRecordSet::Move(AFX_MOVE_REFRESH);来撤消增加或修改模式,
并恢复在增加或修改模式之前的当前记录。其中,参数AFX_MOVE_REFR
ESH的值为零。
    6.数据库连接的复用
    在CRecordSet类中定义了一个成员变量m_pDatabase:
    CDatabase* m_pDatabase;
    它是指向对象数据库类的指针。如果在CRecordSet类对象调用Op
en()函数之前,将一个已经打开的CDatabase类对象指针传给m_pDatab
ase,就能共享相同的CDatabase类对象。如:
    CDatabase m_db;
    CRecordSet m_set1,m_set2;
    m_db.Open(_T("Super_ES"));  //建立ODBC连接
    m_set1.m_pDatabase=&m_db;
    //m_set1复用m_db对象
    m_set2.m_pDatabse=&m_db;
    // m_set2复用m_db对象
    7.SQL语句的直接执行
    虽然我们可以通过CRecordSet类完成大多数的查询操作,而且在C
RecordSet::Open( )函数中也可以提供SQL语句,但是有时候我们还是
希望进行一些其他操作,例如建立新表、删除表、建立新的字段等,这
时就需要使用CDatabase类直接执行SQL语句的机制。通过调用CDatab
ase::ExecuteSQL()函数来完成SQL语句的直接执行:
    BOOL CDB::ExecuteSQLAndReportFailure(const CString& strS
QL)
    {
    TRY
    {
    m_pdb->ExecuteSQL(strSQL);
    //直接执行SQL语句
    }
    CATCH (CDBException,e)
    {
    CString strMsg;
    strMsg.LoadString(IDS_EXECUTE_SQL_FAILED);
    strMsg+=strSQL;
    return FALSE;
    }
    END_CATCH
    return TRUE;
    }
    应当指出的是,由于不同的DBMS提供的数据操作语句不尽相同,直
接执行SQL语句可能会破坏软件的DBMS无关性,因此在应用中应当慎用
此类操作。
    8.动态连接表
    表的动态连接可以利用在调用CRecordSet::Open()函数时指定SQ
L语句来实现。同一个记录集对象只能访问具有相同结构的表,否则查
询结果将无法与变量相对应。
    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;
    }
    }
    9.动态连接数据库
    可以通过赋与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")))
     //连接数据源Super_ES
     {
    AfxMessageBox("数据源Super_ES打开失败,""请检查相应的ODBC
连接", MB_OK|MB_ ICONWARNING);
     exit(0);
     }
    m_id=1;
    break;
    case 1:
    if (!pdb->Open(_T("Motor")))
     //连接数据源Motor
    {
    AfxMessageBox("数据源Motor打开失败,""请检查相应的ODBC连
接", MB_OK|MB_ICO NWARNING);
    exit(0);
    }
    m_id=0;
    break;
    }
    }
    总结
    Visual C++中的ODBC类库可以帮助程序员完成绝大多数的数据库
操作。利用ODBC技术使得程序员从具体的DBMS中解脱出来,从而可以
减少软件开发的工作量,缩短开发周期,并提高效率和软件的可靠性。

--
-----------------------------------
        大道1m无极7;40m0m?
                 苦海无涯
----------------------------------

m;35m※ 来源: 网日情怀 bbs.mm.gnet.gd.cn [FROM: 202.103.176.4]m
--
m;33m※ 转寄:.网日情怀 bbs.maoming.gd.cn.[FROM: bbs.hz.gnet.gd.c]m


--



日出东方,唯我不败;
    天上地下,唯我独尊。

※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.143]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店