Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1322820
  • 博文数量: 334
  • 博客积分: 10302
  • 博客等级: 上将
  • 技术积分: 2986
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-12 10:17
文章分类

全部博文(334)

文章存档

2013年(1)

2012年(9)

2011年(4)

2010年(10)

2009年(24)

2008年(64)

2007年(72)

2006年(150)

我的朋友

分类:

2006-06-23 00:41:15

标题:Delphi 7.0开发技巧集锦(一)------关于Delphi的BDE作者:  出处:  更新时间: 2004年08月09日 
Delphi 7.0开发技巧集锦(一)
这里为读者提供一些实用的开发技巧和某些常见问题的解决途径。很多程序设计人员都有这样的体会,那就是往往自己冥思苦想某个问题的时候,旁人的一句点拨就可以拨云见日,灵感突现。因此下面以FAQ的形式列举了在开发过程中可能会遇到的问题,以飨读者。
1.1 关于Delphi的BDE
Delphi操作数据库主要是利用BDE来进行。BDE是基于32位Windows内核的数据库引擎和连接工具,支持现有的大多数数据库。它具有如下一些特点:
1. 为多种数据库格式提供统一的应用程序接口,包括任何ODBC数据源。
2. 适应C/S数据库应用的开发,程序设计人员可以访问所有本地和服务端的数据,并且很容易实现应用的向上兼容性。
3. 对于Delphi标准的数据库访问(如Paradox和dBASE),BDE提供的连接方式是最快的。
4. 直接实时的访问数据源。
1.1.1 如何自定义BDE的驱动程序
BDE中按照各个文件的作用可分为以下几部分,这些文件均保存在“…\Program Files\Common Files\Borland Shared\BDE”目录下。
1. 必备文件
Blw32.dll:语言驱动函数库。
Idapi32.dll:BDE基本函数库。
Fareast.bll、Usa.bll:远东语言及美国语言驱动程序,对中文软件不可缺少。
Idr20009.dll:错误信息库。
2. 数据库驱动程序(可选)
Idasci32.dll:Ascii文本数据库驱动程序函数库;
Iddao32.dll:Access数据库驱动程序函数库;
Iddbas32.dll:dBase数据库驱动程序函数库;
Idodbc32.dll:ODBC数据库驱动程序函数库;
Idpdx32.dll:Paradox数据库驱动程序函数库。
3. 其他驱动程序和配置文件(可选)
Idbat32.dll:批操作驱动程序函数库,如果不用TBatchMove组件或DbiBatchMove类函数,可以不要。
Iddr32.dll:Data Repository驱动程序函数库,如果不用Data Repository功能,可以不要。
Idprov32.dll:BDE DataSet provide驱动程序函数库,如果不用TProvider组件,可以不要。
Idqbe32.dll:QBE驱动程序函数库,如果不用Query By Example,可以不要。
Idsql32.dll:SQL查询驱动程序函数库,如果不用TQuery进行查询,可以不要。
Idapi32.cfg:BDE配置文件,如果程序中没有特殊要求,可以不要。也可以在BDE管理器中设置正确后再分发。
4. 其他文件(一般不用)
BDE32.HLP、BDE32.CNT:BDE帮助文件。
BdeAdmin.exe、BdeAdmin.HLP、BdeAdmin.CNT:BDE管理器及帮助文件。
*.BLL:其他国家和地区的语言驱动程序。
DataBump.EXE、DataBump.HLP:数据库数据转移工具及帮助文件。
Localsql.HLP、Localsql.CNT:SQL查询语句帮助文件。
Sqllnk32.HLP、Sqllnk32.CNT:SQL连接帮助文件。
1.1.2 如何注册BDE
安装BDE仅仅复制前面提到的各种文件是不行的,还要等到向注册表注册之后才可以使用。
必需的注册表项目包括:
1. BDE动态链接库文件位置设置(如图1所示)
Key:HKEY_LOCAL_MACHINE\Software\Borland\Database Engine
Item:DLLPATH
Value:BDE动态链接库文件所在位置


