VC数据库访问技术之ODBC

博客转移:http://vivianke.blog.163.com/blog/static/297152712007811283766/

 

说明:
MFC 数据库访问方式有:ODBC,DAO,ADO

ODBC数据库编程:
1.创建数据源.
2.连接到数据源:

1)在Visual C++程序中使用刚才建立的数据源之前,还必须简历一个到数据源的连接.
在MFC中到数据源的连接封装在CDatabase类中,要使用CDatabase对象,在ODBC数据源管理器中数据源必须已经正确配置.
在同一个程序中可以使用多个数据源,或者多个连接对应同一个数据源.

连接函数:
virtual BOOL OpenEx(LPCTSTR lpszConnectionString,DWORD dwOptions=0);
    throw(CDBException,CMemoryException);

CDatabase m_db;

TRY{
    m_db.OpenEx("DSN=MySQL;UID=dbaccess;PWD=dbaccess",CDatabase::noOdbcDialog);
}
catch(CDBException ex)
{
    AfxMessageBox(ex->m_strError);
    AfxMessageBox(ex->m_strStateNativeOrigin);
}
AND_CATCH(CMemoryException *pEx)
{
    pEx->ReportError();
    AfxMessageBox("memory exception");
}
AND_CATCH(CMemoryException *pEx)
{
    pEx->ReprotError();
    AfxMessageBox("memory exception");
}
AND_CATCH(CException *e)
{
    TCHAR szError[100];
    e->GetErrorMessage(szError,100);
    AfxMessageBox(szError);
}
END_CATCH

连接一个已经配置好的数据源有一下方法:

CDatabase m_database;//声明对象
//测试库是否已经处于打开状态
if(!m_database.IsOpen())
{
    //Test 表示欲打开的数据源的名称
    if(!m_database.Open(_T("Test"))){
        Assert("不能打开到该数据源的连接!");
    }
    //......
    //关闭连接
    m_database.Close();
}

下面的代码段也可以打开一个数据源的连接,是更为完整的表述.
CDatabase *pDb=new CDatabase;
BOOL bStatus=FALSE;        //数据库是否成功打开标志
//设置连接超时属性为3秒钟
pDb->SetLoginTimeOut(3);
try
{
    bStatus=pDb->OpenEx("Text");
    if(bStatus)
        TRACE("\nDB Opened successfully.\n");
    else
        TRACE("\nOpen DSN failed.\n");
    }
catch(CMemoryException* pEx)//处理内存异常
{
    pEx->ReportError();
}
catch(CDBException*pDBEx)
{
    pDBEx->ReportError();
    TRACE("RetCode:%d strError:[%s] strState:[%s]\n",
            pDBEx->m_nRetCode,
            pDBEx->m_strError,
            pDBEx->m_strStateNativeOrigin);
}
pDB->Close();

2)创建结果集
在CRecordSet类中定义一个成员变量m_pDatabase,它是指向对象数据库类的指针.
用户可以通过一下方式将这个结果集对应到相应的数据源.
//m_database是上一小节已经声明过并连接到数据源的CDatabase对象.
CRecordset m_recordset1,m_recordset2;
m_recordset1.m_pDatabase=&m_database;    //m_recordset1复用m_database对象
m_recordset2.m_pDatabase=&m_database;    //m_recordset2复用m_database对象

3)添加和修改记录
增加记录可以使用AddNew()函数,要求数据库必须是以允许增加方式打开
m_recordset.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();            //重建记录集

4)查询记录
查询记录可以使用CRecordSet::Open()和CRecordSet::Requery()成员函数.
在使用CRecordSet类对象之前,必须使用CRecordSet::Open()函数来获得有效的记录集.
一旦已经使用过CRecordset::Open()函数,那么下一次查询时就可以使用CRecordSet::Requery()函数了.
在调用CRecordSet::Open()函数时,如果已经将一个打开的CDatabase对象指针传给CRecordset类对象的m_pDatabase成员变量,那么就可以使用该数据库对象建立ODBC连接;否则(即m_pDatabase为空指针),就需要新建一个CDatabase类对象并使其与缺省的数据源相连,然后进行CRecordset类对象的初始化.缺省数据源由GetDefaultConnect()函数获得.
下面是几种查询方法,用户可以选择使用:
1.通过SQL语句打开记录集
SQL语句中包含查询条件
LPCTSTR strSQL;//strSQL是包含查询条件的SQL语句
m_recordset1.Open(strSQL);//m_recordset1是结果集的一个对象
2.使用m_strFilter和m_strSort
查询过程中也可以使用CRecordset的成员变量m_strFilter和m_strSort来执行条件查询和结果排序.
其中,m_strFilter为过滤字符串,存放的是SQL语句中WHERE以后的条件,而m_strSort为排序字符串,存放的是SQL语句中ORDER BY之后的字符串.下面是一个简单的例子:
//EMPLORYEE_AGE是参数
_itoa(EMPLOYEE_AGE,ch,8);        //EMPLOYEE_AGE是待查询记录的EMP_AGE值
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 BY EMP_ID ASC;
3.参数查询
利用参数化可以更直观、更方便地完成条件查询任务.具体使用的方法如下:
(1)声明参变量
int EMPLOYEE_AGE;
CString strDept;
(2)在构造函数中初始化参变量
EMPLOYEE_AGE=24;
strDept=_T("Manufacture");        //Manufacture为员工所在部门
m_nParams=2;
(3)将列与参数进行绑定
pFX->setFieldType(CFieldExchage::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类的函数MoveFirset()和MoveNext()函数来取得结果集中相对应的记录.

总结:
以上方法各有优劣,一般请看下SQL查询是最简单的一种,可以直接通过SQL语句得到查询结果,一般的应用开发仅用此方法即可.

5)删除记录
用Delete()函数即可,并且在调用Delete()函数后不需要再调用Update()函数.
m_pSet->Delete();

6)撤销操作
如果用户选择了增加或修改记录后希望放弃当前的操作,可以在调用Update()函数之前调用CRecordSet::Move(AFX_MOVE_REFRESH)来撤销增加或修改模式,并恢复在增加或修改模式之前的当前记录.其中参数AFX_MOVE_REFRESH的值为0.

7)记录集的其他操作
比如,从结果集中取得各个域的值,可以先声明一个CDBVariant对象,然后通过CRecordSet::GetFieldValue()函数来取值到CDBVariant对象,在根据值的类型吧CDBVariant的相应成员变量赋给所需要的变量.
m_recordset.GetFieldValue(2,varValue);        //2是域的位置,varValue是CDBVariant对象
int i=varVariant.m_iVal;                    //如果这个域对应的类型是整数
而CRecordSet::GetRecordCount()函数可以返回还未访问过的结果集里的记录数,可以用来判断结果集是否为空.

8)SQL语句的直接执行
通过CRecordSet类可以完成大多数的查询操作,但有时需要对数据库建立新表、删除表和建立新的字段等,这就需要用到CDatabase类直接执行SQL语句的机制.这可以用过CDatabase::ExecuteSQL()函数来完成.
//下面是为自己创建的类CTry编写执行SQL的函数MyExecuteSQL
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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值