数学建模社区-数学中国

标题: [转帖]在Visual C++中用ADO进行数据库编程(中) [打印本页]

作者: god    时间: 2005-3-30 22:53
标题: [转帖]在Visual C++中用ADO进行数据库编程(中)
4.执行SQL命令并取得结果记录集
" d/ l, }1 z- D! z
3 }; l( b; I8 t+ m  为了取得结果记录集,我们定义一个指向Recordset对象的指针:_RecordsetPtr m_pRecordset;
8 z3 v8 q8 ~) S+ e并为其创建Recordset对象的实例: m_pRecordset.CreateInstance("ADODB.Recordset");& V0 J/ S% R! r- A3 e) O2 H: D+ }( A
SQL命令的执行可以采用多种形式,下面我们一进行阐述。
& P! p% n" d4 b$ X; `6 v$ j7 J0 u
! y! y7 X2 l5 F+ ~) `  |  (1)利用Connection对象的Execute方法执行SQL命令
0 }) R' {8 u* G* g4 F0 a) Z3 M6 m) X6 R: L5 _/ T7 [% T% r
  Execute方法的原型如下所示:
. m+ B7 ~  Y2 p+ l1 J' S6 F6 O7 s2 W/ C( k; d% M
_RecordsetPtr Connection15::Execute ( _bstr_t CommandText, VARIANT * RecordsAffected, long Options )
( ^6 Y& m% x) j7 P& U. g
" l, S/ P3 d, Y! e其中CommandText是命令字串,通常是SQL命令。: g1 A: F5 q, W; {) M
参数RecordsAffected是操作完成后所影响的行数, * ?; t* T$ F3 r  T
参数Options表示CommandText中内容的类型,Options可以取如下值之一:! A4 m1 ~& g. L3 \/ v
adCmdText:表明CommandText是文本命令6 e* p1 `1 g/ ^# Y$ A
adCmdTable:表明CommandText是一个表名# D$ G1 }3 D( _$ k% ]2 D4 o
adCmdProc:表明CommandText是一个存储过程2 c( T% Z4 ^- M
adCmdUnknown:未知
( e5 s: z" {6 ~; k1 y* Q2 K3 I, |! j; u: r9 y& d! Y
Execute执行完后返回一个指向记录集的指针,下面我们给出具体代码并作说明。 6 X5 W4 u1 s) |
_variant_t RecordsAffected;
6 ^1 c# q2 t3 T///执行SQL命令:CREATE TABLE创建表格users,users包含四个字段:整形ID,字符串username,整形old,日期型birthday+ v2 ~+ E# [$ B/ K
m_pConnection->Execute("CREATE TABLE users(ID INTEGER,username TEXT,old INTEGER,birthday DATETIME)",9 p$ \1 p" f& |- h) ^
&RecordsAffected,6 z7 d, f: W5 _5 j
adCmdText);
5 O- ]1 A- I% t/ B4 v& Z8 F! S) u& `& F* s9 I8 F, \
///往表格里面添加记录
  w& p0 @' \  m1 [4 {0 Em_pConnection->Execute("INSERT INTO users(ID,username,old,birthday) valueS (1, ''''Washington'''',25,''''1970/1/1'''')",&RecordsAffected,adCmdText);
+ K) @# {' o+ R( B+ y5 x, a+ S% w! b- @* A, t. Z$ l5 }. k$ y# C! J8 S7 a
///将所有记录old字段的值加一) L0 D- ~/ V, {  O
m_pConnection->Execute("UPDATE users SET old = old+1",&RecordsAffected,adCmdText);
" g/ ?/ J/ ]4 I* F9 y
. z0 J, F) W' J# O///执行SQL统计命令得到包含记录条数的记录集
# V. |! y4 Q% h5 s% D* Y* r3 em_pRecordset = m_pConnection->Execute("SELECT COUNT(*) FROM users",&RecordsAffected,adCmdText);" K; X, c6 q1 T
_variant_t vIndex = (long)0;" p' Y) ^4 d- V2 X0 ~  M
_variant_t vCount = m_pRecordset->GetCollect(vIndex);///取得第一个字段的值放入vCount变量) t: Y( {% D$ }% ^4 ]. w# f
上两句可以写成— _variant_t vCount = m_pRecordset->GetCollect((_variant_t)((long)0));8 O* N7 V2 n% G, n" P. r4 I8 d
m_pRecordset->Close();///关闭记录集
5 R& {9 r9 |. r7 @" RCString message;
' ]. F4 L, a6 I$ h9 }, Cmessage.format("共有%d条记录",vCount.lVal);7 Y' n" o5 s% i9 f3 T3 n2 K
AfxMessageBox(message);///显示当前记录条数
9 Z& W" c) ~+ Y& U9 F4 k! I  x  }, f
; p7 R% q. _* s' S1 Z9 W(2)利用Command对象来执行SQL命令
$ U  {: o5 G8 {5 u$ G$ L+ X
" q" Q8 V+ V: m0 L  ^3 T_CommandPtr m_pCommand;( ?% S. H! c8 ~+ p6 G: j, q
m_pCommand.CreateInstance("ADODB.Command");
- w, S2 Q) u' K, O$ `, U_variant_t vNULL;
+ x) e/ \  }* q! Y2 G) b$ J4 P0 CvNULL.vt = VT_ERROR;
5 I! `9 z3 L+ r+ q; avNULL.scode = DISP_E_PARAMNOTFOUND;///定义为无参数
( n- I4 l# E1 x2 em_pCommand->ActiveConnection = m_pConnection;///非常关键的一句,将建立的连接赋值给它! ]8 U' j5 {, c9 O5 u
m_pCommand->CommandText = "SELECT * FROM users";///命令字串
  p8 n- a# m) e4 jm_pRecordset = m_pCommand->Execute(&vNULL,&vNULL,adCmdText);///执行命令,取得记录集/ h& _1 x9 R: a3 L5 \6 N! w: u

+ M5 X4 e8 F* g  在这段代码中我们只是用Command对象来执行了SELECT查询语句,Command对象在进行存储过程的调用中能真正体现它的作用。下次我们将详细介绍。
9 @6 ~; ~- r$ j' L( F7 F% y6 {# i3 Y% G4 z
  (3)直接用Recordset对象进行查询取得记录集2 K6 t1 J. U5 t# V* U; q3 i1 D) O

# a8 K2 t3 D) j- w5 W  实例—— 8 K1 S: b7 ?6 Q# ~8 }
- K& h+ _( t0 m4 H+ `' V; S
void CGmsaDlg::OnDBSelect()
. i1 n6 f  o0 W{
9 A! z8 d4 Z2 l8 S  a7 v& t// TOD Add your control notification handler code here% P; d0 _" q7 M
_RecordsetPtr Rs1; //定义Recordset对象) {- X- A7 Y0 t; b9 D/ m0 l
_bstr_t Connect("DSN=GMS;UID=saWD=;");//定义连接字符串
! n/ j( A$ j, o1 q3 __bstr_t Source ("SELECT count(*) FROM buaa.mdb010"); //要执行的SQL语句- \' o! F$ u& R
::CoInitialize(NULL); //初始化Rs1对象
1 k$ O6 l( N9 J9 i) H* }HRESUL hr = Rs1.CreateInstance( __uuidof( Recordset ) );9 e) c7 K! S, `; O" b: p% \
//省略对返回值hr的判断
* u) ?& F2 q" BRs1->Open( Source,1 P1 r  _, d0 G; J7 d' q
Connect,; v/ I% Q- T4 @" E9 Y, y& p
adOpenForwardOnly,
0 M) n6 h3 q: xadLockReadOnly,
" A2 m" s7 c8 n" p' j-1 ); " @5 Y4 }6 y1 `! V
_variant_t temp=Rs1->GetCollect(_variant_t((long)0));
) D& i0 t5 y! L/ ^CString strTemp=(char* )(_bstr_t)temp;
! ^% n. X# O& p! @MessageBox("OK!"+strTemp);% X) ^, Q$ h7 o! Y" D3 ?) F2 m
}
7 ~2 L1 I1 i0 ]$ x/ @! J
2 X& x8 R5 y+ y7 w" ]! a+ _3 z3 {例如
' E, f) N% H* S1 e! e6 W6 hm_pRecordset->Open("SELECT * FROM users",
+ y4 s% k( U3 ^# w_variant_t((IDispatch *)m_pConnection,true),' F/ z- I/ T; ^1 w% K4 Z
adOpenStatic,
7 q: T+ n, S, }2 g! L: f$ _9 i/ madLockOptimistic," Q. h' u$ f* i# l) b; g  I
adCmdText);
, }" V: y2 M' b6 M- w& `( u! X( P. R4 Z# M# a7 c% f% {4 v
Open方法的原型是这样的:- j/ r; s2 \: J0 u$ ?
HRESULT Recordset15::Open ( const _variant_t & Source, $ {; L/ |5 j) X$ T* K9 |! a
const _variant_t & ActiveConnection, 0 Z8 ]* O5 [+ h& v$ J; e  r
enum CursorTypeEnum CursorType,
; @8 j7 k' _! Eenum LockTypeEnum LockType, 6 O! [6 ^5 Y8 C: O1 A
long Options )
! H4 L8 Z& g+ ^6 a& B4 c
" S  y3 u, w  ^2 c其中:8 k. v" \. B- O+ L' |' l' B
4 m1 S' A) v( U
①Source是数据查询字符串
3 A) i  R1 _, `2 W( G0 A②ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象)
. ?; j0 ?0 ]! f/ u. Q③CursorType光标类型,它可以是以下值之一,请看这个枚举结构:7 u4 x9 w6 H' n! w/ j/ F  e0 H9 D
& _: k3 Y  }5 n
enum CursorTypeEnum
1 s* d; P3 E# G{
' M; S3 v* {- U! l! y5 J' _+ radOpenUnspecified = -1,///不作特别指定
, P# }: Z7 Z* u. N0 h- D6 sadOpenForwardOnly = 0,///前滚静态光标。这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这种方式可以提高浏览速度。但诸如BookMark,RecordCount,AbsolutePosition,AbsolutePage都不能使用
* |3 h, L9 [/ S4 Y: ladOpenKeyset = 1,///采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。
+ z8 A  `1 ]/ t3 A) @' f. S+ x% G, R$ W/ R7 a8 R
adOpenDynamic = 2,///动态光标。所有数据库的操作都会立即在各用户记录集上反应出来。
8 U" J( o3 f7 B1 Z9 t5 I) Y4 v; dadOpenStatic = 3///静态光标。它为你的记录集产生一个静态备份,但其它用户的新增、删除、更新操作对你的记录集来说是不可见的。
. \& {9 s: Y# i! n' {, Z};
( ^+ z) A9 ^) P7 o1 H8 p" ~④LockType锁定类型,它可以是以下值之一,请看如下枚举结构:
" J6 V7 V& l) {8 u* g, [+ P# @
enum LockTypeEnum
) ^# z! X1 q2 ~! F: t( x{
+ E# V# c! {1 g3 c, X, tadLockUnspecified = -1,///未指定, T* w  R% A! V* O0 \/ {
adLockReadOnly = 1,///只读记录集
  Z6 Y% u% z3 H1 O* i2 h# qadLockPessimistic = 2,悲观锁定方式。数据在更新时锁定其它所有动作,这是最安全的锁定机制
8 d+ B; ~' D+ G5 r$ X* radLockOptimistic = 3,乐观锁定方式。只有在你调用Update方法时才锁定记录。在此之前仍然可以做数据的更新、插入、删除等动作$ X( X& P7 |/ z. d; l
adLockBatchOptimistic = 4,乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。
. `5 Q; W6 T1 _% T0 b5 H# L& _& P};
6 ~) N$ I; A4 @+ Y; X/ U. Z5 V$ Q, Z
⑤Options可以取如下值之一:
  c7 P9 |  B" O" KadCmdText:表明CommandText是文本命令! [; R, P8 O  w- [$ x+ d7 x
adCmdTable:表明CommandText是一个表名2 O' Y1 }( z7 W% j
adCmdProc:表明CommandText是一个存储过程8 ^! U! A. J3 Q7 g3 a4 \, c
adCmdUnknown:未知




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5