图1 BDE动态链接库文件位置设置

2. BDE语言驱动文件路径设置(如图2所示)
Key:HKEY_LOCAL_MACHINE\Software\Borland\BLW32
Item:BLAPIPATH
Value:BDE语言驱动文件所在路径


图2 BDE语言驱动文件路径设置

3. 定义可用的BDE语言驱动文件(如图3所示)
Key:HKEY_LOCAL_MACHINE\Software\Borland\BLW32
Item:LOCALE_LIB#" (#表示数字, 如"LOCALE_LIB1"、"LOCALE_LIB3"等)
Value:指定各BDE语言驱动文件

图3定义可用的BDE语言驱动文件
1.1.3 如何在运行期检测和建立数据库别名
在前面学习的案例中,数据库别名的建立、修改和删除等维护工作,一般在BDE Administrator中进行,并在设计期就已经设置完毕,但这些功能在运行期将如何实现呢?在Delphi的BDE中,当数据库类型为STANDARD时,其别名定义最为简单,但这时仅能使用Paradox,dBASE,ASCIIDRV三种数据库作为默认的驱动程序。另外还需定义数据库存储路径(PATH)和ENABLE BCD,这样才能建立一个完整的数据库别名。
Delphi的数据库应用程序能自动提供一个Session组件,这个Session组件即为应用程序与BDE的接口。
1. 检测别名
通过调用Session.GetAliasNames(list:Tstrings)方法,可将当前BDE配置中的所有数据库别名的名称存放到List字符串列表中。然后调用list.IndexOf(需要检测的别名')函数,该函数的返回值可用来检测数据库别名是否存在(若其值为-1则不存在)。
2. 添加别名
使用Session组件的过程AddStandardAlias(constName,Path,DefaultDriver:string),可以添加一个标准类型的数据库别名。如添加一个数据库别名为NewAlias,其默认数据库驱动程序为Paradox、存储路径为c:\instance1,则可以使用下面的语句。
Session.AddStandardAlias('NewAlias',' c:\instance1','Paradox');
3. BDE配置文件存盘
使用Session.SaveConfigFile语句可将设置信息保存。

一般可以在窗体的OnCreate事件中添加检测和创建数据库别名的程序代码,下面就是一个在运行期实现上述功能的例子。首先单击Delphi工具栏上的“New Form”按钮,新建一窗体,在该窗体上添加一个Table组件,用以提供TSession对象。然后在窗体的OnCreate事件中添加如下所示的代码,程序执行时,系统会首先检测NewAlias别名是否存在,若不存在,提示用户是否创建这个别名,如图4所示。
Procedure TForm1.FormCreate(Sender: TObject);
var
sl:TStringList; //字符串列表变量
re:Integer;
begin
sl:=TStringlist.Create;
Session.GetAliasNames(sl); //取得别名列表
if (sl.IndexOf('NewAlias')=-1) then //判断别名是否存在
begin
re:=Application.MessageBox('别名NewAlias不存在,现在创建吗?','BDE信息窗口',mb_OKCancel);
if re=IDCANCEL then begin
sl.Free;
Exit;
end;
Session.AddStandardAlias('newAlias','c:\instance1','Paradox');
//增加一个名为NewAlias的数据库别名
Session.SaveConfigFile; //保存BDE配置文件
end ;
sl.free;
end;

图4 提示信息
1.1.4 Delphi连接数据库的方式有哪些
---- Delphi访问数据库的方式主要有3种,包括直接访问,如访问标准数据库类型Paradox和dBASE;通过ODBC访问,如访问Access、Foxpro等数据库;通过内嵌(Native)方式访问数据库,如访问SQLServer、Oracle、DB2等。下面以Table组件为例说明这3种方式的特点和用法。
1. 直接访问
----Delphi可以直接访问诸如Paradox和dBASE的标准数据库类型,而不需要什么特别的设置,只需要把文件路径或数据库别名赋值给Table组件的属性DatabaseName就可以访问该路径下的数据表了。
2. 通过ODBC访问
----访问Paradox和dBASED以外的数据库,通常可通过ODBC来实现。Delphi可以访问支持ODBC的数据库系统,如Access、SQLServer和Oracle等。当然,通过ODBC访问数据库时,首先要使用Windows的控制面板或Delphi的数据库引擎建立ODBC数据源。
3. 通过内嵌方式访问
Delphi中还可以不使用ODBC,而以内嵌方式访问SQLServer、Oracle、DB2等数据库系统。这需要使用数据库别名来指定数据库,数据库别名可以事先建立,也可以在程序运行时动态创建。前者称为静态别名,后者称为动态别名。使用数据库别名来访问数据库的方法和使用ODBC数据源的情形相同,这里不再赘述。
通过内嵌方式访问数据库的静态别名必须在BDE中建立。以访问SQLServer数据库为例,在建立别名时必须指定数据库服务器的名称(Servername)、主机名(Hostname)以及要访问的数据库名称(Databasename),可以指定登录用户名(Username)和密码(Password)等。

图5 设置Database组件
通过动态创建的别名来访问数据库必须使用Database组件。用户可以用鼠标双击Database组件,出现参数设置窗口,如图5所示。在“Drivername”一栏选择要访问的数据库系统,如“MSSQL”,然后选择按钮“Defaults”,就会把BDE中该数据库系统所需的参数名称和缺省值加入到“Parameteroverrides”列表中。根据实际情况更改参数中的“Servername”、“Databasename”等项。最后单击OK按钮完成设置。
比较可知,通过内嵌方式访问数据库要比通过ODBC访问数据库速度快一些。而且,内嵌方式可以在程序中动态设置连接数据库所需的参数,用户可不必设置ODBC数据源,从而降低了对用户技术水平的要求,并且减少了用户的工作量。因此从系统配置的难易和复杂程度来看,使用内嵌方式开发出的数据库应用系统更便于普通用户使用。
1.1.5 如何获取BDE的版本信息
单击Delphi工具栏中的“New Form”按钮,新建一窗体。向该窗体中添加1个Memo组件,并设置其Align属性为alclient。在窗体对应的单元文件的USES部分添加dbierrs, DBTables两个引用库文件。在下面的单元文件中,fDbiGetSysVersion函数将返回一个称为SysVersion的结构,并将最后结果显示在窗体的Memo中。
/*该窗体的单元文件代码*/
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,dbierrs, DBTables, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function fDbiGetSysVersion(SysVerList: TStringList): SYSVersion;
var
Month, Day, iHour, iMin, iSec: Word;
Year: SmallInt;
begin
Check(DbiGetSysVersion(Result));
if (SysVerList <> nil) then
begin
with SysVerList do
begin
Clear;
Add(Format('数据引擎版本号=%d', [Result.iVersion]));
Add(Format('接口级=%d', [Result.iIntfLevel]));
Check(DbiDateDecode(Result.dateVer, Month, Day, Year));
Add(Format('版本日期=%s', [DateToStr(EncodeDate(Year, Month, Day))]));
Check(DbiTimeDecode(Result.timeVer, iHour, iMin, iSec));
Add(Format('版本时间=%s', [TimeToStr(EncodeTime(iHour, iMin, iSec div 1000, iSec div 100))]));
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var hStrList: TStringList;
Ver: SYSVersion;
begin
hStrList:= TStringList.Create;
try Ver := fDbiGetSysVersion(hStrList);
except
ShowMessage('BDE not installed !');
end;
Memo1.Lines.Assign(hStrList);
hStrList.Destroy;
end;
end.
按F9键运行程序,将得到如图6所示的BDE版本信息。

图6 运行结果窗口

1.1.6 如何维护DBF数据库
事实上,由于Delphi具有快捷易用、功能强大等优点,使得很多FoxPro和VFP的程序设计人员加入到了Delphi阵营。但在FoxPro和VFP的开发环境下,有许多DBF类型的数据表文件需要移植到Delphi中来,因此在Delphi中如何维护和操作这些数据将是一个很重要的问题。下面阐述在Delphi中完成DBF数据库的如下操作:真正删除记录、显示被删除记录、获取当前记录号和恢复被删除记录.
1. 真正删除记录
在Delphi程序中,使用Table或Query组件的Delete方法执行删除记录操作时,系统执行的是软删除,即相当于Foxpro中的“Set Delete Off”的效果。该方法只是将记录用星号标记为删除,实际并没有进行物理上的删除。要想真正删除记录,需要调用BDE函数DbiPackTable,该函数语法为:
functionDbiPackTable(hDb:hDBIDb;hCursor:hDBICur;pszTableName:PChar;pszDriverType:PChar;bRegenIdxs:Bool):DBIResult;
其中hDb为数据库Databse的句柄,hCursor为数据表Table的句柄,pszTableName为要删除记录的数据表名,pszDriverType为要删除记录的数据表的类型,bRegenIdxs表示是否在删除记录后自动更新索引文件。在四个参数中,hDb不能为NULL。hCursor、pszTableName、pszDriverType可以为NULL,但必须提供足够的信息来标识数据表的文件名和类型,当hCursor不为空时,pszTableName和pszDriverType可以为NULL;当pszTableName为数据表的路径和文件名时,hCursor和pszDriverType可以为NULL。
值得注意的是,在删除记录时,如果用Table来实现,则Table必须以Exclusive=True的方式打开。
2. 显示或不显示软删除记录
当DBF数据库中的记录执行软删除后,默认情况下在DBGrid等数据库显示组件中是看不见这些记录的。可以用BDE函数来控制是否显示DBF数据库中被软删除的记录,如同在Foxpro中利用语句Set Delete ON/OFF开关一样。执行这一功能的函数为DbiSetProp,其语法为:
functionDbiSetProp(hObj:hDBIObj;iProp:Longint;iPropValue:Longint):DBIResult;
该函数用来设置DBI对象中某个属性的值。其中Obj为DBI对象名称,这里为数据表Table的句柄,iProp为属性名,可使用软删除属性curSOFTDELETEON,iPropValue为属性值。
3. 获取当前记录号
在Delphi中可以使用BDE函数获取当前记录在数据集中的记录号.该函数为DbiGetRecord,其语法为:
functionDbiGetRecord(hCursor:hDBICur;eLock:DBILockType;pRecBuff:Pointer;precProps:pRECProps):DBIResult;
该函数用来取得当前记录的一些属性。其中,hCursor为数据集的Handle,eLock为对记录加锁的类型,pRecBuff存放记录的缓冲区,precProps为记录属性集,这里面就包含当前记录的记录号。
4. 恢复软删除记录
在Delphi应用程序中,对DBF数据表执行的删除操作为软删除操作。由于物理记录并没有从数据表中删除,因此可以恢复被软删除的记录,只要去掉删除标志即可。完成这一功能需使用函数DbiUndeleteRecord,其语法为:
functionDbiUndeleteRecord(hCursor:hDBICur):DBIResult;
其中,hCursor可以是数据集的Handle。
1.1.7 如何备份数据表
对于数据库应用来说,数据表的备份应该算是一个常用的功能。下面举一例,介绍其实现过程。单击Delphi工具栏上的“New Form”按钮,新建一窗体,在该窗体上添加1个Table组件、1个DataSource组件、1个DBGrid组件和2个Button组件,设置数据库之间的连接关系,并置Table的Active属性为True。窗体的布局设计如图7所示。

图7 窗体布局示例

然后在“备份表”按钮的OnClick事件中添加代码:
Procedure TForm1.Button1Click(Sender: TObject);
begin
QuickCopyTable(table1,'c:\a.dbf',true);
ShowMessage('数据表备份已完成')
end;
其中所引用的QuickCopyTable方法的代码如下所示。
Procedure QuickCopyTable(T: TTable; DestTblName: string; Overwrite: Boolean);
var
DBType: DBINAME;
WasOpen: Boolean;
NumCopied: Word;
begin
WasOpen := T.Active; //保存表的Active属性值
if not WasOpen then T.Open; //检查表是否打开
Check(DbiGetProp(hDBIObj(T.Handle),drvDRIVERTYPE,@DBType, SizeOf(DBINAME), NumCopied)); //获得驱动程序类型字符串
Check(DBICopyTable(T.DBHandle, Overwrite, PChar(T.Tablename),
DBType, PChar(DestTblName))); //复制表
T.Active := WasOpen; //恢复表的Active属性值
end;
最后,要在单元文件的Uses备份添加dbierrs库文件。此时单击Delphi工具栏上的“Run”按钮或按下F9键,运行程序,单击“备份表”按钮,如图8所示。所备份的数据表a.dbf内容,如图9所示。

图8 运行结果窗口


图9 备份的a.dbf文件的内容
1.1.8 如何使用过滤器
在操作数据库时,经常需要对数据进行筛选过滤。例如在第四章学生学籍管理系统的案例中,有一个名为jiben.dbf的数据表,它具有XH、XM、CSRQ等多个字段,如果只想查看班级编号为001的学生记录,就需要对数据表中的信息进行过滤。下面是常用的对数据表信息进行过滤的方法:
1. 利用TTable和TQuery的Filter属性
n 在设计时设置Filter属性
例如设置Filter为(bjbh=’001’),然后改变Filtered属性为True。此时将只能看到对应的bjbh(班级编号)字段内容为’001’的记录。另外设置Filter时可以使用的操作符有:<、>、<=、>=、=、<>、AND、OR、NOT。
n 在程序运行期间进行动态过滤
要在程序运行时改变Filter属性,包括两种情况。一是操作符右边为常量,例如语句(table1.Filter:='bjbh'+'='+'001';);二是操作符右边不为常量,可能是通过一个变量指定的值,或由一输入框给出的值。此时需要使用Format函数。其代码形式为(Table1.Filter:=Format('bjbh'+'='+'%S',[bjbhvalue]);)其中bjbhvalue为已经赋值的一个字符串变量,也可以为其他形式如Edit1.Text。
2. 用ApplyRange筛选数据集的记录
Delphi的DBDEMOS数据库中有一个Customer.db数据表,如果我们想查看顾客号从1000到3000之间的顾客记录。可使用ApplyRange, SetRangeStart, SetRangeEnd过程来完成,其代码为:
Table1.SetRangeStart;
Table1[‘CustNo’]:=1000;
Table1.SetRangeEnd;
Table1[‘CustNo’]:=3000;
Table1.ApplyRange;
需要说明的是该过程只适用于索引的字段。
3. 用OnFilterRecord事件过滤
例如下面的代码:
Procedure TForm1.Table1FilterRecord(DataSet:TDataSet;varAccept:Boolean);
begin
Accept:=DataSet[‘bjbh’]=’001’;
end;
4. 用Query组件的SQL语句
n SQL语句中不包含变量和参数
Select * from Customer Where CustNo>=1000 and CustNo<=3000
n SQL语句中包含参数
Select * from Customer Where CustNo>=:p1
可在程序中给参数p1赋值,读者可参阅前面讲述的案例程序。
n SQL语句中包含变量
此时向Query组件添加SQL语句的代码如下所示:
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add(Format(‘Select * from Customer’+’’+’where CustNo=’+’%S’, [CustNoValue]));
Query1.Open;
 
 

阅读(7964) | 评论(1) | 转发(0) |
0

上一篇:Error Load MIDAS.DLL

下一篇:好事多磨

给主人留下些什么吧!~~