我发现很多朋友在开发数据库时都使用 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):

constadOpenDynamic = $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;
begintryResult := CreateOleObject('ADODB.Connection');Result.CursorLocation := adUseServer;Result.IsolationLevel := adXactCursorStability;Result.Mode := adModeReadWrite;Result.Provider := 'SQLOLEDB.1';exceptif not VarIsEmpty(Result) then Result := Unassigned;end;
end;procedure FreeConnection(var cnn: OleVariant);
beginif not VarIsEmpty(cnn) thenbeginif cnn.State <> adStateClosed then cnn.Close;cnn := Unassigned;end;
end;function CreateRecordset: OleVariant;
begintryResult := CreateOleObject('ADODB.Recordset');Result.CacheSize := 1000;Result.CursorType := adOpenStatic;Result.CursorLocation := adUseServer;Result.LockType := adLockOptimistic;exceptif not VarIsEmpty(Result) then Result := Unassigned;end;
end;procedure FreeRecordset(var rst: OleVariant);
beginFreeConnection(rst);
end;function CreateCommand: OleVariant;
begintryResult := CreateOleObject('ADODB.Command');Result.CommandType := adCmdText;Result.CommandTimeout := 5;exceptif not VarIsEmpty(Result) then Result := Unassigned;end;
end;procedure FreeCommand(var cmd: OleVariant);
beginif not VarIsEmpty(cmd) then cmd := Unassigned;
end;function ConnectToDB(cnn: OleVariant; const db, host, usr, pwd: string): Boolean;
beginResult := not VarIsEmpty(cnn);if Result thenbeginif 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';trycnn.Open(cnn.ConnectionString, usr, pwd, -1);exceptResult := False;end;end;
end;function ExecSQL(cnn, rst: OleVariant; const sql: string): Boolean;
beginResult := not (VarIsEmpty(cnn) or VarIsEmpty(rst)) and (cnn.State = adStateOpen);if Result thenbeginif rst.State <> adStateClosed then rst.Close;tryrst.Open(sql, cnn, adOpenStatic, adLockOptimistic, adCmdText);exceptResult := False;end;end;
end;function ExecSQLA(cnn, cmd: OleVariant; const sql: string): Boolean;
beginResult := not (VarIsEmpty(cnn) or VarIsEmpty(cmd)) and (cnn.State = adStateOpen);if Result thenbegincnn.BeginTrans;trycmd.ActiveConnection := cnn;cmd.CommandText := sql;cmd.Prepared := True;cmd.Execute;cnn.CommitTrans;exceptcnn.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 的帮助;

四、一些例子

