VCpp操作ODBC数据库

⌚Time: 2023-04-02 19:53:15

👨‍💻Author: Jack Ge

添加ODBC数据源

打开ODBC管理程序,添加数据源,使用Microsoft Access数据库为例子

可以选择或者创建一个数据库

设置数据源名字

创建好的数据源

程序

需要的头文件afxdb.h

使用CDatabase类和进行数据库的连接和操作


CDatabase::BeginTrans   在连接的数据源上启动一个“事务”,即一系列对 CRecordset 类的 AddNew、Edit、Delete 和 Update 成员函数的可逆调用。 数据源必须支持事务才能使 BeginTrans 生效。

CDatabase::BindParameters   允许在调用 CDatabase::ExecuteSQL 之前绑定参数。

CDatabase::Cancel   从第二个线程取消异步操作或进程。

CDatabase::CanTransact  如果数据库支持事务,则返回非零。

CDatabase::CanUpdate    如果 CDatabase 对象可更新(非只读),则返回非零。

CDatabase::Close    关闭数据源连接。

CDatabase::CommitTrans  完成由 BeginTrans 开始的事务。 执行更改数据源的事务中的命令。

CDatabase::ExecuteSQL   执行 SQL 语句。 不返回任何数据记录。

CDatabase::GetBookmarkPersistence   标识书签用于保存在记录集对象上的操作。

CDatabase::GetConnect   返回用于将 CDatabase 对象连接到数据源的 ODBC 连接字符串。

CDatabase::GetCursorCommitBehavior  标识提交事务对打开的记录集对象的影响。

CDatabase::GetCursorRollbackBehavior    标识回退事务对打开的记录集对象的影响。

CDatabase::GetDatabaseName  返回当前正在使用的数据库的名称。

CDatabase::IsOpen   如果 CDatabase 对象当前连接到数据源,则返回非零。

CDatabase::OnSetOptions 由框架调用以设置标准连接选项。 默认实现设置查询超时值。 可通过调用 SetQueryTimeout 来提前建立这些选项。

CDatabase::Open 建立与数据源的连接(通过 ODBC 驱动程序)。

CDatabase::OpenEx   建立与数据源的连接(通过 ODBC 驱动程序)。

CDatabase::Rollback 撤销当前事务期间所做的更改。 数据源返回到之前的状态,就像 BeginTrans 调用时定义的那样,没有改变。

CDatabase::SetLoginTimeout  设置数据源连接尝试超时后的秒数。

CDatabase::SetQueryTimeout  设置数据库查询操作超时后的秒数。影响所有后续记录集 Open、AddNew、Edit 和 Delete 调用。

CRecordset类进行数据查询


CRecordset::AddNew  准备添加新记录。 调用 Update 以完成添加。

CRecordset::CanAppend   如果可以通过 AddNew 成员函数将新记录添加到记录集中,则返回非零值。

CRecordset::CanBookmark 如果记录集支持书签,则返回非零值。

CRecordset::Cancel  从第二个线程取消异步操作或进程。

CRecordset::CancelUpdate    由于 AddNew 或 Edit 操作,取消任何挂起的更新。

CRecordset::CanRestart  如果可以调用 Requery 以再次运行记录集的查询,则返回非零值。

CRecordset::CanScroll   如果可以滚动浏览记录,则返回非零值。

CRecordset::CanTransact 如果数据库支持事务,则返回非零值。

CRecordset::CanUpdate   如果可以更新记录集(可以添加、更新或删除记录),则返回非零值。

CRecordset::CheckRowsetError    调用以处理记录提取期间生成的错误。

CRecordset::Close   关闭记录集及其关联的 ODBC HSTMT。

CRecordset::Delete  从记录集中删除当前记录。 删除后,必须显式滚动到另一条记录。

CRecordset::DoBulkFieldExchange 调用以将批量数据行从数据源交换到记录集。 实现批量记录字段交换(批量 RFX)。

CRecordset::DoFieldExchange 调用以在记录集的字段数据成员与数据源上的相应记录之间(双向)交换数据。 实现记录字段交换 (RFX)。

