利用GotoNearest方法执行不精确查找
窗体中的 不精确查找 按钮的事件处理过程代码如下
procedure TForm Button Click(Sender: TObject)
begin
with table do
begin
IndexFieldNames:= Company ;
setkey;
FieldByName( Company ) AsString:=Edit text;
GotoNearest;
label caption:=FieldByName( Company ) AsString;
end;
end;
读者可以利用 FindNearest 方法执行上面的不精确查找 具体使用方法可以参看Findkey方法的使用
在上面的例子中要设置table 的IndexFieldNames属性为Company
GotoNearest方法进行不精确查找
修改数据库中的记录
我们掌握了字段对象的概念和如何查找数据库中的记录之后 下面我便可以很方便地修改数据库中现存的记录了 一般来说 在程序中修改数据库中的记录包括下面这些步骤
在数据库中找到要修改的记录 并将记录指针移至该记录
调用Edit方法将与数据库表相连的TTable部件设置成编辑状态
修改一个或多个字段
调用post方法将修改后的记录写入数据库
以上这几个步骤只是概述性的 具体实现时还有很多细节需要留心 我们通过一个例子来演示上面的全过程 以便让读者进一步地了解和掌握修改记录的方法
例 我们为四个按钮分别编写了事件处理过程 用来遍历数据库中的记录并对每个客户记录的Company字段进行修改 在程序对记录进行更新 *** 作时窗口中的控件都是无效的 在这个例子中我们还编写了一个简单的异常代码块用来确保在更新过程中出现异常时使控件恢复正常 *** 作
修改数据库记录
Edit方法Post方法
为了能让用户通过程序修改数据库表中的记录 TTable部件必须要处在编辑状态下 在大多数情况下 数据库表都是以浏览(只读方式)方式打开的 也就是说它的每一个字段可以被读取介不能被编辑修改 调用Edit 方法能够将 TTable 部件置成编辑状态 当TTable部件处于编辑状态后 我们才可以通过程序修改当前记录指针所指向的记录 但这样修改后的记录不会立即被写入到磁盘上的实际数据库表中 要想保存对记录的修改 必须要调用Post方法 Post方法才真正将我们对记录的修改写入实际的数据库表中
一般来说 用来扫描整个数据库表并修改每个记录的某一个字段的程序如下所示
with Table Do
begin
DisableControls;{在修改记录的过程中 使其它部件无效}
First; {将记录指针指向第一条记录}
while not EOF do
begin
<读取记录的一个字段值到一个变量中>
<做适当的修改>
Edit; {将TTable部件置成编辑状态}
<将修改后的字段值写回到其对应的字段>
post; {将修改后的记录写回数据库}
next; {修改下一条记录}
end;
enablecontrols; {恢复其它部件的功能}
end;
程序都是对TTable部件进行 *** 作 因此使用With语句来防止错误的扩散是很有意义的 在这里要注意Disablecontrols方法和EnableControls方法的使用 DisableControls方法是在程序修改TTable部件中的记录时 切断TTable部件与数据访问部件TDatasource 部件的联系 否则 在对TTable中的每一修改之后 TDataSource 部件都会更新窗体中所有数据浏览部件的显示内容 这样会急剧减慢处理过程而且浪费时间 EnableControls方法是与DisableControle方法执行相反的 *** 作 它是用来恢复TTable部件与TDatasource部件的联系并促使所有的数据浏览部件更新显示
调用First方法是将记录指针移到数据库表中的第一条记录 确保程序从表中的第一条记录开始进行修改 调用Next方法是将记录指针从当前的记录移到下一条记录 这样保证了从表中的第一条记录开始逐条记录进行修改 直到修改完最后一条记录 如果不调用Next方法 程序将会陷入无穷的死循环
实现异常保护的TRY…FINALLY语句
上面的程序存在着潜在的危险 在实际应用过程中 可能因为某些原因使得对数据库表的更新不能进行下去 如当程序试图执行Post方法将修改后的记录写回磁盘时 而又因为某种原因磁盘没有准备好 这时便出现了异常 当出现异常时 应用程序会暂停下来并且会d出一对话框显示有关的错误信息 在用户单击错误信息对话框之后 程序将继续执行到某一个地方去 而这个地方常常不是用户所能预料到的 在我们的程序中 在执行Post方法之前 窗体中所有的部件与TTable部件都已失去联系 因此 这种异常将导致窗体中显示的数据和数据库无关
Object Pascal中的Try…Finally语句为我们解决上述异常问题提供了一个解决方法 在Delphi中仍然采用了这一语句用来处理异常问题 实际上 Try…Finally 语句是把两组语句组合在一起 语句的Try部分包含了可能产生异常的程序代码 Finally部分包含了即使发生了异常也必须执行的一条或多条语句 在本例中 Finally 部分只包含了EnableControls方法调用这一条语句 我们将前面的代码改写并组合进Try…Finally 语句
with Table Do
begin
DisableControls;{在修改记录的过程中 使其它部件无效}
Try;
First; {将记录指针指向第一条记录}
while not EOF do
begin
<读取记录的一个字段值到一个变量中>
<做适当的修改>
Edit; {将TTable部件置成编辑状态}
<将修改后的字段值写回到其对应的字段>
post; {将修改后的记录写回数据库}
next; {修改下一条记录}
end;
enablecontrols;
Finally;{出现异常时 执行下面的程序}
enablecontrols; {恢复其它部件的功能}
end; {结束Try…Finally语句}
end;
在保留字Try和Finally之间的代码跟前面的代码是一样的 它们用于在记录之间移动记录指针并处理对记录的修改 这一段代码可能会出现异常 当异常发生时 我们想保证执行EnableControls 以便窗体中各控件恢复与 TTable 部件的联系 因此我们必须将EnableControls语句放在Finally和结束语句End之间
在这里要特别注意 请读者们不要混淆了Try…Finally语句和Try…Except 语句 如果真正想在发生异常时采取相应的处理 就要使用Try…Except语句 Try… Finally语句只是用来处理当异常出现时 使应用程序执行Finally部分的语句 使程序继续执行下去 Try…Except语句是实现异常处理 Try…Finally语句是实现异常保护
有了上述这些概念 我们便可以提供这个例子的一些程序代码 它涉及了所有这些内容
lishixinzhi/Article/program/Delphi/201311/25167
在TDBGrid部件中显示数据库表中的记录信息时 如果TDBGrid使用数据集部件在运行过程中动态生成的字段部件时 TDBGrid显示数据库表中的记录是按表中记录的缺省顺序和字段的缺省顺序显示表中的记录信息 而且要显示表中各个记录的全部字段的值 而在大多数情况下 用户可能希望按自己喜欢的字段顺序显示记录的各个字段 有时还希望只显示记录的部分字段值 要达到这一目的 必须在设计阶段使用字段编辑器来创建永久性的字段部件 并且还要设置各个字段部件有关的属性
当使用字段编辑器(Fields Editor)创建永久性的字段部件提供给TDBGrid部件来使用时 我们可以在TDBGrid部件中更灵活地显示数据库表中的记录信息 例如在字段编辑器中的Fields列表框中我们可以设定字段部件的显示顺序 在设定好字段的显示顺序之后 TDBGrid部件便按这个顺序显示记录的各个字段值 当我们设置字段部件的DisplayFormat和EditFormat属性之后 在TDBGrid部件中便相应地以设定的显式和编辑格式显示字段值和编辑字段值 当设置某一个字段部件的Required属性为True时 当插入一条新记录时 必须要为该字段输入相应的字段值 否则会出错 通过设置字段部件的Visible属性 可以确定相应的字段值是否在TDBGrid组件中显示 有关使用字段编辑器来创建字段部件 设置字段部件的属性请参看 节
TDBGrid部件的主要属性及应用
TDBGrid部件是用于显示和编辑数据库表中的记录信息的重要部件 它是我们在程序设计过程当中要经常使用的 灵活地用于显示和编辑数据库表中的记录信息的一个强有力的工具 TDBGrid具有很多重要的属性 我们可以在程序设计阶段和程序运行过程中进行设置 TDBGrid部件的一些重要属性及其设置方法请参看联机帮助文件 TDBGrid部件中一些重要的属性是Option属性 DrawMode属性和DefaultDrawing属性 我们重点对两个属性进行阐述
Options属性 它是TDBGrid部件的一个扩展属性 在程序设计阶段设置Options属性可以控制TDBGrid部件的显示特性和对事件的响应特性 Options属性在TDBGrid部件的属性栏中显示时 它的前面带有一个 + 标志 双击 + 标志 便可以展开一个布尔型属性列表 用户可以逐个地修改其中的各个属性值 修改完毕后可以双击Options属性前的 标志 使TDBGrid部件的属性列表恢复到原来的显示状态
表 列出了Options属性中包含的所有的扩展属性项以及它们对TDBGrid部件的影响
表 TDBGrid部件的Options属性中的扩展属性项
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
属 性 名 取 值 及 影 响
─────────────────────────────────
dbEditing True: 缺省情况下为此值 确保用户能够在网格中编辑插入和删除数据库表中的记录
False:在网格中不能编辑 插入和删除表中的记录
─────────────────────────────────
dbAlwaysShow True: 当用户选中记录中的一个字段时 自动地使该字段
Editor 处于编辑状态
False:缺省情况下为此值 当一个字段被选中 它不能自动地变成编辑状态
─────────────────────────────────
dgTitles True: 缺省情况下为此值 在网格的第一行中显示字段名或字段标题
False:在网格中不显示字段名或字段对应的标题
─────────────────────────────────
dgIndicator True: 缺省情况下为此值 在网格的最左边用一个黑箭头标注当前记录指针所在的位置 在插入状态时 箭头变成星状 在编辑状时 箭头变成 I 头
False:在网格中不标识当前记录指针的位置
─────────────────────────────────
dgColumnResize True: 缺省情况下为此值 通过拖拉网格的垂直分隔线可以改变网格中各列的宽度 在具体 *** 作时要拖拉各列中显示字段标题区域中的垂直分隔线
False:网格中各列的宽度不能改变
─────────────────────────────────
dgCloLines True: 缺省情况下为此值 在网格中显示各列之间的垂直分隔线
False:在网格中不显示垂直分隔线
─────────────────────────────────
dgRowLines True: 缺省情况下为此值 在网格中显示各行之间的水平分隔线
False:在网格中不显示水平分隔线
─────────────────────────────────
dgTabs True: 缺省情况下为此值 可以在记录的各字段之间移动输入焦点(也即选择提示棒)
False:不能在记录的名字段之间移动输入焦点 在网格中按Tab键时 直接跳出网格
─────────────────────────────────
dgRowSelect True: 选择提示棒覆盖整条记录中的全部字段False:缺省情况下为此值 选择提示棒一次只覆盖记录中的一个字段
─────────────────────────────────
dgAlwaysShow True: 缺省情况下为此值 在网格始终显示选择提示棒 即
Selection 使其控件获得焦点时 也是如此
False:只在当网格获得焦点时 才显示选择提示棒
─────────────────────────────────
dbConfirmDelete True: 缺省情况下为此值 当在网格中删除记录时 d出确认信息
False:在网格中删除记录时不d出确认信息
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
用户想了解这些可选属性项的作用和影响 还可以参看联机帮助信息
DragMode属性 该属性有两个可选的属性值 当它的值被设置为dmManual时 在应用程序运行过程中 用户可以用鼠标拖放网格中的各列 改变各列在网格中的显示顺序和位置 当用鼠标拖放网格中的一列 改变它在网格中的位置时 只是改变了该列在数据集中的位置 并没有改变它对应的数据库表中的位置 当该属性的值被设置成dmAutomatic时 用户不能用鼠标拖放网格中的各列而改变它在网格中的位置
DefalultDrawing属性 该属性是布尔型属性 它用于控制网格中各网格单元的绘制方式 在缺省情况下 该属性的值为True 也就是说Delphi使用网格本身缺省的方法绘制网格中各网格单元 并填充各网格单元中的内容 各网格单元中的数据根据其对应的字段部件的DisplayFormat属性和EidtFormat属性进行显示和绘制 如果DefaulDrawing属性被设置为False时 Delphi不会自动地绘制网格中各网格单元和网格单元中的数据 用户必须自己为TDBGrid部件的OnDrawDataCell事件编写相应的程序用于绘制各网格单元和其中的数据
在了解了TDBGrid部件的各个属性之后 我们便可以使用TDBGrid部件来显示和编辑数据库表中的数据了 图 所示的应用窗体中各部件的属性设置如表 所示
lishixinzhi/Article/program/Delphi/201311/25148
在数据库应用程序中 数据控件是经常要用到的 数据控件都是可视的 也就是说 如果修改了这些构件的属性 能在窗体上马上反映出来 如果这些构件的Enabled属性设为True并且数据集的Active属性也设为True 在设计期就可以看到数据
下面就来介绍一下这些控件的简单应用
指定一个数据源
数据控件必须通过TDataSource构件连接数据集 TDataSource构件扮演的角色实际上就是数据控件与数据集之间的桥梁 首先 把一个数据集构件放到窗体或数据模块上 设置它的DatabaseName属性指定要访问的数据库 设置它的TableName属性指定要访问的表 接着 把一个TDataSource构件放到窗体或数据模块上 设置它的DataSet属性指定数据集 然后 把一个数据控件放到窗体上 设置它的DataSource属性指定TDataSource构件 而这个TDataSource构件的DataSet属性已经指定了一个数据集 最后 设置数据控件的DataField属性指定要显示的字段 不过 对于TDBGrid TDBCtrlGrid和TDBNavigator构件来说 不需要设置DataField属性 因为这几个控件是以整个数据集为工作内容的
编辑和更新数据
除了TDBNavigator构件外 其他数据控件都是用来显示和编辑数据的 这里要介绍怎样编辑数据
要使用户能编辑数据 数据集必须进入dsEdit状态 如果TDataSource的AutoEdit属性设为False 用户不能直接编辑数据 除非程序调用Edit函数
要使用户能够在数据控件中修改数据 必须把数据控件的ReadOnly属性设为False 如果ReadOnly属性设为True 数据控件中显示的数据就是只读的 一般情况下 TDataSource构件的Enabled属性设为True 如果这个属性设为False 数据控件就无法显示数据 更不能修改数据
如果数据集构件的ReadOnly属性设为True 数据集就是只读的 用户在数据控件中所作的修改不能写到数据集中 除了TDBGrid构件外 当用户修改了一个字段的值 还需要把输入焦点移走 新的数据才写到数据集中 在移走输入焦点之前 用户随时可以按ESC键取消修改 在TDBGrid构件建立的栅格中 当用户修改了一个字段的值 还需要把输入焦点移到另一条记录上 新的数据才写到数据集中
禁止和允许数据刷新
当程序正在遍历整个数据集或者搜索一个特定的记录时 应当暂时禁止数据控件刷新数据 这样能加快遍历或搜索的速度 防止屏幕总是在闪烁 调用数据集的DisableControls可以暂时禁止连接这个数据集的数据控件刷新数据 DisableControls函数通常在循环 *** 作前调用 等循环结束后 程序应当立即调用数据集构件的EnableControls函数重新允许刷新数据 为了确保最后总是能恢复刷新 建议采用Try Finally结构 这样 即使在循环中出现异常 也可以保证总能调用EnableControls
下面的代码演示了怎样调用DisableControls和EnableControls函数
CustTable DisableControls;TryCustTable First;While not CustTable EOF DoBegin CustTable Next;End;FinallyCustTable EnableControls;End;
手动刷新数据
调用数据集的Refresh可以读取数据集中最新的数据并刷新数据控件 这个功能在多用户环境尤其有用 因为其他用户有可能已改变了数据集中的数据 有时候 调用Refresh可能会导致意想不到的结果 例如 如果另一个用户已经删除了一条记录 调用Refresh后 这条记录将从数据控件中消失
显示单个字段的数据控件
有的数据控件以数据库的一个或几个字段作为工作内容 如TDBText和TDBEdit 而有的数据控件以整个数据集为工作内容 如TDBGrid和TDBNavigator 显示单个字段的数据控件往往是从一个标准的Windows控件演化而来的 例如 TDBEdit构件就可以认为是TEdit的数据感知版本
把数据作为标签显示
TDBText构件是一个只读的数据控件 它非常类似于TLabel构件和TStaticText构件 TDBText构件能够把数据作为标签显示 用来标注其他控件 例如 可以用一个TDBText构件显示名称(Common_Name字段)
TDBText构件需要指定一个字段 当用户使用导航器或其他手段浏览记录时 TDBText构件显示的数据将自动变化 因为TDBText构件总是显示当前记录的数据
TDBText构件的AutoSize属性一般要设为True 这是因为字段的内容长度可能是不同的 如果AutoSize属性设为False 有些较长的内容可能会被截断
显示和编辑数据
TDBText构件只能显示数据 不能编辑数据 要既能显示数据 又能编辑数据 就要用到TDBEdit构件 TDBEdit可以认为是TEdit的数据感知(Data Aware)版本 例如 有一个TDataSource构件叫CustomersSource 它的DataSet属性指向一个TTable构件叫CustomersTable 把一个TDBEdit构件放在窗体上 其DataSource属性设为CustomersSource 把它的DataField属性设为CustNo 这个TDBEdit构件马上就能显示CustNo字段的值 用户可以在编辑框中键入新的值
显示和编辑多行文本
TDBMemo构件是TMemo构件的数据感知版本 可以显示dBASE和Paradox数据库中备注字段的内容
与TDBEdit不同的是 TDBMemo能够以多行的形式显示文本 同时也允许用户键入多行文本
默认情况下 TDBMemo允许用户修改它显示的文本 如果不想让用户修改文本 只要把ReadOnly属性设为True即可
要允许用户在文本中插入一个制表符 应当把WantTabs属性设为True 否则 当用户按下Tab键 将把输入焦点移走 而不是插入制表符 要限制用户最多可输入的字符数 可以设置MaxLength属性 如果这个属性设为 表示没有限制
此外 ScrollBars属性可以设置要不要加上滚动栏 WordWrap属性可以设置是否允许自动绕回 Alignment属性可以设置文本的对齐方式 在运行期 您可以调用CutToClipboard和CopyToClipboard函数把选择的文本剪切和复制到剪贴板中 调用PasteFromClipboard能够粘贴剪贴板中的文本
lishixinzhi/Article/program/Delphi/201311/8453
数据集部件的事件
数据集部件TTable或TQuery具有很多的事件 为这些事件编写相应的程序代码可以进行有效性验证 计算可计算字段的值 确认对数据库表的多种 *** 作等等 这些事件及其描述如表 所示
表 数据集部件常用的事件
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
事 件 描 述
───────────────────────────────────
BeforeOpen Afteropen 在数据集部件被打开之前/之后被触发
───────────────────────────────────
BeforeClose Afterclose 在数据集部件被关闭之前/之后被触发
───────────────────────────────────
BeforeInsert AfterInsert 在数据集部件进入插入状态之前/之后被触发
───────────────────────────────────
BeforeEdit AfterEdit 在数据集部件被编辑之前/之后被触发
───────────────────────────────────
BeforePost AfterPost 在数据集部件投寄被修改的记录之前/之后被触发
───────────────────────────────────
BeforeCancel AfterCancel 在数据集部件取消前一步 *** 作之前/之后被触发
───────────────────────────────────
BeforeDelete AfterDelete 在数据集部件删除当前记录之前/之后被触发
───────────────────────────────────
OnNewRecord 当建立一条新记录时被触发
───────────────────────────────────
OnCalcFields 当为表中的计算字段计算字段值时被触发
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TTable部件及应用
在前一节里我们介绍了数据集部件TTable 和TQuery 的共同的一些属性和方法 TTable部件是Delphi数据库编程中要经常使用的最重要的部件之一 它是数据库应用程序访问数据库时必须使用的数据集部件之一 在这一节里 我们重点介绍TTable部件特有的属性和方法 TTable部件所有的属性 方法和事件都可以在联机帮助中查到
TTabel部件主要的属性
DatabaseName属性和TableName属性
DatabaseName属性是说明数据库应用程序所 *** 作的数据库的名字 它可以是由BDE定义的数据库的别名 显式说明的数据库文件所在的磁盘路径或者由TDatabase部件定义的一个数据库名 DatabaseName属性常常是一个由BDE定义的数据库的别名 使用由BDE定义的数据库的别名代替数据库实际所在的路径和名字 好处是当实际的数据库存放的位置发生变化时 只需利用BDE简单地设置一下该数据库的别名 而数据库应用程序无需修改 有关BDE的使用请参看BDE的设置应用 TabelName属性用以说明当前TTable部件所连接的实际的数据库表 这两个属性一般都在设计阶段指定 当然在程序运行过程中也可以设置 但是要修改这两个属性时 必须要在TTabel的Active属性为False时进行 当TTable的Active属性为True时 这两个属性是不能被修改和设置的
TableType属性
该属性说明与TTable部件相连接的数据库表的类型 当TableType属性设置成Default时 该属性所说明的数据库表的类型由数据库文件的扩展名决定
● 若数据库文件的扩展名为 DB或没有扩展名 表的类型是Paradox表
● 若数据库文件的扩展名为 DBF时 表的类型是dBASE表
● 若数据库文件的扩展名为 TXT时 表的类型是ASCII表
如果TableType属性不设定为Default 那么与TTable 部件相连的数据库表的类型由TableType中的设置的值决定 不用考虑数据库文件的扩展名
KeyExclusive属性
该属性的一个作用是说明在数据库表中查找记录时 将记录移到与查找值相匹配的记录处还是将记录指针移到与查找值相匹配的记录后面一条记录处 该属性是布尔型变量 当它的值为False时(缺省情况下为False) 将记录指针移到相匹配的记录处 为True时 将记录指针移到相匹配记录的后面一条记录处 该属性另一个作用是在表中指定检索范围时 用来说明是否包括满足过滤条件的边界记录 当KeyExclusive的值为False时 检索范围包括边界记录 否则不包括边界记录 有关详细的 *** 作请参看 限定表中记录的检索范围
IndexFields属性和IndexFieldsCount属性
IndexFields的属性值是数据库表中字段名列表 它包含与TTable部件相连的数据库表中的全部索引字希 IndexFieldsCount属性说明表中索引字段的个数 这两个属性值都是只读的 只有在程序运行过程中可用
IndexName属性和IndexFieldNames属性
IndexName属性中存放著在建立数据库表时为数据库表定义的所有辅助索引名 它是一个辅助索引名列表 是只读属性 IndexFieldNames属性指定用于数据库表索引排序的字段名 多个字段名之间用分号隔开 例如对Customer DB表中的客户记录按邮政编码ZipCode和客户号码CustNo排序时可以设定IndexFieldNames的值为
ZipCode ; CustNo
在IndexFieldNames属性中指定的字段必须存在于相应的数据库表中 否则会导致错误 IndexName和IndexFieldName是互斥的 每次只能指定其中一个属性的值 不能同时为两个属性都指定属性值
lishixinzhi/Article/program/Delphi/201311/25157
GetDatabaseNames方法
声明 procedure GetDatabaseNames(List: TStrings)
GetDatabaseNames方法清除List的内容并将所有BDE别名和应用程序定义的别名的名字写入List
GetDriverNames方法
声明 procedure GetDriverNames(List: TStrings)
GetDriverNames方法清除List中的内容 并将BDE当前安装的驱动程序名写入List
GetDriverParams方法
声明 procedure GetDriverParams(const DriverName: String; List: TStrings)
GetDriverParams方法消除List中的内容 并将名为DriveName驱动程序缺省参数写入List
GetTableNames方法
声明 procedure GetTableNames(const DatabaseName Pattern: Strings;
Extensions SystemTable: Boolean; List: TStrings)
GetTableNames方法消除List中的内容 并将名为DatabaseName的数据库中的所有表的名字写入List Pattern参数将限制表名 对于SQL服务器 将SystemeTables设为True将获取系统表和用户表 对非SQL数据库 将Extensions设为True将在表名中包含扩展名
处理Client/Server事务控制
使用隐式控制和显示控制的数据库应用中有两种方法管理事务控制
● 运用TDatabase部件的属性和方法进行显式控制
● 运用TQuery部件的传递式SQL控制事务
Delphi还支持Paradox和dBASE表的局部事务处理
事务控制概述
当用Delphi创建数据库应用时 Delphi提供了用为所有数据库访问的事务控制
事务是这样一组 *** 作 在被提交前 它们对一个或多个数据库的 *** 作 必须全部执行成功 如果其中一个 *** 作失败 则所有 *** 作失败 即事务具有原子性
即使发生硬件失败 事务也要保证数据库一致性 当允许多用户并发访问时 事务还要维持数据完整性
例如 一个应用程序可能更新ORDERS表以指明接受购买某一项目的定单 那么也要更新INNENTORY表以反映库存的减少 如果在第一个更新之后 第二个更新之前发生硬件错误 数据库就会处于不一致状态 因为库存情况没有反映定单情况 在事务控制下 两个表达式将在同一时间提交 如果其中一个表达式失败 则被返转(Rolled Back)
使用隐式控制
在缺省情况下 Delphi通过BDE为应用程序提供隐式事务控制 当应用程序处于隐式事务控制时Delphi为DataSet中的写每个记录进行隐式事务控制 它提交每一个独立的写 *** 作 如Post和Append Record
使用隐式事务控制是容易的 它保证最小的记录更新冲突和数据库的一致性视图 另一方面 因为写入数据库的数据的每一行都要进行事务控制 所以隐式事务控制将导致网络过忙和应用程序性能下降
如果采用显式事务控制 就能选择最有效的时机来开始 提交和终止事务 特别是在开发多用户环境下的客户应用程序运行访问远程SQL服务器 就更应该采用显式控制
使用显式事务控制
有两种协作又独立的方式可运用于Delphi数据库应用的事务控制
● 使用TDatabase部件的方法和属性
● 使用TQuery部件中的传递式SQL 这种方式只有在Delphi Client/Server Suite版中才有效 SQL Links将SQL表达式直接传给过程SQL或ODBC服务器
使用TDatabase部件的方法和属性的好处是提供了清晰的 轻便的 与特定数据库或服务器无关的应用能力
使用传递式SQL的主要好处在于可以运用特定服务器的先进事务管理能力
使用TDatabase的方法和属性
下表中列出了TDatabase部件中用于事务管理的方法和属性以及它们的使用方法
表 TDatabase用于事务显式控制的方法表
━━━━━━━━━━━━━━━━━━━━━━━━
方法或属性 作 用
────────────────────────
Commit 提交数据的修改并终止事务
Rollback 取消数据的修改并终止事务
StartTransaction 开始一个事务
TransIsolation 表述事务的独立性级别
━━━━━━━━━━━━━━━━━━━━━━━━
StartTransaction Commit和Rollback是供应用程序在运行时调用开始事务 控制事务并且保存或放弃所做数据修改的方法
TransIsolation是TDatabase部件的用于控制作用于相同表的不同事务之间如何交互的属性
⑴ 开始一个事务
当你开始一个事务时 后来的所有读写数据库的表达式都发生在那次事务的环境中 每个表达式都是其中一部分 任何表达式所做的修改 要么成功地提交给数据库 要么每一个修改都被取消 考虑一个在ATM上的银行传输问题 当顾客决定将钱从存款帐户转到支付帐户时 在银行数据库记录上必须发生两个修改
● 存款帐户必须记入借方
● 支付帐户必须记入贷方
如果出于某种原因 其中的一个 *** 作不能被完成 那么任何一个 *** 作都不应该发生 因为这些 *** 作是相关的 它们应该发生在同一个事务中
为了开始Delphi应用程序中的一个事务 需要调用TDatabase部件中的StartTransaction方法
DatabaseInterBase StartTransaction;
此后的所有数据 *** 作都发生在最近一个事务的环境中 直到该次事务通过调用Commit或Rollback显式地终止为止
那么 应当将事务保持多久呢?理想状态下 只要需要 多久都行 事务的活跃状态越长 同时访问数据库的用户越多 在你的事务的生命其中 更多的并发 同时的事务开始和终止 于是当试图提交修改时 与其它事务冲突的可能性更大
⑵ 提交一个事务
为了做永久性修改 事务必须使用TDatabase部件的Commit方法提交 执行提交表达式将保存数据库的修改并终止事务 例如 下列表达式将终止在上例中开始的事务
DatabaseInterBase Commit
Commit的调用应当置于try…except表达式中 如果一个事务不能成功提交 你就能处理错误 并重试 *** 作
⑶ 返转一个事务
为了取消数据库修改 必须用Rollback方法返转一个事务 Rollback 复原一个事务的修改 并终止事务 例如 下列表达式将返转一个事务
DatabaseInterBase Rollback;
Rollback通常发生在
● 异常处理代码
● 按钮或菜单事件代码 如用户点按了Cancel按钮
⑷ 使用TransIsolation属性
TransIsolation属性描述TDatabase部件事务的独立级别 事务的独立级别决定了事务与其它作用于相同表的事务是如何相互作用的 在改变或设置TransIsolation 的值之前 应当相当熟悉Delphi中的事务和事务管理
TransIsolation的缺省值是tiReadCommitted 下表中总结了TransIsolation的可能值并描述了它们的含义
表 TransIsolation属性值的含义
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
独立级别 含 义
──────────────────────────────────────
tiDirtyRead 允许读由其它同时事务写入数据库的未提交的修改 未提交的修改不是永久性的 可能在任何时候被复原 在这个级别你的事务与其它事务所做的修改具有最低独立度
tiReadCommitted 只允许读由其它同时事务提交的数据库修改 这是缺省的独立级别
iRepeatableRead 允许单个的数据库读事务无法看见其它同时事务对相同数据做的修改 这个独立级别保证了你的事务一次读一个记录 记录的视图不会改变 在这个级别你的事务与其它事务做的修改完全独立
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
各种数据库服务器不同程度地支持这些独立级别 有的根本不支持 如果请求的隔离级别不被服务器支持 Delphi将采用更高的独立级别 各种服务器支持的独立级别请参见表
如果应用程序使用ODBC与服务器交互 ODBC驱动程序必须支持独立级别
使用传递式SQL
为了能使用传递式SQL控制事物 必须
● 使用Delphi Client/Server Suite
● 安装正确的SQL Links驱动程序
● 正确配置网络协议
● 访问远程服务器上数据库的能力
● 用BDE配置工具将SQLPASSTHROUGH MODE设置为NOT SHARED
通过传递式SQL 你可以使用TQuery TStoredProc 或TUpdateSQL部件直接发送一个SQL事务控制表达式给远程数据库服务器 BDE本身并不处理SQL表达式 采用传递式SQL可使用户直接获得SQL服务器提供了事务控制优点 尤其是当那些控制是非标准的时
SQL PASS THROUGHMODE 描述BDE和传递式SQL是否共享相同的数据库联接 在大多数情况下 SQLPASSTHROUGHMODE被设置SHARED AUTOMIT 然而 如果你想将SQL事务控制传递给服务器 你就必须用BDE配置工具 将BDE的SQLPASSTHROUGHMODE 设置为NOT SHARED 此外 还必须为传递SQL事务控制表达式的TQuery部件建立独立的TDatabase 部件
使用本地事务
BDE还支持Paradox和dBASE上的本地事务 从代码角度而言 在本地事务和远程数据库服务器的事务之间没有什么差别
当作用于本地数据库表的事务开始时 更新 *** 作被记录在日志中 每个日志记录包含旧的记录缓冲区 当事务处于活跃状态 更新的记录被锁定 直到事务被提交或返转 在返转过程中 旧的记录被应用于将更新的记录恢复到原先的状态
使用存储过程
TStoredProc部件概述
存储过程是以数据库服务器为基础的接受输入参数 并将结果返回给应用程序的一段程序 TStoredProc部件 *** 作远程服务器上的数据库中的存储过程 存储过程是一连串表达式的集合 作为服务器的一部分存储 存储过程在服务器上执行一系列重复性的与数据库相关的任务 并将结果传给客户应用程序 如Delphi数据库应用程序
TStaredProc部件使Delphi数据库应用程序能执行服务器上的存储过程
通常 作用于数据库表中大量记录并且使用统计或数学函数的 *** 作都是存储过程的首选对象 通过将这些重复计算任务转移到服务器 可以提高数据库应用程序的性能
● 充分利用服务器的处理能力和速度
● 减少网络传输的数量
例如 考虑一个需要计算单个值的应用程序 在大批记录中的标准差值 如果在Delphi应用程序中执行这项功能就必须从服务器中得到所有在计算中用到的记录 这必将导致网络拥塞 因为应用程序所需的只是代表标准差的最终返回值 因此 由服务器上的存储过程来读数据 执行计算和将值传给应用程序将更有效
lishixinzhi/Article/program/Delphi/201311/25131
Sybase和MicroSoft SQL Server数据库
在建立Sybase或MicroSorft SQL Server的SQL Link时除了需要下列文件外 应用程序还需要Sybase数据库管理系统的客户端的连接产品与网络协议接口
表 建立Sybase数据库的SQL Link所需的文件
━━━━━━━━━━━━━━━━━━━━━━━━━━━
文件名 描 述
───────────────────────────
SQLD_SS DLL BDE SQL Link for Sybase的驱动程序
SQLD_SS HLP 联机帮助文件
SQL_SS CNF Sybase驱动程序的BDE配置文件
W DBLIB DLL Sybase/MC SQL Server客户端的DLL文件
DBNMP DLL Sybase/MC SQL Server客户端的DLL文件
SYDC LD Sybase语言驱动程序
SYDC LD Sybase语言驱动程序
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Informix数据库
在建立Informix的SQL Link时除了需要下列文件外 应用程序还需要Informix数据库管理系统的客户端的连接产品与网络协议接口
表 建立Informix 数据库的SQL Link所需的文件
━━━━━━━━━━━━━━━━━━━━━━━━━━━
文件名 描 述
───────────────────────────
SQLD_ss DLL BDE SQL Link for Informix的驱动程序
SQLD_INF HLP 联机帮助文件
SQL_INF CNF Informix驱动程序的BDE配置文件
LDLLSQLW DLL Informix客户端的DLL文件
ISAM IEM Informix错误信息文件
OS IEM Informix错误信息文件
RDS IEM Informix错误信息文件
SECURITY IEM Informix错误信息文件
SQL IEM Informix错误信息文件
━━━━━━━━━━━━━━━━━━━━━━━━━━━
InterBase 数据库
在建立InterBase的SQL Link时除了需要下列文件外 应用程序还需要InterBase数据库管理系统的客户端的连接产品与网络协议接口
表 建立InterBase数据库的SQL Link所需的文件
━━━━━━━━━━━━━━━━━━━━━━━━━━━
文件名 描 述
───────────────────────────
SQLD_IB DLL BDE SQL Link for InterBase的驱动程序
SQLD_IB HLP 联机帮助文件
SQL_IB CNF InterBase驱动程序的BDE配置文件
CONNECT EXE InterBase连接测试诊断工具
CONNECT HLP InterBase连接测试诊断工具的帮助文件
GDS DLL InterBase API DLL
REMOTE DLL InterBase与网络的接口的DLL文件
INTERBASE MSG InterBase错误信息文件
━━━━━━━━━━━━━━━━━━━━━━━━━━━
返回目录 DELPHI基础教程
编辑推荐
Java程序设计培训视频教程
J EE高级框架实战培训视频教程
Visual C++音频/视频技术开发与实战
Oracle索引技术
ORACLE G数据库开发优化指南
Java程序性能优化 让你的Java程序更快 更稳定
C嵌入式编程设计模式
Android游戏开发实践指南
lishixinzhi/Article/program/Delphi/201311/25179
增加字段部件
字段编辑器Fields Editor中的Add Fields菜单项用于向数据集部件中增加字段部件的 单击Add Fields菜单项时便会打开增加字段部件对话框 如图 所示 Available Fields列表框中显示出数据集部件TTable或TQuery中当前可以用于创建永久字段部件的全部的字段 也就是说Available Fields列表框中显示字段是数据库表中实际存在的字段 而且还没有为这些字段创建相应的永久性的字段部件 在缺省状态下所有的字段都被选择用于创建相应的永久性的字段部件 用鼠标单击其中的字段名可以有选择地创建其相应的永久性的字段部件 选择好有关的字段名之后 单击OK按钮便可以创建永久性的字段部件
字段编辑器的增加字段部件对话框
删除字段部件
用字段编辑器Fields Editor为数据集部件创建好的字段部件都会显示在字段编辑器的Fields列表框中 如果用户认为其中的一些字段部件不合适或不再需要时 可以单击这些不需要的字段部件 然后单击鼠标右键d出一佣d出式菜单 从d出式菜单中选择Delete菜单项 便可删除相应的字段部件 如果在d出式菜单中单击Select All菜单项 然后选择Delete菜单项 这样会删除已创建好的所有的字段部件 某一个字段部件被删除以后 通过单击Add Fields菜单项可以重新创建 只是先前为该字段部件设定的一些属性将不复存在
定义新的字段部件
字段编辑器Fields Editor中的d出式菜单中New Fields菜单项是用来为数据集部件TTable或TQuery创建用于显示目的的新的字段部件 我们可以用它来为数据库表中实际存在的字段创建新的字段部件(如改变字段的数据类型 使它的字段值被显示时不再需有关的类型转换) 但是我们使用New Fields菜单项创建新的字段部件主要是创建计算字段 计算字段并不与数据库表中实际存在的字段对应 它的字段值是根据表中其它的字段值计算而来的 具体的计算表达式由用户为TTable部件或TQuery部件的OnCalCFields事件编写程序代码时决定
定义(创建)计算字段的过程如下
单击字段编辑器中的New Fields菜单项 定义字段对话框如图 所示
在FieldName编辑框中输入新字段部件的名字 或者从下拉式列表框中选择一个已存在的字段部件的名字
在FieldType列表框中为新字段部件选择一个字段类型
单击Calculated检查框 确认定义的新字段部件是计算字段
单击ok按钮 创建上述定义的计算字段部件 此时该字段部件的名字会自动地加入到字段编辑中的Fields列表框中
创建新的计算字段
新的计算字段创建好了之后 它是没有任何字段值的 我们必须要编写相应的程序代码 根据数据库表中实际存在的字段的字段值为计算字段的宝定义字段值 我们为计算字段所在数据集部件的OnCalcFields事件编写代码来为计算字段赋值 其步骤如下
选择数据集部件TTable或TQuery
单击数据集部件的事件页
双击OnCalcFields事件为TTable或TQuery部件编写事件处理过程
TReport部件及其应用
在一般的数据库应用程序中都包含着为最终用户提供输出报表的功能 使用Delphi开发数据库应用程序时 可以使用一个叫TReport的部件来执行报表功能的 报表的具体格式和内容是由Delphi提供的一个专用报表生成工具ReprotSmith创建的 它报表的具体格式和内容生成一个报表文件 然后为TReport部件设置相应的属性参数 由TReport部件执行报表功能
我们可以在设计阶段双击TReport部件 调用ReportSimith工具或者在Delphi程序组内双击ReportSmith图标来调用ReportSmith工具来创建一个报表文件 具体的 *** 作步骤和设计方法请参看ReportSimth工具的使用说明
我们在使用TReport部件执行报表功能时 要设置TReport部件的一些的一些属性 这些属性是
ReportName属性 说明报表文件的名字 就是用ReportSmith创建的报表文件
ReportDir属性 说明报表文件所在的途径名
PreView属性 这是一个布尔型属性 若它的值为True 那么在执行报表功能时 只是在屏幕上显示报表 若它的值为False 则报表内容将在缺省的打印机打印出来
AutoUnload属性 布尔型属性 它的值为True时 在执行完一个报表功能后 自动地从内存中卸出ReportSmith工具 它的值为False时 在运行完一个报表功能后 不从内存中卸出ReportSmith工具 一般情况下 如果应用程序只有一个报表或者只有较少的报表要输出时 应设置AutoUnload属性为True 如果应用程序一次要输出多个报表 那么要应设置AutoUnload属性为False
InitialValues属性 这是一个字符串类型的属性 它是说明报表文件中使用的变量 每一条说明一个变量 如
ReportVAR := Value;
要详细了解创建和使用报表变量的过程请参看创建报表一节
TReport部件要真正执行报表功能以输出一个报表需要调用Run方法 如下所示
Report Run;
TReport部件所具有的重要方法如表 所示
表 TReport部件的方法
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
方法 功 能
────────────────────────────
Run 执行报表功能 输出报表
RunMacro 发送一个宏命令给Reportimith工具
Connect 预先连接报表文件和数据库 在输出报表时不需要登录到数据库
SetVariable 改变说明的报表变量
ReCalcReport 当报表变量改变以后 重新输出报表
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
还有一些其他的数据访问部件如TBatchMove部件 它主要用在两个数据库表之间移动或拷贝帆数据记录 具体的使用请参看本地SQL服务器的使用
应用举例 多个窗体显示同一个数据库表
在应用当中 我们常常需要以不同的视图显示同一个数据库表中的内容 例如要在两窗体中同时显示一个数据库表中一个记录的不同字段时 我们必须要想办法使两个窗体中的数据浏览部件同步地显示数据库表中的同一条记录的不同字段的值 要想做到以不同的视图显示同一个数据库表中的记录 下面两条规则是很重要的
● 多个TDataSource部件能够同时访问同一个数据集部件
● 在多个窗体中显示同一个表时 必须为每个窗体设置一个TDataSource部件 只须为其中的一个窗体设置一个TTable部件
例如 如果想在窗体Form 和Form 中同时显示一个数据库表的记录 最简单可行的办法是 为Form 和Form 各设置一个TDataSource部件叫DataSource DataSource 并在Form 中设置一个TTable部件Table 连接Form 中的Datasource 和Table 在程序运行过程中设置Form 中的DataSource 的DataSet属性为Form 中的Table 代码如下
Format DataSource Dataset := Form Table ;
这样 当Table 被打开时 两个窗体中便可以同步地显示数据库表中的同一条记录了
一个名叫OForms DPR的例子在C:\Delphi\DEMos\DB\TwoForms中(如果Delphi安装在其它的磁盘驱动器中 从相应的磁盘驱动器中可以找到该例子) 它演示了在两个窗体中显示同一个数据库表的记录 应用程序在第一个窗体中打开Contry DB表 并在窗体中显示Name Captial和Continent字段 在第二个窗体中显示Area和Population字段 在第一个窗体中有一个按钮用于打开第二个窗体 两个窗体中都有TDBNavigator部件 用于记录的导航
返回目录 DELPHI基础教程
编辑推荐
Java程序设计培训视频教程
J EE高级框架实战培训视频教程
Visual C++音频/视频技术开发与实战
Oracle索引技术
ORACLE G数据库开发优化指南
Java程序性能优化 让你的Java程序更快 更稳定
C嵌入式编程设计模式
Android游戏开发实践指南
lishixinzhi/Article/program/Delphi/201311/25156
在这一章里我们主要介绍Delphi的数据访问部件的层次结构 多部件之间的关系 部件的属性 方法 事件以及各部件的应用 这些部件包括
● TSession部件
● 数据集部件(TTable和TQuery)
● TDatasource部件
● 字段对象TField
● 字段编辑器的使用
● TReport部件和TBatchMove部件
我们对这些部件的属性 方法和事件进行一般性的描述 读者在实际使用Delphi开发应用程序时 还可以通过联机帮助获得有关部件更详细的信息
Delphi数据访问部件的层次结构
Delphi提供了强大的开发数据库应用程序的能力 它给用户提供了大量的数据访问部件 以方便程序设计人员开发数据库应用程序 这些部件中 有些部件继承了另一些部件的属性 方法和事件 也就是说多部件之间存在着继承和被继承的关系 各部件的这种关联便构成了一个层次结构
TSession是全局性的部件 在应用程序运行时 它自动地建立 在设计阶段和运行过程中它是一个不可见的部件
TDatabase部件是为开发客户/服务器数据库应用程序时 设置登录的数据库的有关参数的 它在数据访问部件页上
TDataset部件是不可见的 TTable和TQuery部件是由它派生而来的 这两个部件一般被称为数据集部件 它们在数据访问部件页上
TDatasource部件是连接数据集部件和数据浏览部件的桥梁 它在数据访问部件页上
TFields部件对应于数据库表中的实际字段 它既可以在应用程序的运行过程中动态地生成也可以在程序设计阶段用字段编辑器创建 它是不可见的部件 在程序中我们可以通过TField部件来访问数据库记录的各个字段值
Tsession部件及其应用
TSession部件一般用得较少 但它对于一些特殊的应用是很有用的 在每一个数据库应用程序运行时Delphi自动地创建一个TSession部件 程序设计人既不能看见该部件也不能显示地创建一个TSession 部件 但是我们可以在应用程序中全局性地使用TSession部件的属性 方法
TSession部件的重要属性及作用
TSession部件的许多重要属性是用于控制数据库应用程序与数据库的连接的 在一个应用程序中 可以全局性地设置TSession的有关属性值 对与之相连接的磁盘上的数据库进行控制 TSession部件主要有下列属性
Database属性 是TSession中可以进行连接的所有数据库的数据库名字列表 这些数据库的名字常常是实际数据库的别名 包括数据库的路径 用户名 用户登录口令等参数
DatabaseCount属性 是TSession中可以进行连接的所有数据库的数量 它是一个整数
KeepCounnections属性 是一个布尔型属性 用它说明应用程序是否保持与一个非活动数据库的连接 因为对于一个数据库 当该数据库中没有相应的数据集部件(TTable或TQuery)被打开时 该数据库将自动地变成非活动的数据库 缺省情况下 KeePcounnections的值是True 就是说应用程序总是保持着与数据库的连接 即使数据库变成了非活动的数据库时 也是如此 如果将KeepConnections属性设置成False 那么当数据库由活动状态变成非活动状态时 应用程序与该数据库的连接也随之中断
NetFileDir属性 说明BDE网络控制文件的路径名
PrivateDir属性 说明存取临时文件的路径名
TSession部件的方法
TSession部件中的大部分方法是用于向用户提供与应用程序相连接的数据库的信息 如数据库的名字及别名 数据库中的表名以及数据库引擎BDE的有关参数等 在设计数据库应用程序时 想要获取有关数据库的信息 调用TSession部件的下列方法 将会大大简化程序的设计
GetAliasNames方法 调用该方法 我们可以获得数据库引擎BDE中定义的数据库别名
GetAliasParams方法 该方法主要用于获取我们在BDE中定义数据库别名时所说明的参数值 如BDE所在的目录路径以及实际名称等
GetDatabaseNames 方法 调用该方法可以帮助我们获得当前应用程序可以进行连接的所有数据库的名字 数据库的名字是用户使用BDE工具定义的实际数据库的别名
GetDriverNames方法 数据库引擎BDE可以与多种数据库管理系统相连接 如客户/服务器数据库管理系统Oracle Sybase以及本地数据库管理系统dBASE Paradox等 BDE与每一种数据库管理系统进行连接时 都有相应的驱动程序 而且这些驱动程序都可以选择地安装 通过调用GetDriverNames方法 我们可以获得当前BDE安装的数据库驱动程序的名字
GetDriverParams方法 BDE的数据库驱动程序中包含着多个参数 如支持的民族语言 DBMS的版本号 文件块大小等 对于服务器上的DBMS 还有数据库服务器的名字等等
GetTableNames方法 因为每一个数据库都是由多个数据库表组成的 我们通过说明数据库名 然后调用GetTableNames方法 便可以获得该数据库中全部的数据库表的名字
上述这些方法在调用时都需要一个字符串列表作为参数 而且都返回一个字符串列表的值
TSession部件还有一个叫DropConnections的方法用于控制应用程序与数据库的连接 当调用DropConnections方法时 应用程序与所有的数据库的连接将会切断
TSession部件应用举例
例 :我们创建一个应用程序 通过调用TSession有关的方法获取当前应用程序可以进行连接的数据库的名字以及获取其中任意一个数据库中的全部数据库表的名字
通过TSession部件获取数据库的有关信息
窗体中主要使用了两个列表框 其中列表框DatabaselistBox用于显示数据库的名字 列表框TablelistBox用于显示数据库中的表名 程序运行完后数据库的名字显示在DatabaselistBox列表框中 当用户单击DatabaselistBox列表框中的数据库名时 该数据库全部的数据库表的名字将会显示在TablelistBox列表框中 有关的程序代码如下
lishixinzhi/Article/program/Delphi/201311/25161
以上就是关于DELPHI基础教程:简单数据库应用的创建及MASTAPP介绍(三)[1]全部的内容,包括:DELPHI基础教程:简单数据库应用的创建及MASTAPP介绍(三)[1]、DELPHI基础教程:数据浏览部件的应用及编程(二)[1]、Delphi数据库控件使用入门(一)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)