VC++下使用ADO编写数据库程序
VC
++下使用
ADO
编写数据库程序
准备:
( 1 )、引入 ADO 类
在stdafx.h中加入如下语句:
#import "c:\program files\common files\system\ado\msado15.dll" \
no_namespace \
rename ( "EOF" , "adoEOF" )
( 2 )、初始化 COM
在 MFC 中可以用 AfxOleInit ();非 MFC 环境中用:
CoInitialize ( NULL );
CoUnInitialize ();
( 3 ) #import 包含后就可以用3个智能指针了:_ConnectionPtr、_RecordsetPtr和_CommandPtr
1 .连接和关闭数据库
( 1 )连接
一般在 App 类成员函数 InitInstance ()里初始化
例子:连接 Access 数据库
AfxOleInit (); //初始化
HRESULT hr ;
try
{
hr = m_pConnection . CreateInstance ( "ADODB.Connection" ); ///创建Connection对象
if ( SUCCEEDED ( hr ))
{
m_pConnection -> ConnectionTimeout = 0 ;
hr = m_pConnection -> Open (
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb" , "" , "" , adModeUnknown );
//m_pConnection->PutDefaultDatabase ((_bstr_t)"DB");//设置默认数
据库
m_pCommand . CreateInstance ( __uuidof ( Command ));
m_pCommand -> CommandTimeout = 5 ;
m_pCommand -> ActiveConnection = m_pConnection ;
}
}
catch ( _com_error e ) ///捕捉异常
{
CString errormessage ;
errormessage . Format ( "连接数据库失败!\r\n错误信息:%s" , e . ErrorMessage ());
AfxMessageBox ( errormessage ); ///显示错误信息
return FALSE ;
}
( 2 )、关闭
一般在 App 类成员函数 InitInstance ()里关闭数据库连接
//如果数据库连接有效
if ( m_pConnection -> State )
m_pConnection -> Close ();
m_pConnection = NULL ;
( 3 )、设置连接时间 //设置连接时间-----------------------------------
pConnection -> put_ConnectionTimeout ( long ( 5 ));
2 .打开一个结果集
( 1 )打开,首先创建一个 _RecordsetPtr 实例,然后调用 Open ()得到一条 SQL 语句的执行结果
_RecordsetPtr m_pRecordset ;
m_pRecordset . CreateInstance ( __uuidof ( Recordset ));
// 在ADO操作中建议语句中要常用try...catch()来捕获错误信息,
// 因为它有时会经常出现一些意想不到的错误。jingzhou xu
try
{
m_pRecordset -> Open ( "SELECT * FROM DemoTable" , // 查询DemoTable表中所有字段
m_pConnection . GetInterfacePtr (), // 获取库接库的IDispatch指针
adOpenDynamic ,
adLockOptimistic ,
adCmdText );
}
catch ( _com_error * e )
{
AfxMessageBox ( e -> ErrorMessage ());
}
( 2 )关闭结果集 m_pRecordset -> Close ();
m_pRecordset = NULL ;
3 .操作一个结果集
( 1 )、遍历(读取)
a )、用 pRecordset -> adoEOF 来判断数据库指针是否已经移到结果集的末尾了; m_pRecordset -> BOF 判断是否 在第一
条记录前面: while (! m_pRecordset -> adoEOF )
{
var = m_pRecordset -> GetCollect ( "Name" );
if ( var . vt != VT_NULL )
strName = ( LPCSTR ) _bstr_t ( var );
var = m_pRecordset -> GetCollect ( "Age" );
if ( var . vt != VT_NULL )
strAge = ( LPCSTR ) _bstr_t ( var );
m_AccessList . AddString ( strName + " --> " + strAge );
m_pRecordset -> MoveNext ();
}
b )、取得一个字段的值的办法有两种办法
一是
//表示取得第0个字段的值 m_pRecordset->GetCollect("Name");
或者 m_pRecordset -> GetCollect ( _variant_t ( long ( 0 ));
二是
pRecordset -> get_Collect ( "COLUMN_NAME" );
或者 pRecordset -> get_Collect ( long ( index ));
( 2 )、添加
a )、调用 m_pRecordset -> AddNew ();
b )、调用 m_pRecordset -> PutCollect ( "Name" , _variant_t ( m_szName ));给每个字段赋值( m_szName 为控件所对应的字符串变量)
c )、调用 m_pRecordset -> Update ();确认
// 添加完后可读取显示
对于 MFC 有些控件显示需要更新(比如 ListBox )
( 3 )、修改
( 4 )、删除
a )、把记录指针移动到要删除的记录上,然后调用 Delete ( adAffectCurrent ) try
{
// 假设删除第二条记录
m_pRecordset -> MoveFirst ();
m_pRecordset -> Move ( 1 );
// 从0开始
m_pRecordset -> Delete ( adAffectCurrent );
// 参数adAffectCurrent为删除当前记录
m_pRecordset -> Update ();
}
catch ( _com_error * e )
{
AfxMessageBox ( e -> ErrorMessage ());
}
4 .直接执行 SQL 语句,除了要用到结果集其余的大部分功能都可以直接用 SQL 语言实现
( 1 )、用 _CommandPtr 和 _RecordsetPtr 配合
_CommandPtr m_pCommand ;
m_pCommand . CreateInstance ( __uuidof ( Command ));
// 将库连接赋于它
m_pCommand -> ActiveConnection = m_pConnection ;
// SQL语句
m_pCommand -> CommandText = "SELECT * FROM DemoTable" ;
// 执行SQL语句,返回记录集
m_pRecordset = m_pCommand -> Execute ( NULL , NULL , adCmdText );
( 2 )、直接用 _ConnectionPtr 执行 SQL 语句
_RecordsetPtr Connection15 :: Execute ( _bstr_t CommandText ,
VARIANT *
RecordsAffected ,
long Options )
其中 CommandText 是命令字串,通常是 SQL 命令。
参数 RecordsAffected 是操作完成后所影响的行数,
参数 Options 表示 CommandText 中内容的类型, Options 可以取如下值之一:
adCmdText :表明 CommandText 是文本命令
adCmdTable :表明 CommandText 是一个表名
adCmdProc :表明 CommandText 是一个存储过程
adCmdUnknown :未知
例子:
_variant_t RecordsAffected ;
m_pConnection -> Execute ( "UPDATE users SET old = old+1" ,& RecordsAffected , adCmdText );
5 .调用存储过程
( 1 )、利用 _CommandPtr
_CommandPtr m_pCommand ;
m_pCommand . CreateInstance ( __uuidof ( Command ));
m_pCommand -> ActiveConnection = m_pConnection ; // 将库连接赋于它
m_pCommand -> CommandText = "Demo" ;
m_pCommand -> Execute ( NULL , NULL , adCmdStoredProc );
( 2 )、直接用 _ConnectionPtr 直接调用(见 4 .( 2 ))
6 .遍历数据库中的所有表名 _ConnectionPtr m_pConnect ;
_RecordsetPtr pSet ;
HRESULT hr ;
try
{
hr = m_pConnect . CreateInstance ( "ADODB.Connection" );
if ( SUCCEEDED ( hr ))
{
CString dd ;
dd . Format ( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s" , file );
hr = m_pConnect -> Open (( _bstr_t ) dd , "" , "" , adModeUnknown );
pSet = m_pConnect -> OpenSchema ( adSchemaTables );
while (!( pSet -> adoEOF ))
{
//获取表格
_bstr_t table_name = pSet -> Fields -> GetItem ( "TABLE_NAME" )-
> Value ;
//获取表格类型
_bstr_t table_type = pSet -> Fields -> GetItem ( "TABLE_TYPE" )-
> Value ;
//过滤一下,只输出表格名称,其他的省略
if ( strcmp ((( LPCSTR ) table_type ), "TABLE" )== 0 ){
CString tt ;
tt . Format ( "%s" ,( LPCSTR ) table_name );
AfxMessageBox ( tt );
}
pSet -> MoveNext ();
}
pSet -> Close ();
}
m_pConnect -> Close ();
} catch ( _com_error e ) ///捕捉异常
{
CString errormessage ;
errormessage . Format ( "连接数据库失败!rn错误信息:%s" , e . ErrorMessage ());
AfxMessageBox ( errormessage );
return - 1 ;
}
7 .遍历一个表中的所有字段
Field * field = NULL ;
HRESULT hr ;
Fields * fields = NULL ;
hr = m_pRecordset -> get_Fields (& fields ); //得到记录集的字段集和
if ( SUCCEEDED ( hr ))
fields -> get_Count (& ColCount );
//得到记录集的字段集合中的字段的总个数
for ( i = 0 ; iItem [ i ]-> get_Name (& bstrColName ); //得到记录集//中的字段名
strColName = bstrColName ;
nameField = strColName ;
m_FieldsList . AddString ( nameField );
}
if ( SUCCEEDED ( hr ))
fields -> Release (); //释放指针
附:
1 、 _variant_t
( 1 )、一般传给这 3 个指针的值都不是 MFC 直接支持的数据类型,而要用 _variant_t 转换一下
_variant_t ( XX )可以把大多数类型的变量转换成适合的类型传入:
( 2 )、 _variant_t var ; _variant_t -> long : ( long ) var ;
_variant_t -> CString : CString strValue = ( LPCSTR ) _bstr_t ( var );
CString -> _variant_t : _variant_t ( strSql );
2 、 BSTR 宽字符串与 CString 相互转换
BSTR bstr ;
CString strSql ;
CString -> BSTR : bstr = strSql . AllocSysString ();
BSTR -> CString : strSql = ( LPCSTR ) bstr ;
3 、 _bstr_t 与 CString 相互转换
_bstr_t bstr ;
CString strSql ;
CString -> _bstr_t : bstr = ( _bstr_t ) strSql ;
_bstr_t -> CString : strSql = ( LPCSTR ) bstr ;
4 、关于时间
Access :表示时间的字符串 #2004-4-5#
Sql :表示时间的字符串 '' 2004 - 4 - 5 ''
DateField (时间字段) select * from my_table where DateField > #2004-4-10#
try
{
m_pCommand -> CommandText = "INSERT INTO tTest(age) VALUES('23f2') " ;
m_pRecordset = m_pCommand -> Execute ( NULL , NULL , adCmdText );
}
catch ( _com_error e ) ///捕捉异常
{
CString errormessage ;
errormessage . Format ( "连接数据库失败!\r\n错误信息:%s" , e . ErrorMessage ());
AfxMessageBox ( errormessage ); ///显示错误信息
}
准备:
( 1 )、引入 ADO 类
在stdafx.h中加入如下语句:
#import "c:\program files\common files\system\ado\msado15.dll" \
no_namespace \
rename ( "EOF" , "adoEOF" )
( 2 )、初始化 COM
在 MFC 中可以用 AfxOleInit ();非 MFC 环境中用:
CoInitialize ( NULL );
CoUnInitialize ();
( 3 ) #import 包含后就可以用3个智能指针了:_ConnectionPtr、_RecordsetPtr和_CommandPtr
1 .连接和关闭数据库
( 1 )连接
一般在 App 类成员函数 InitInstance ()里初始化
例子:连接 Access 数据库
AfxOleInit (); //初始化
HRESULT hr ;
try
{
hr = m_pConnection . CreateInstance ( "ADODB.Connection" ); ///创建Connection对象
if ( SUCCEEDED ( hr ))
{
m_pConnection -> ConnectionTimeout = 0 ;
hr = m_pConnection -> Open (
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb" , "" , "" , adModeUnknown );
//m_pConnection->PutDefaultDatabase ((_bstr_t)"DB");//设置默认数
据库
m_pCommand . CreateInstance ( __uuidof ( Command ));
m_pCommand -> CommandTimeout = 5 ;
m_pCommand -> ActiveConnection = m_pConnection ;
}
}
catch ( _com_error e ) ///捕捉异常
{
CString errormessage ;
errormessage . Format ( "连接数据库失败!\r\n错误信息:%s" , e . ErrorMessage ());
AfxMessageBox ( errormessage ); ///显示错误信息
return FALSE ;
}
( 2 )、关闭
一般在 App 类成员函数 InitInstance ()里关闭数据库连接
//如果数据库连接有效
if ( m_pConnection -> State )
m_pConnection -> Close ();
m_pConnection = NULL ;
( 3 )、设置连接时间 //设置连接时间-----------------------------------
pConnection -> put_ConnectionTimeout ( long ( 5 ));
2 .打开一个结果集
( 1 )打开,首先创建一个 _RecordsetPtr 实例,然后调用 Open ()得到一条 SQL 语句的执行结果
_RecordsetPtr m_pRecordset ;
m_pRecordset . CreateInstance ( __uuidof ( Recordset ));
// 在ADO操作中建议语句中要常用try...catch()来捕获错误信息,
// 因为它有时会经常出现一些意想不到的错误。jingzhou xu
try
{
m_pRecordset -> Open ( "SELECT * FROM DemoTable" , // 查询DemoTable表中所有字段
m_pConnection . GetInterfacePtr (), // 获取库接库的IDispatch指针
adOpenDynamic ,
adLockOptimistic ,
adCmdText );
}
catch ( _com_error * e )
{
AfxMessageBox ( e -> ErrorMessage ());
}
( 2 )关闭结果集 m_pRecordset -> Close ();
m_pRecordset = NULL ;
3 .操作一个结果集
( 1 )、遍历(读取)
a )、用 pRecordset -> adoEOF 来判断数据库指针是否已经移到结果集的末尾了; m_pRecordset -> BOF 判断是否 在第一
条记录前面: while (! m_pRecordset -> adoEOF )
{
var = m_pRecordset -> GetCollect ( "Name" );
if ( var . vt != VT_NULL )
strName = ( LPCSTR ) _bstr_t ( var );
var = m_pRecordset -> GetCollect ( "Age" );
if ( var . vt != VT_NULL )
strAge = ( LPCSTR ) _bstr_t ( var );
m_AccessList . AddString ( strName + " --> " + strAge );
m_pRecordset -> MoveNext ();
}
b )、取得一个字段的值的办法有两种办法
一是
//表示取得第0个字段的值 m_pRecordset->GetCollect("Name");
或者 m_pRecordset -> GetCollect ( _variant_t ( long ( 0 ));
二是
pRecordset -> get_Collect ( "COLUMN_NAME" );
或者 pRecordset -> get_Collect ( long ( index ));
( 2 )、添加
a )、调用 m_pRecordset -> AddNew ();
b )、调用 m_pRecordset -> PutCollect ( "Name" , _variant_t ( m_szName ));给每个字段赋值( m_szName 为控件所对应的字符串变量)
c )、调用 m_pRecordset -> Update ();确认
// 添加完后可读取显示
对于 MFC 有些控件显示需要更新(比如 ListBox )
( 3 )、修改
( 4 )、删除
a )、把记录指针移动到要删除的记录上,然后调用 Delete ( adAffectCurrent ) try
{
// 假设删除第二条记录
m_pRecordset -> MoveFirst ();
m_pRecordset -> Move ( 1 );
// 从0开始
m_pRecordset -> Delete ( adAffectCurrent );
// 参数adAffectCurrent为删除当前记录
m_pRecordset -> Update ();
}
catch ( _com_error * e )
{
AfxMessageBox ( e -> ErrorMessage ());
}
4 .直接执行 SQL 语句,除了要用到结果集其余的大部分功能都可以直接用 SQL 语言实现
( 1 )、用 _CommandPtr 和 _RecordsetPtr 配合
_CommandPtr m_pCommand ;
m_pCommand . CreateInstance ( __uuidof ( Command ));
// 将库连接赋于它
m_pCommand -> ActiveConnection = m_pConnection ;
// SQL语句
m_pCommand -> CommandText = "SELECT * FROM DemoTable" ;
// 执行SQL语句,返回记录集
m_pRecordset = m_pCommand -> Execute ( NULL , NULL , adCmdText );
( 2 )、直接用 _ConnectionPtr 执行 SQL 语句
_RecordsetPtr Connection15 :: Execute ( _bstr_t CommandText ,
VARIANT *
RecordsAffected ,
long Options )
其中 CommandText 是命令字串,通常是 SQL 命令。
参数 RecordsAffected 是操作完成后所影响的行数,
参数 Options 表示 CommandText 中内容的类型, Options 可以取如下值之一:
adCmdText :表明 CommandText 是文本命令
adCmdTable :表明 CommandText 是一个表名
adCmdProc :表明 CommandText 是一个存储过程
adCmdUnknown :未知
例子:
_variant_t RecordsAffected ;
m_pConnection -> Execute ( "UPDATE users SET old = old+1" ,& RecordsAffected , adCmdText );
5 .调用存储过程
( 1 )、利用 _CommandPtr
_CommandPtr m_pCommand ;
m_pCommand . CreateInstance ( __uuidof ( Command ));
m_pCommand -> ActiveConnection = m_pConnection ; // 将库连接赋于它
m_pCommand -> CommandText = "Demo" ;
m_pCommand -> Execute ( NULL , NULL , adCmdStoredProc );
( 2 )、直接用 _ConnectionPtr 直接调用(见 4 .( 2 ))
6 .遍历数据库中的所有表名 _ConnectionPtr m_pConnect ;
_RecordsetPtr pSet ;
HRESULT hr ;
try
{
hr = m_pConnect . CreateInstance ( "ADODB.Connection" );
if ( SUCCEEDED ( hr ))
{
CString dd ;
dd . Format ( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s" , file );
hr = m_pConnect -> Open (( _bstr_t ) dd , "" , "" , adModeUnknown );
pSet = m_pConnect -> OpenSchema ( adSchemaTables );
while (!( pSet -> adoEOF ))
{
//获取表格
_bstr_t table_name = pSet -> Fields -> GetItem ( "TABLE_NAME" )-
> Value ;
//获取表格类型
_bstr_t table_type = pSet -> Fields -> GetItem ( "TABLE_TYPE" )-
> Value ;
//过滤一下,只输出表格名称,其他的省略
if ( strcmp ((( LPCSTR ) table_type ), "TABLE" )== 0 ){
CString tt ;
tt . Format ( "%s" ,( LPCSTR ) table_name );
AfxMessageBox ( tt );
}
pSet -> MoveNext ();
}
pSet -> Close ();
}
m_pConnect -> Close ();
} catch ( _com_error e ) ///捕捉异常
{
CString errormessage ;
errormessage . Format ( "连接数据库失败!rn错误信息:%s" , e . ErrorMessage ());
AfxMessageBox ( errormessage );
return - 1 ;
}
7 .遍历一个表中的所有字段
Field * field = NULL ;
HRESULT hr ;
Fields * fields = NULL ;
hr = m_pRecordset -> get_Fields (& fields ); //得到记录集的字段集和
if ( SUCCEEDED ( hr ))
fields -> get_Count (& ColCount );
//得到记录集的字段集合中的字段的总个数
for ( i = 0 ; iItem [ i ]-> get_Name (& bstrColName ); //得到记录集//中的字段名
strColName = bstrColName ;
nameField = strColName ;
m_FieldsList . AddString ( nameField );
}
if ( SUCCEEDED ( hr ))
fields -> Release (); //释放指针
附:
1 、 _variant_t
( 1 )、一般传给这 3 个指针的值都不是 MFC 直接支持的数据类型,而要用 _variant_t 转换一下
_variant_t ( XX )可以把大多数类型的变量转换成适合的类型传入:
( 2 )、 _variant_t var ; _variant_t -> long : ( long ) var ;
_variant_t -> CString : CString strValue = ( LPCSTR ) _bstr_t ( var );
CString -> _variant_t : _variant_t ( strSql );
2 、 BSTR 宽字符串与 CString 相互转换
BSTR bstr ;
CString strSql ;
CString -> BSTR : bstr = strSql . AllocSysString ();
BSTR -> CString : strSql = ( LPCSTR ) bstr ;
3 、 _bstr_t 与 CString 相互转换
_bstr_t bstr ;
CString strSql ;
CString -> _bstr_t : bstr = ( _bstr_t ) strSql ;
_bstr_t -> CString : strSql = ( LPCSTR ) bstr ;
4 、关于时间
Access :表示时间的字符串 #2004-4-5#
Sql :表示时间的字符串 '' 2004 - 4 - 5 ''
DateField (时间字段) select * from my_table where DateField > #2004-4-10#
try
{
m_pCommand -> CommandText = "INSERT INTO tTest(age) VALUES('23f2') " ;
m_pRecordset = m_pCommand -> Execute ( NULL , NULL , adCmdText );
}
catch ( _com_error e ) ///捕捉异常
{
CString errormessage ;
errormessage . Format ( "连接数据库失败!\r\n错误信息:%s" , e . ErrorMessage ());
AfxMessageBox ( errormessage ); ///显示错误信息
}