CRecordset::Edit    准备对当前记录进行更改。 调用 Update 以完成编辑。

CRecordset::FlushResultSet  如果使用预定义查询时要检索另一个结果集,则返回非零值。

CRecordset::GetBookmark 将记录的书签值分配给参数对象。

CRecordset::GetDefaultConnect   调用以获取默认的连接字符串。

CRecordset::GetDefaultSQL   调用以获取要执行的默认 SQL 字符串。

CRecordset::GetFieldValue   返回记录集中字段的值。

CRecordset::GetODBCFieldCount   返回记录集中的字段数。

CRecordset::GetODBCFieldInfo    返回有关记录集中字段的特定类型信息。

CRecordset::GetRecordCount  返回记录集中的记录数。

CRecordset::GetRowsetSize   返回希望在单个提取期间检索的记录数。

CRecordset::GetRowsFetched  返回提取期间检索的实际行数。

CRecordset::GetRowStatus    返回提取后行的状态。

CRecordset::GetSQL  获取用于为记录集选择记录的 SQL 字符串。

CRecordset::GetStatus   获取记录集状态:当前记录索引以及是否已获取记录的最终计数。

CRecordset::GetTableName    获取记录集所基于的表的名称。

CRecordset::IsBOF   如果在第一条记录之前定位了记录集,则返回非零值。 没有最新记录。

CRecordset::IsDeleted   如果记录集位于已删除的记录上,则返回非零值。

CRecordset::IsEOF   如果记录集位于最后一条记录之后,则返回非零值。 没有最新记录。

CRecordset::IsFieldDirty    如果当前记录中的指定字段已更改,则返回非零值。

CRecordset::IsFieldNull 如果当前记录中的指定字段为 null(没有值),则返回非零值。

CRecordset::IsFieldNullable 如果当前记录中的指定字段可以设置为 null(没有值),则返回非零值。

CRecordset::IsOpen  如果此前调用过 Open,则返回非零值。

CRecordset::Move    将记录集置于任一方向上当前记录的指定数目记录。

CRecordset::MoveFirst   将当前记录放置在记录集中的第一条记录上。 首先测试 IsBOF。

CRecordset::MoveLast    将当前记录放置在最后一条记录或最后一行集上。 首先测试 IsEOF。

CRecordset::MoveNext    将当前记录放置在下一条记录或下一行集上。 首先测试 IsEOF。

CRecordset::MovePrev    将当前记录放置在前一条记录或前一行集上。 首先测试 IsBOF。

CRecordset::OnSetOptions    调用以为指定 ODBC 语句设置选项(在选择时使用)。

CRecordset::OnSetUpdateOptions  调用以为指定 ODBC 语句设置选项(在更新时使用)。

CRecordset::Open    通过检索表或执行记录集所表示的查询来打开记录集。

CRecordset::RefreshRowset   刷新指定行的数据和状态。

CRecordset::Requery 再次运行记录集的查询以刷新所选记录。

CRecordset::SetAbsolutePosition 将记录集放置在对应于指定记录编号的记录上。

CRecordset::SetBookmark 将记录集放置在书签指定的记录上。

CRecordset::SetFieldDirty   将当前记录中的指定字段标记为已更改。

CRecordset::SetFieldNull    将当前记录中指定字段的值设置为 null(没有值)。

CRecordset::SetLockingMode  将锁定模式设置为“乐观”锁定(默认)或“悲观”锁定。 确定如何锁定记录以进行更新。

CRecordset::SetParamNull    将指定参数设置为 null(没有值)。

CRecordset::SetRowsetCursorPosition 将游标置于行集中的指定行上。

CRecordset::SetRowsetSize   指定希望在提取期间检索的记录数。

CRecordset::Update  通过在数据源上保存新数据或编辑的数据来完成 AddNew 或 Edit 操作。

CDBVariant对象表示用于MFC ODBC类的可变数据类型。CDBVariant允许存储值而不必关心值的数据类型。

类CRecordset在三个成员函数中利用CDBVariant对象:GetFieldValue,GetBookmark和SetBookmark。


