我发现很多朋友在开发数据库时都使用 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 = $;
adOpenStatic = $; adLockOptimistic = $;
adLockBatchOptimistic = $; adStateClosed = $;
adStateOpen = $;
adStateConnecting = $;
adStateExecuting = $;
adStateFetching = $; adUseServer = $;
adUseClient = $; adModeReadWrite = $; adXactCursorStability = $; adCmdText = $;
adCmdTable = $;
adCmdStoredProc = $;
adCmdFile = $; adAffectCurrent = $;
adAffectGroup = $;
adAffectAll = $;
adAffectAllChapters = $; 、一些基本函数和过程
//创建 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 := ;
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 := ;
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, -);
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; 、取得 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; 、取得 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、觉得有用的朋友可以试一下,如果觉得没用就当我没写,耽误你时间了。

Delphi 原生ADO(二)的更多相关文章

  1. delphi实现ado的高级功能

    ADO是Microsoft存取通用数据源的标准引擎.ADO通过封装OLE DB而能够存取不同类型的数据,让应用程序能很方便地通过统一的接口处理各种数据库.ADO由一组COM对象组成,每一个不同的原生A ...

  2. Delphi通过ADO读写数据库

    ADO是一种程序对象,用于表示用户数据库中的数据结构和所包含的数据. ADO (ActiveX Data Objects,ActiveX数据对象)是Microsoft提出的应用程序接口(API)用以实 ...

  3. iOS学习——iOS原生实现二维码扫描

    最近项目上需要开发扫描二维码进行签到的功能,主要用于开会签到的场景,所以为了避免作弊,我们再开发时只采用直接扫描的方式,并且要屏蔽从相册读取图片,此外还在二维码扫描成功签到时后台会自动上传用户的当前地 ...

  4. 升讯威ADO.NET增强组件(源码):送给喜欢原生ADO.NET的你

    目前我们所接触到的许多项目开发,大多数都应用了 ORM 技术来实现与数据库的交互,ORM 虽然有诸多好处,但是在实际工作中,特别是在大型项目开发中,容易发现 ORM 存在一些缺点,在复杂场景下,反而容 ...

  5. Delphi中ADO异步执行方式

    当ADO开始处理数据后,应用程序必须等到ADO处理完毕之后才可以继续执行.但是除了同步执行方式之外,ADO也提供了异步执行的方式,允许当ADO处理时,应用程序仍然能够先继续执行.而当ADO处理数据完毕 ...

  6. Delphi使用ADO进行数据库编程

    Delphi是一个可视化的编程工具,ADO编程也是这样,所以话不多言,直接通过代码.截图和语言来说明. 我的数据库是Oracle,为了测试,先建一个表:create table practice(un ...

  7. iOS原生实现二维码拉近放大

    http://www.cocoachina.com/ios/20180416/23033.html 2018-04-16 15:34 编辑: yyuuzhu 分类:iOS开发 来源:程序鹅 8 300 ...

  8. delphi 原生 ADODB.recordset

    ADODB.recordset ..\source\rtl\win\Winapi.ADOInt.pas..\17.0\OCX\Servers\ADODB2010.pasCLASS_Recordset: ...

  9. delphi 基础之二 面向对象概念初步

    面向对象概念初步 •类自动生成 快捷键:ctrl+shift+c 1.类的定义 类是用户创建的数据类型,包括状态.表达式和一些操作.有3个组成部分,即字段.方法和属性.字段是类的内部数据变量,方法就是 ...

随机推荐

  1. jquery实现全选、不选、反选的两种方法

    在取复选框checkbox的属性checked属性值时,发现一个问题,就是当用attr取值时,真的为"checked",假的为"undefined";当用pro ...

  2. SVN提交出错--URL access forbidden for unknown reason

    使用SVN在eclipse中提交文件,但是出现错误,如下: URL access forbidden for unknown reasonsvn: Commit failed (details fol ...

  3. 20165210 Java第四次实验报告

    20165210 实验四 Android程序设计 实验步骤 第24章:初识Android 任务一:完成Hello World, 要求修改res目录中的内容,Hello World后要显示自己的学号 学 ...

  4. PostgreSQL EXPLAIN执行计划学习--多表连接几种Join方式比较

    转了一部分.稍后再修改. 三种多表Join的算法: 一. NESTED LOOP: 对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择.在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表 ...

  5. 阿里maven镜像服务器配置

    把下面的配置复制到 .m2/settings.xml配置文件中. <?xml version="1.0" encoding="UTF-8"?> &l ...

  6. Scikit-Learn:开源的机器学习Python模块(转载)

    摘要: scikit-learn是一个用于机器学习的Python模块,其具有操作简单.效率高.无访问限制.BSD开源协议等等特征,在机器学习这一块是比较受欢迎的. scikit-learn是一个用于机 ...

  7. LINUX下的ssh登录之后的文件远程copy:scp命令(接前文ssh登录)

    先记录参考: 1:http://www.cnblogs.com/peida/archive/2013/03/15/2960802.html 2:http://www.vpser.net/manage/ ...

  8. vim编辑器安装命令使用命令和设置的使用总结

    vim编辑器的安装 vi(vim)是上Linux非常常用的编辑器,很多Linux发行版都默认安装了vi(vim).vi(vim)命令繁多但是如果使用灵活之后将会大大提高效率.本文讲解主要是在Cento ...

  9. 一般在cmd中报不是合法的命令啥的,都是环境变量没有配置好

    在配置cnpm的时候一定要将环境变量先配置好,配置如下: C:\Program Files\nodejs; C:\Program Files\nodejs\node_global; C:\Progra ...

  10. C语言词法分析:C#源码

    今天继续研究代码解析的算法 这个是算法流程图 有图解可能更直观一点: 以下是c#源码:   1using System;   2using System.IO;   3using System.Tex ...