我发现很多朋友在开发数据库时都使用 Delphi 自带的 ADO 组件 或 Diamond ADO,其实在 Delphi 中使用原生 ADO 接口也是十分方便和有效的。我使用原生 ADO 开发项目已有很长一段时间,也回答过一些朋友类似的问题,现在把自己的一点心得与大家分享,班门弄斧,只是希望能对大家有所帮助。当然,这帖子也是原生的,不是转贴的。一、优点 1 、大家知道 Delphi 对 ADO 接口进行了一番包装后形成了 ADOExpress,我想 Borland 的主要目的还是想与自己的数据敏感控件相连。然而事实上数据敏感控件并不是那么耀眼,如果你希望你编出来的程序稍微有点水准的话那就别用那玩意;如果你很少使用数据敏感控件,那么 ADOExpress 基本上失去了其应有的作用,无数冗余的属性、虚方法,不管你用不用得到一股脑给你编译进去,也会使你的程序再大上 200K;效率么,不说了。 2 、MSDN 和 VB 中的例子你可以搬过来就用。 3 、告诉那些 Delphi 反对者,Delphi 不是离开组件就活不了。 4 、关于代码重用:我给大家的例子都是以函数或过程形式,重用性不好么? 5 、别说帖子太长,那你看看 DB.pas, ADODB.pas 多长?二、基本储备 1 、一些必须的单元uses Variants, ComObj; 2 、一些基本常数(其它查 ADODB2000.pas): const adOpenDynamic = $ 00000002 ; adOpenStatic = $ 00000003 ; adLockOptimistic = $ 00000003 ; adLockBatchOptimistic = $ 00000004 ; adStateClosed = $ 00000000 ; adStateOpen = $ 00000001 ; adStateConnecting = $ 00000002 ; adStateExecuting = $ 00000004 ; adStateFetching = $ 00000008 ; adUseServer = $ 00000002 ; adUseClient = $ 00000003 ; adModeReadWrite = $ 00000003 ; adXactCursorStability = $ 00001000 ; adCmdText = $ 00000001 ; adCmdTable = $ 00000002 ; adCmdStoredProc = $ 00000004 ; adCmdFile = $ 00000100 ; adAffectCurrent = $ 00000001 ; adAffectGroup = $ 00000002 ; adAffectAll = $ 00000003 ; adAffectAllChapters = $ 00000004 ; 3 、一些基本函数和过程 // 创建 Connection 对象 function CreateConnection: OleVariant; // 释放 Connection 对象;cnn 为 Connection 对象 procedure FreeConnection(var cnn: OleVariant); // 创建 Recordset 对象 function CreateRecordset: OleVariant; // 释放 Recordset 对象;rst 为 Recordset 对象 procedure FreeRecordset(var rst: OleVariant); // 创建 Command 对象 function CreateCommand: OleVariant; // 释放 Command 对象;cmd 为 Command 对象 procedure FreeCommand(var cmd: OleVariant); // 用 Connection 连接到 SQLServer 数据库;cnn 为 Connection 对象,db 数据库名,host 主机名,usr 用户名,pwd 密码 function ConnectToDB(cnn: OleVariant; const db, host, usr, pwd: string ): Boolean; // 执行 SQL 语句,有返回行,无事务处理;cnn 为 Connection 对象,rst 为 Recordset 对象,sql 为 SQL 语句(可以是存储过程) function ExecSQL(cnn, rst: OleVariant; const sql: string ): Boolean; // 执行 SQL 语句,无返回行,有事务处理;cnn 为 Connection 对象,cmd 为 Command 对象,sql 为 SQL 语句(可以是存储过程) function ExecSQLA(cnn, cmd: OleVariant; const sql: string ): Boolean;function CreateConnection: OleVariant;begin try Result : = CreateOleObject( ' ADODB.Connection ' ); Result.CursorLocation : = adUseServer; Result.IsolationLevel : = adXactCursorStability; Result.Mode : = adModeReadWrite; Result.Provider : = ' SQLOLEDB.1 ' ; except if not VarIsEmpty(Result) then Result : = Unassigned; end;end;procedure FreeConnection(var cnn: OleVariant);begin if not VarIsEmpty(cnn) then begin if cnn.State <> adStateClosed then cnn.Close; cnn : = Unassigned; end;end;function CreateRecordset: OleVariant;begin try Result : = CreateOleObject( ' ADODB.Recordset ' ); Result.CacheSize : = 1000 ; Result.CursorType : = adOpenStatic; Result.CursorLocation : = adUseServer; Result.LockType : = adLockOptimistic; except if not VarIsEmpty(Result) then Result : = Unassigned; end;end;procedure FreeRecordset(var rst: OleVariant);begin FreeConnection(rst);end;function CreateCommand: OleVariant;begin try Result : = CreateOleObject( ' ADODB.Command ' ); Result.CommandType : = adCmdText; Result.CommandTimeout : = 5 ; except if not VarIsEmpty(Result) then Result : = Unassigned; end;end;procedure FreeCommand(var cmd: OleVariant);begin if not VarIsEmpty(cmd) then cmd : = Unassigned;end;function ConnectToDB(cnn: OleVariant; const db, host, usr, pwd: string ): Boolean;begin Result : = not VarIsEmpty(cnn); if Result then begin if cnn.State <> adStateClosed then cnn.Close; cnn.ConnectionString : = ' Provider=SQLOLEDB.1;Persist Security Info=True;Initial Catalog= ' + db + ' ;Data Source= ' + host + ' ;Connect Timeout=5; ' + ' Use Procedure for Prepare=1 ' ; try cnn.Open(cnn.ConnectionString, usr, pwd, - 1 ); except Result : = False; end; end;end;function ExecSQL(cnn, rst: OleVariant; const sql: string ): Boolean;begin Result : = not (VarIsEmpty(cnn) or VarIsEmpty(rst)) and (cnn.State = adStateOpen); if Result then begin if rst.State <> adStateClosed then rst.Close; try rst.Open(sql, cnn, adOpenStatic, adLockOptimistic, adCmdText); except Result : = False; end; end;end;function ExecSQLA(cnn, cmd: OleVariant; const sql: string ): Boolean;begin Result : = not (VarIsEmpty(cnn) or VarIsEmpty(cmd)) and (cnn.State = adStateOpen); if Result then begin cnn.BeginTrans; try cmd.ActiveConnection : = cnn; cmd.CommandText : = sql; cmd.Prepared : = True; cmd.Execute; cnn.CommitTrans; except cnn.RollbackTrans; Result : = False; end; end;end;三、访问数据 1 、最前 rst.MoveFirst; 2 、最后 rst.MoveLast; 3 、向前 rst.MovePrevious; 4 、向后 rst.MoveNext; 5 、取当前记录 rst.Fields[ 0 ].Value 或 rst.Fields[ ' 字段名 ' ].Value; 6 、修改当前记录 rst.Update(rst.Fields[ 0 ].Name, 某值); 7 、取消修改 rst.CancelUpdate; 8 、删除当前记录 rst.Delete(adAffectCurrent); 9 、删除所有记录 rst.Delete(adAffectAll); 10 、追加记录 rst.AddNew; rst.Fields[ 0 ].Value : = 值1; rst.Fields[ 1 ].Value : = 值2; rst.Update; 11 、刷新 rst.Refresh; 12 、记录数 rst.RecordCount 15 、其它方法和属性查 MSDN 或 ADO 的帮助;四、一些例子 // 变量声明 var cnn, rst, cmd: OleVariant; // 创建对象 procedure TForm1.FormCreate(Sender: TObject);begin cnn : = CreateConnection; rst : = CreateRecordset; cmd : = CreateCommand;end; // 释放对象 procedure TForm1.FormDestroy(Sender: TObject);begin FreeCommand(cmd); FreeRecordset(rst); FreeConnection(cnn);end; // 连接数据库 procedure TForm1.Button1Click(Sender: TObject);begin if ConnectToDB(cnn, ' mydb ' , ' 127.0.0.1 ' , ' sa ' , ' ok ' ) then Caption : = ' 连接成功 ' else Caption : = ' 连接失败 ' ;end; // 取记录 procedure TForm1.Button2Click(Sender: TObject);begin ExecSQL(cnn, rst, ' select * from 表a ' ); Caption : = VarToStr(rst.Fields[ ' 字段a ' ].Value);end;五、原生 ADO 与 Delphi ADOExpress 组件的对应关系 1 、Connection <=> ADOConnection.ConnectionObject; 2 、Recordset <=> ADODataSet.Recordset; 3 、Command <=> ADOCommand.CommandObject; 4 、 ? <=> ADOQuery,因为 ADOQuery 根本就不是原生 ADO 对象 5 、ExecSQL <=> ADODataSet.Open; 6 、ExecSQLA <=> ADOCommand.Execute; 7 、有了上面几个其它的就不多说了六、与数据库结构有关的一些函数 1 、动态改变字段名称uses ComObj; // Access // TableName: 表名; OldColName: 原字段名; NewColName: 新字段名; procedure RenameField( const TableName, OldColName, NewColName: string );var DB, Col: OleVariant;begin DB : = CreateOleObject( ' ADOX.Catalog ' ); DB.ActiveConnection : = ADOConnection1.ConnectionObject; Col : = CreateOleObject( ' ADOX.Column ' ); Col : = DB.Tables[TableName].Columns[OldColName]; Col.Name : = NewColName;end; // SQLServer procedure RenameField( const TableName, OldColName, NewColName: string );begin with ADOCommand1 do begin CommandText : = ' EXEC sp_rename ''' + TableName + ' . ' + OldColName + ''' , ''' + NewColName + ''' , '' COLUMN '' ; ' ; Excute; end;end; 2 、取得 Access 库中的表结构type TTableDef = record Name, DateCreated, LastUpdated, Description: string ; end; TTableDefs = array of TTableDef;procedure GetTableDefs( const DBName: string ; out TableDefs: TTableDefs);var DBEngine, DB: OleVariant; I: Longint;begin try DBEngine : = CreateOleObject( ' DAO.DBEngine.36 ' ); DB : = DBEngine.OpenDatabase(DBName); SetLength(TableDefs, Longint(DB.TableDefs.Count)); for I : = Low(TableDefs) to High(TableDefs) do begin TableDefs[I].Name : = DB.TableDefs[I].Name; TableDefs[I].DateCreated : = DB.TableDefs[I].DateCreated; TableDefs[I].LastUpdated : = DB.TableDefs[I].LastUpdated; try TableDefs[I].Description : = DB.TableDefs[I].Properties[ ' Description ' ].Value; except TableDefs[I].Description : = '' ; end; end; finally DB : = Unassigned; DBEngine : = Unassigned; end;end; 3 、取得 Access 表中的字段结构type TFieldDef = record Name: string ; Types, Size: Longint; Description: string ; end; TFieldDefs = array of TFieldDef;procedure GetFieldDefs( const DBName, TableName: string ; out FieldDefs: TFieldDefs);var DBEngine, DB: OleVariant; I: Longint;begin try DBEngine : = CreateOleObject( ' DAO.DBEngine.36 ' ); DB : = DBEngine.OpenDatabase(DBName); SetLength(FieldDefs, Longint(DB.TableDefs[TableName].Fields.Count)); for I : = Low(FieldDefs) to High(FieldDefs) do begin FieldDefs[I].Name : = DB.TableDefs[TableName].Fields[I].Name; FieldDefs[I].Types : = DB.TableDefs[TableName].Fields[I].Type; FieldDefs[I].Size : = DB.TableDefs[TableName].Fields[I].Size; try FieldDefs[I].Description : = DB.TableDefs[TableName].Fields[I].Properties[ ' Description ' ].Value; except FieldDefs[I].Description : = '' ; end; end; finally DB : = Unassigned; DBEngine : = Unassigned; end;end; 4 、至于如何动态创建 Access 数据库之类我就不罗嗦了,到处都有相关的月经贴七、其它 1 、我使用 ADO 的经历:ADOExpress --> ADOExpress的原生接口 --> 引用ADO2.1接口单元,即ADODB_TLB --> 直接使用 ADO 的 COM 接口; 2 、希望此贴能对朋友门有所帮助,我写的这些都是经过实战检验的; 3 、觉得有用的朋友可以试一下,如果觉得没用就当我没写,耽误你时间了。