在Delphi中使用原生ADO控制数据库

转载 2007年10月09日 23:19:00
我发现很多朋友在开发数据库时都使用 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: stringout 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: stringout 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、觉得有用的朋友可以试一下,如果觉得没用就当我没写,耽误你时间了。
 

Delphi下的原生ADO使用方法

本文向您揭示在Delphi中使用ADO是如何轻而易举,结合了ADO的Delphi应用程序,将不再依赖于BDE。 ADO的精髓在于利用简单的COM指令来快速方便的访问ODBC数据源,微软的表格、...
  • Hmillet
  • Hmillet
  • 2016年03月30日 09:55
  • 2418

Delphi使用ADO组件访问ACCESS数据入门例程

在form上添加控件 一.方法一: 1.增加一个ADOConnection控件,点击ConnectionString属性,选Use Connection string 下面的例子中...
  • qq173684423
  • qq173684423
  • 2015年04月09日 13:17
  • 2221

Delphi多线程下的ADO编程

前言: 几个月前接到一个任务:将一后台程序访问数据库的方式从BDE改为ADO,原因是由于业务量的增加,通过BDE不论是向数据库写入数据还是从数据库中读出数据的速度都变得无法忍受,大家都知道ADO在数...
  • youthon
  • youthon
  • 2013年05月06日 16:13
  • 3113

Delphi使用ADO连接网络数据库,断网后重连问题

使用TADOConnection对象连接网络数据库(以MySQL为例),当本地网络断开时,连接对象的Connected属性不会发生变化,一直是True。 即使将连接对象的KeepConnection...
  • Trassion
  • Trassion
  • 2013年12月05日 14:23
  • 9407

Delphi使用ADO连接网络数据库,断网后重连问题

使用TADOConnection对象连接网络数据库(以MySQL为例),当本地网络断开时,连接对象的Connected属性不会发生变化,一直是True。 即使将连接对象的KeepConnection属...
  • jhq1990
  • jhq1990
  • 2013年09月16日 16:50
  • 2486

使用原生ADO对数据进行分页显示.rar

  • 2010年08月25日 11:33
  • 267KB
  • 下载

Delphi 7中ADO控件打开Access数据库文件

delphi7中ADO控件打开Access数据库文件最近在学习delphi7编程,尽管已经这门语言已经落寞了,但是作为新手,我目前觉得delphi难度比其他的小,可能与可视化环境有关,尤其很多控件拖拖...
  • shuyaoblog
  • shuyaoblog
  • 2016年01月26日 21:45
  • 1649

delphi ADO连数据库学习实例(初级+高级)

delphi ado 连数据库------初级 1.在窗体上添加ADOConnection,ADOTable,DataSource控件各一个 2.把ADOTable关联到ADOConnectio...
  • sushengmiyan
  • sushengmiyan
  • 2012年03月27日 19:01
  • 4114

开发基于ADO的Delphi数据库应用程序

开发基于ADO的Delphi数据库应用程序时,在组件面板的Data Controls页、ADO页和Data Access页上的组件允许我们的应用程序从数据库中读取和写入信息。       每个数...
  • autumn20080101
  • autumn20080101
  • 2012年04月29日 09:41
  • 474

在Delphi中用ADO连接FoxPro数据库

VisualPro,即VFP,那个小狐狸头,在学校时拿它做数据库理论教育,但自从6.0之后就从未接触它了,听说出在有9.0,但我觉得它的时代已经过去了。例外的是,现在还发现有人用VFP写的应用,还是号...
  • fancy105
  • fancy105
  • 2012年07月21日 12:05
  • 1877
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在Delphi中使用原生ADO控制数据库
举报原因:
原因补充:

(最多只允许输入30个字)