Delphi 原生ADO(二)
我发现很多朋友在开发数据库时都使用 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(二)相关推荐
- Linux开发之Delphi FMXLinux(二)、Delphi对Linux操作系统内核态主要的Api封装(FMUX.Api.pas)
目录 Linux开发之Delphi FMXLinux(二).Delphi对Linux操作系统内核态主要的Api封装(FMUX.Api.pas) 1.代码的版权(比较新的代码库): 2.依赖: 3.其中 ...
- iOS原生实现二维码扫描
iOS原生实现二维码扫描 最近项目上需要开发扫描二维码进行签到的功能,主要用于开会签到的场景,所以为了避免作弊,我们再开发时只采用直接扫描的方式,并且要屏蔽从相册读取图片,此外还在二维码扫描成功签到时 ...
- Delphi进行CAD二次开发教学(1)——基础学习:运行、新建、打开图形文件
http://hi.baidu.com/piaoliuxia/blog/item/d61e03faed3bd18c9f514670.html 查看文章 [原创]Delphi进行CAD二次开发教学( ...
- delphi使用ADO在sql数据库存取图片的方法
delphi使用ADO在sql数据库存取图片的方法 新手参考,老鸟绕行 我一直不认为能把代码写的和天书一样的程序员是好的程序员,那不过是因为我真的对delphi也就是略懂皮毛,太深了看不懂. 网上查询 ...
- 在delphi下生成二维码
在delphi下生成二维码,可以使用TDelphiZXingQRCode,该开源代码地址为:https://github.com/foxitsoftware/DelphiZXingQRCode/tre ...
- Delphi使用ADO组件访问ACCESS数据入门例程
在form上添加控件 一.方法一: 1.增加一个ADOConnection控件,点击ConnectionString属性,选Use Connection string 下面的例子中要使用ACCESS数 ...
- iOS原生实现二维码拉近放大
http://www.cocoachina.com/ios/20180416/23033.html 2018-04-16 15:34 编辑: yyuuzhu 分类:iOS开发 来源:程序鹅 8 300 ...
- iOS原生封装二维码、条形码扫描工具;生成、识别(彩色)二维码、条形码图片
二维码扫描在App中很常见的功能,之前都是用三方工具Zing.ZBar.后来Apple的AVFoundation也支持二维码扫描.生成,而且效率比三方库还要高.我把它封装成一个工具,这样使用起来十分方 ...
- Delphi中ADO查询多表更新单表解决方法
学Delphi也好久了,但一直没怎么总结,这不好久没弄ADO了,趁这个星期一直看公司的代码,自己也来实践一下.以前一直用ADO操作单表,一直没怎么弄过ADO操作多表的程序,不自己实践一下还真不知道操作 ...
最新文章
- firefox显示nagios
- 【Android 性能优化】布局渲染优化 ( 过渡绘制 | 背景设置产生的过度绘制 | Android 系统的渲染优化 | 自定义布局渲染优化 )
- a标签用ajax请求传参,Django中如何实现传参的Ajax请求
- 笔记-高项案例题-2017年下-整体管理-变更管理
- html ondrop未触发,javascript – TableDnD onDrop事件未触发
- Django syncdb mysql error on localhost - (1045, Access denied for user 'ODBC'@'
- eclipse添加maven配置
- java的this()与super()用法
- 伯克利推出世界最快的KVS数据库Anna:秒杀Redis和Cassandra
- Java中异常处理和设计
- 贵州省谷歌地球高程DEM等高线下载
- 连接打印机错误0x000000bcb解决方法
- sae nodejs mysql_通过新浪云部署NideShop微信小程序商城(基于Node.js+MySQL+ThinkJS)
- 关于NXP公司的IMX6系列芯片参考资料体系介绍
- python合并单元格的快捷键是什么_【答疑】wps word表格如何合并单元格,快捷键是什么? - 羽兔网问答...
- 计算机图形学 :中点画圆法
- 迁移过程中出现报错:无法解析的成员访问表达式[USERENV]
- 对于微信支付宝支付的总结
- Oracle Livelabs实验: Setting Up Active Data Guard For On-Premises
- vscode 实现在行尾加分号