CDBVariant::m_boolVal   包含类型为 BOOL 的值。

CDBVariant::m_chVal 包含类型为 unsigned char 的值。

CDBVariant::m_dblVal    包含类型为 double 的值。

CDBVariant::m_fltVal    包含类型为 float 的值。

CDBVariant::m_iVal  包含类型为 short 的值。

CDBVariant::m_lVal  包含类型为 long 的值。

CDBVariant::m_pbinary   包含指向 CLongBinary 类型对象的指针。

CDBVariant::m_pdate 包含指向 TIMESTAMP_STRUCT 类型对象的指针。

CDBVariant::m_pstring   包含指向 CString 类型对象的指针。

CDBVariant::m_pstringA  存储指向 ASCII CString 对象的指针。

CDBVariant::m_pstringW  存储指向宽 CString 对象的指针。

使用OpenEx函数打开数据库,ODBC数据源TestAccessDB,用户名密码为admin,admin


db.OpenEx("DSN=TestAccessDB;UID=admin;PWD=admin", CDatabase::noOdbcDialog); 

使用ExecuteSQL函数执行sql语句


db.ExecuteSQL("insert into table1 (id, name, sex, age) values(1, '张三','男',44)");

完整代码


#include "stdafx.h"

#include <afxdb.h>

int _tmain(int argc, _TCHAR* argv[])

{

        CDatabase db;

        BOOL bRtn;

        try {

            bRtn = db.OpenEx("DSN=TestAccessDB;UID=admin;PWD=admin", CDatabase::noOdbcDialog); 

        }catch (CDBException *pDBEx) {

            pDBEx->ReportError();

        }catch (CMemoryException *pMemEx) {

            pMemEx->ReportError();

        }

        if (!bRtn) {

            printf("连接数据库失败!\n");

        }else{

            printf("连接数据库成功!\n");

        }

        //创建表

        try {

            db.ExecuteSQL("CREATE TABLE table1 ("

            "id int primary key,"

            "name text(10),"

            "sex text(4),"

            "age int)");

            printf("创建表成功!\n");

        } catch (CDBException *pDBEx) {

            pDBEx->ReportError();

        }



        //插入数据

        try {

            db.ExecuteSQL("insert into table1 (id, name, sex, age) values(1, '张三','男',44)");

            db.ExecuteSQL("insert into table1 (id, name, sex, age) values(2, '张四','女',24)");

            db.ExecuteSQL("insert into table1 (id, name, sex, age) values(3, '张五','女',11)");

            db.ExecuteSQL("insert into table1 (id, name, sex, age) values(4, '张六','男',21)");

            printf("新增数据成功!\n");

        } catch (CDBException *pDBEx) {

            pDBEx->ReportError();

        } 

        try {

            db.ExecuteSQL("delete from table1 where age < 20");

            printf("删除数据成功!\n");

        } catch (CDBException *pDBEx) {

            pDBEx->ReportError();

        }

        //获取数据

        CRecordset recordSet(&db);

        try {

            bRtn = recordSet.Open(CRecordset::forwardOnly, "select * from table1", CRecordset::readOnly);

        } catch(CDBException *pDBEx) {

            pDBEx->ReportError();

        } catch(CMemoryException *pMemEx) {

            pMemEx->ReportError();

        }

        if(!bRtn) {

            MessageBox(NULL, "Query table failed!", "", MB_OK|MB_ICONERROR);

            return -1 ;

        }



        //recordSet.MoveFirst();

        

        printf("id  name    sex age\n");

        for(;!recordSet.IsEOF();recordSet.MoveNext()) {



            CDBVariant varID,varName,varSex,varAge;

            recordSet.GetFieldValue( "id" , varID );

            recordSet.GetFieldValue( "name" , varName );

            recordSet.GetFieldValue( "sex" , varSex );

            recordSet.GetFieldValue( "age" , varAge );



            printf("%d  %s  %s  %d\n", varID.m_iVal, varName.m_pstringA->GetString(), varSex.m_pstringA->GetString(), varAge.m_iVal);

        }



        recordSet.Close();

        db.Close();

        system("pause");

        return 0;

}