//变量声明
varcnn, rst, cmd: OleVariant;//创建对象
procedure TForm1.FormCreate(Sender: TObject);
begincnn := CreateConnection;rst := CreateRecordset;cmd := CreateCommand;
end;//释放对象
procedure TForm1.FormDestroy(Sender: TObject);
beginFreeCommand(cmd);FreeRecordset(rst);FreeConnection(cnn);
end;//连接数据库
procedure TForm1.Button1Click(Sender: TObject);
beginif ConnectToDB(cnn, 'mydb', '127.0.0.1', 'sa', 'ok') thenCaption := '连接成功'else Caption := '连接失败';
end;//取记录
procedure TForm1.Button2Click(Sender: TObject);
beginExecSQL(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);
varDB, Col: OleVariant;
beginDB := 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);
beginwith ADOCommand1 dobeginCommandText := 'EXEC sp_rename ''' + TableName + '.' + OldColName + ''',''' + NewColName + ''',''COLUMN'';';Excute;end;
end;2、取得 Access 库中的表结构
typeTTableDef = recordName,DateCreated,LastUpdated,Description: string;end;TTableDefs = array of TTableDef;procedure GetTableDefs(const DBName: string; out TableDefs: TTableDefs);
varDBEngine, DB: OleVariant;I: Longint;
begintryDBEngine := CreateOleObject('DAO.DBEngine.36');DB := DBEngine.OpenDatabase(DBName);SetLength(TableDefs, Longint(DB.TableDefs.Count));for I := Low(TableDefs) to High(TableDefs) dobeginTableDefs[I].Name := DB.TableDefs[I].Name;TableDefs[I].DateCreated := DB.TableDefs[I].DateCreated;TableDefs[I].LastUpdated := DB.TableDefs[I].LastUpdated;tryTableDefs[I].Description := DB.TableDefs[I].Properties['Description'].Value;exceptTableDefs[I].Description := '';end;end;finallyDB := Unassigned;DBEngine := Unassigned;end;
end;3、取得 Access 表中的字段结构
typeTFieldDef = recordName: string;Types,Size: Longint;Description: string;end;TFieldDefs = array of TFieldDef;procedure GetFieldDefs(const DBName, TableName: string; out FieldDefs: TFieldDefs);
varDBEngine, DB: OleVariant;I: Longint;
begintryDBEngine := CreateOleObject('DAO.DBEngine.36');DB := DBEngine.OpenDatabase(DBName);SetLength(FieldDefs, Longint(DB.TableDefs[TableName].Fields.Count));for I := Low(FieldDefs) to High(FieldDefs) dobeginFieldDefs[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;tryFieldDefs[I].Description := DB.TableDefs[TableName].Fields[I].Properties['Description'].Value;exceptFieldDefs[I].Description := '';end;end;finallyDB := Unassigned;DBEngine := Unassigned;end;
end;

4、至于如何动态创建 Access 数据库之类我就不罗嗦了,到处都有相关的月经贴

七、其它
1、我使用 ADO 的经历:ADOExpress-->ADOExpress的原生接口-->引用ADO2.1接口单元,即ADODB_TLB-->直接使用 ADO 的 COM 接口;
2、希望此贴能对朋友门有所帮助,我写的这些都是经过实战检验的;
3、觉得有用的朋友可以试一下,如果觉得没用就当我没写,耽误你时间了。

Delphi 原生ADO(二)相关推荐

  1. Linux开发之Delphi FMXLinux(二)、Delphi对Linux操作系统内核态主要的Api封装(FMUX.Api.pas)

    目录 Linux开发之Delphi FMXLinux(二).Delphi对Linux操作系统内核态主要的Api封装(FMUX.Api.pas) 1.代码的版权(比较新的代码库): 2.依赖: 3.其中 ...

  2. iOS原生实现二维码扫描

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

  3. Delphi进行CAD二次开发教学(1)——基础学习:运行、新建、打开图形文件

    http://hi.baidu.com/piaoliuxia/blog/item/d61e03faed3bd18c9f514670.html 查看文章   [原创]Delphi进行CAD二次开发教学( ...

  4. delphi使用ADO在sql数据库存取图片的方法

    delphi使用ADO在sql数据库存取图片的方法 新手参考,老鸟绕行 我一直不认为能把代码写的和天书一样的程序员是好的程序员,那不过是因为我真的对delphi也就是略懂皮毛,太深了看不懂. 网上查询 ...

  5. 在delphi下生成二维码

    在delphi下生成二维码,可以使用TDelphiZXingQRCode,该开源代码地址为:https://github.com/foxitsoftware/DelphiZXingQRCode/tre ...

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

    在form上添加控件 一.方法一: 1.增加一个ADOConnection控件,点击ConnectionString属性,选Use Connection string 下面的例子中要使用ACCESS数 ...

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

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

  8. iOS原生封装二维码、条形码扫描工具;生成、识别(彩色)二维码、条形码图片

    二维码扫描在App中很常见的功能,之前都是用三方工具Zing.ZBar.后来Apple的AVFoundation也支持二维码扫描.生成,而且效率比三方库还要高.我把它封装成一个工具,这样使用起来十分方 ...

  9. Delphi中ADO查询多表更新单表解决方法

    学Delphi也好久了,但一直没怎么总结,这不好久没弄ADO了,趁这个星期一直看公司的代码,自己也来实践一下.以前一直用ADO操作单表,一直没怎么弄过ADO操作多表的程序,不自己实践一下还真不知道操作 ...

最新文章

  1. firefox显示nagios
  2. 【Android 性能优化】布局渲染优化 ( 过渡绘制 | 背景设置产生的过度绘制 | Android 系统的渲染优化 | 自定义布局渲染优化 )
  3. a标签用ajax请求传参,Django中如何实现传参的Ajax请求
  4. 笔记-高项案例题-2017年下-整体管理-变更管理
  5. html ondrop未触发,javascript – TableDnD onDrop事件未触发
  6. Django syncdb mysql error on localhost - (1045, Access denied for user 'ODBC'@'
  7. eclipse添加maven配置
  8. java的this()与super()用法
  9. 伯克利推出世界最快的KVS数据库Anna:秒杀Redis和Cassandra
  10. Java中异常处理和设计
  11. 贵州省谷歌地球高程DEM等高线下载
  12. 连接打印机错误0x000000bcb解决方法
  13. sae nodejs mysql_通过新浪云部署NideShop微信小程序商城(基于Node.js+MySQL+ThinkJS)
  14. 关于NXP公司的IMX6系列芯片参考资料体系介绍
  15. python合并单元格的快捷键是什么_【答疑】wps word表格如何合并单元格,快捷键是什么? - 羽兔网问答...
  16. 计算机图形学 :中点画圆法
  17. 迁移过程中出现报错:无法解析的成员访问表达式[USERENV]
  18. 对于微信支付宝支付的总结
  19. Oracle Livelabs实验: Setting Up Active Data Guard For On-Premises
  20. vscode 实现在行尾加分号

热门文章

  1. 一个“人工智能Python机器学习与深度学习”课程表
  2. 2021年春季学期-信号与系统-第二次作业参考答案-第一小题
  3. 5V蜂鸣器内部工作原理
  4. 后浪们 : 难道要先结婚后恋爱?
  5. 广义互相关计算TDOA
  6. DAC8830可以当做电位器来使用吗?
  7. 基于STM32F103RE ADDA板制作
  8. oracle显示当天日期函数,oracle日期函数
  9. 摄像头自建html直播,html5调用摄像头实现拍照
  10. chrome正受到自动软件的控制_谷歌优化Chrome Omnibox自动完成功能 使其更加智能