📄 035.htm
字号:
<p>end;</p><p> </p><p>procedure TForm1.MixedCaseSecondAddBtnClick(Sender: TObject);</p><p>begin</p><p>ForceCase('Addr2',Mixed);</p><p>end;</p><p> </p><p>procedure TForm1.FormCreate(Sender: TObject);</p><p>begin</p><p>customerTable.open;</p><p>end; </p><p>end. </p><p align="center">14.7 插入和删除记录 </p><p> 虽然我们使用DBD或者在应用程序窗体中用TDBNavigator可以插入、删除表中的记录,但是任何重要的数据库应用程序都是根据最终用户的命令完成此类操作的。同样,如果我们掌握了字段对象及其用法,修改数据库中的记录,插入和删除记录将变得非常容易。</p><p> 要想删除表中的某一条记录,首先将记录指针移到该记录处,然后调用delete方法,这样,当前指针所在的记录就会被删除,而且我们在进行删除操作时,不必将TTable部件设置成编辑状态。当前指针所在的记录被删除之后,被删除记录下面的所有记录都向前移动,记录指针自动移到紧挨着被删除的记录的下一条记录。在删除记录的过程中没有提醒用户是否真的想删除当前记录的信息确认框,因此在进行此项操作时要倍加小心,如果是开发应用程序,最好的办法是提供一个确认信息框确保用户不会意外删除记录。</p><p> 插入一条记录也很简单,Delphi为用户提供两种方法用来插入记录到现存数据库表中,一种方法是在当前记录指针所在的记录处插入记录;另一种方法是在数据库表的尾部插入记录。这两种方法是分别调用Insert方法和Append方法实现的。但是无论是调用Insert方法还是调用Append方法在具有索引的数据库表中插入记录,增加到索引表中的记录都将按照索引顺序写入到数据库表中,也就是说对于索引表,调用Insert和Append方法的效果是一样的。事实上,Append方法只适用于那些没有索引的表,这种没有索引的表并不十分有用因而通常不创建这种表。几乎任何情况下我们都是用Insert方法来插入记录。</p><p> 用户在插入记录时一般可以采用两种方式插入:逐步插入即首先建立一条空记录,然后再填充记录的各个字段,最后再将记录写回到磁盘,共分三个独立的操作步骤;而使用InsertRecord方法便可以一次将插入记录的操作完成。 </p><p>14.7.1 逐步插入方法 </p><p> 逐步插入方法分为三个明确的步骤:先调用TTable部件的Insert方法在TTable中创建一条新的空记录,然后填充该记录的各个字段,最后调用post方法把新记录写到磁盘上的实际数据库文件中,在填充并传送记录以前,考虑插入记录到表中的什么位置是毫无意义的,假设插入的表是有索引的,在调用post方法时,Delphi会自动地把插入的新记录按照索引顺序插入到表中的正确位置。如果插入的表中没有索引,那么新记录将插入到当前指针所在记录的后面。</p><p>因此,采用逐步插入方法插入记录的程序代码一般如下形式:</p><p>With Table do</p><p>begin</p><p>Insert; {插入一条空白记录}</p><p><填充该记录的各个字段></p><p>post; {将插入的记录写回到磁盘文件}</p><p>end;</p><p>对于没有索引的数据库表,可以用Append方法替代Insert方法把新记录插入到表的尾部。 </p><p>14.7.2 调用InsertRecord插入记录 </p><p> 对于简单的应用程序,Delphi允许用户用一条语句插入一个新记录,而且这个新记录可以带有任意多个新字段值。InsertRecord方法把新记录中字段的赋值语句和psot方法调用组合进一条语句中。</p><p> InsertRecord方法把记录的各个字段值组合成一个字段值数组作为它的唯一参数。在字段值数组中,可以为插入的记录的每个字段提供一个字段值,或从最左一列开始依次为任意多个字段赋值。也就是说用户可以从表的最左边一列起, 把多个列的值同时传递给InsertRecord,直到所有字段都被赋值。用户也可以省略后面的字段,InsertRecord会用空值填充这些没有赋值的字段。用户还可以对那些明确希望用空值填充的字段传递保留字NIL来标明该字段为空。</p><p>如我们希望在Customer.DB表中插入一条记录,可以用下面的代码来实现: </p><p>InsertRecord(['2000',NIL,NIL,NIL]); </p><p>在上面的程序代码中,我们只填充了四个字段:CustNo、Company、Add1、 Add2 。InsertRecord会自动将其它字段赋以空值。</p><p>例14.7 在这个例子中,我们在CustNo.DB表中插入和删除记录,都是在程序中完成这类操作的,而不再是使用DBD或数据浏览部件完成。 </p><p> 插入/删除记录 </p><p>程序清单:</p><p>unit tt; </p><p>interface </p><p>uses</p><p>SysUtils, Windows, Messages, Classes, Graphics, Controls,</p><p>StdCtrls, Forms, DBCtrls, DB, DBGrids, Buttons, DBTables, Grids, </p><p>ExtCtrls,Mask,Dialogs;</p><p> </p><p>type</p><p>TForm1 = class(TForm)</p><p>DBGrid1: TDBGrid;</p><p>DBNavigator: TDBNavigator;</p><p>Panel1: TPanel;</p><p>DataSource1: TDataSource;</p><p>Panel2: TPanel;</p><p>customerTable: TTable;</p><p>BitBtn1: TBitBtn;</p><p>Label1: TLabel;</p><p>Label2: TLabel;</p><p>BitBtn2: TBitBtn;</p><p>BitBtn3: TBitBtn;</p><p>CustNoEdit: TEdit;</p><p>CompEdit: TEdit;</p><p>procedure FormCreate(Sender: TObject);</p><p>procedure BitBtn2Click(Sender: TObject);</p><p>procedure BitBtn3Click(Sender: TObject);</p><p>procedure FormActivate(Sender: TObject);</p><p>private</p><p>{ private declarations }</p><p>public</p><p>{ public declarations }</p><p>end;</p><p> </p><p>var</p><p>Form1: TForm1;</p><p> </p><p>implementation</p><p> </p><p>{$R *.DFM}</p><p> </p><p>procedure TForm1.FormCreate(Sender: TObject);</p><p>begin</p><p>customerTable.Open;</p><p>end;</p><p> </p><p>procedure TForm1.BitBtn2Click(Sender: TObject);</p><p>begin</p><p>If (Length(CustNoEdit.text)=0)and</p><p>(Length(CompEdit.text)=0)</p><p>then</p><p>MessageDlg('没有输入新记录的字段值!',mtError,[mbCancel],0)</p><p>else</p><p>with customerTable do</p><p>begin</p><p>IndexFieldNames:='CustNo';</p><p>If FindKey([CustNoEdit.text]) then</p><p>MessageDlg('已经存在这条记录!',mtError,[mbCancel],0)</p><p>else</p><p>InsertRecord([StrToInt(CustNoEdit.text),CompEdit.text,nil]);</p><p>CustNoEdit.text:=' ';</p><p>CompEdit.text:=' ';</p><p>end;</p><p> </p><p>end;</p><p> </p><p>procedure TForm1.BitBtn3Click(Sender: TObject);</p><p>begin</p><p>If (Length(CustNoEdit.text)=0)and</p><p>(Length(CompEdit.text)=0)</p><p>then</p><p>MessageDlg('没有输入删除的记录的字段值!',mtError,[mbCancel],0)</p><p>else</p><p>with customerTable do</p><p>begin</p><p>IndexFieldNames:='CustNo';</p><p>If FindKey([CustNoEdit.text]) then</p><p>begin</p><p>If MessageDlg('你确定要删除这条记录吗?',mtConfirmation, </p><p>[mbYes,mbno],0)=mrYes then Delete;</p><p>end</p><p>else</p><p>MessageDlg('没有你要删除的记录!',mtError,[mbCancel],0);</p><p>CustNoEdit.text:=' ';</p><p>CompEdit.text:=' ';</p><p>end;</p><p>end;</p><p> </p><p>procedure TForm1.FormActivate(Sender: TObject);</p><p>begin</p><p>CustNoEdit.setfocus;</p><p>end; </p><p>end. </p><p align="center">14.8 输入数据的有效性验证 </p><p> 当用户向一个数据库表中插入新记录或修改原有记录时,我们必须确保用户输入的数据是有效的,为此Delphi通过三种不同的途径用来验证用户输入的数据是否有效。</p><p> 这三种途径是:基于数据库表的有效性验证、基于字段的有效性验证、基于记录的有效性验证。</p><p>基于数据库表的有效性验证:</p><p> 在用户创建数据库表时就建立有效性验证机制,如在使用DBD创建一个表时,我们可以为创建的数据库表说明一些验证手段,包括字段的最大值,最小值,图形字段的显示格式等等。在设定这些有效性验证机制时,不需要编写任何程序代码。基于数据库表的有效性验证是当数据写到数据库之前,由数据库本身来执行。Delphi也执行一些有效性验证,如在数据写到数据库之前Delphi会验证每一个字段是否被填入相应的值,有关这种途径来验证数据的有效性的详细情况请参考DBD的使用。</p><p>基于字段的有效性验证:</p><p>一般有两种方法来进行这种方式的有效性验证。</p><p>①为记录中需要设置有效性验证的字段编写Onvalidate事件处理过程。这样每当该字段的值被修改时,该字段的OnValidate事件处理过程就会被调用,进而对被修改的字段值进行验证。</p><p>②对于记录中要求非空的字段(如口令或关键字等),我们必须首先设置这些字段的Required属性为True,然后为这些字段编写OnValidate事件处理过程,这样在修改现存记录或插入新记录时,在写入数据库之前,如果要求非空的字段中没有填入适当的字段值,那么会出现错误信息提示用户必须输入字段值。</p><p>基于记录的有效性验证:</p><p>这种验证方式一般在TTable部件的BeforePost事件处理过程中进行处理,即在记录写回到数据库之前对记录的每个字段值进行有效性验证。</p><p>例14.8 在程序中对字段值的有效性进行验证。</p><p>1. 创建一个用TEdit部件浏览ORDERS.DB表的应用,如图14.25所示。</p><p>2. 修改TDataSource部件的AutoEdit属性为True。</p><p>3. 双击TTable部件打开字段编辑器Fields Editor,并单击SaleDate字段。</p><p>4. 在Object Inspector中双击SaleDate字段对象的OnValidate事件,为该字段对象编写事件处理过程如下: </p><p>TForm1.Table1SaleDateValidate(Sender:TField);</p><p>begin</p><p>If SaleDate.Value>Now then</p><p>raise Exception.Create('不能输入一个未来的日期');</p><p>end;</p><p> 当这个应用程序运行时,用户修改或插入ORDERS.DB中的记录时,该应用程序会对销售日期(SaleDate)字段的值进行验证,该字段值不能晚于系统的当前日期,程序中调用Now方法获得系统的当前日期。如果字段值大于系统的当前日期会出现一错误信息提示框,告知用户不能输入一个未来的日期。</p><p>使用TDBComBox部件和TDBLookupComBox部件来限制用户输入字段值的范围。</p><p> 创建查看orders.db表的应用,创建好的窗体如图14.25所示。窗体中显示Terms字段的是TDBComBox部件,显示EmpNo字段的是TDBLookupComBox部件。 </p><p>图14.25 用数据浏览部件限制用户的输入 </p><p>TDBComBox和TDBLookupComBox部件的属性值如表14.8所示: </p><p>表14.8 窗体中各部件的属性设置</p><p>━━━━━━━━━━━━━━━━━━━━━━━━━━━</p><p>部 件 属 性 属 性 值</p><p>───────────────────────────</p><p>DataField Terms</p><p>DBComBox1 DataSource DataSource1</p><p>Items Prepaid</p><p>Net 30</p><p>COD</p><p>───────────────────────────</p><p>DataField EmpNo</p><p>DataSource DataSource1</p><p>DBLookupComBox LookupSource DataSource2</p><p>KeyField EmpNo</p><p>LookupField EmpNo</p><p>───────────────────────────</p><p>DataSource1 DataSet Table1</p><p>AutoEdit True</p><p>───────────────────────────</p><p>DataSource2 DataSet Table1</p><p>AutoEdit True</p><p>───────────────────────────</p><p>Table1 DatabaseName DemosDB</p><p>TableName orders.db</p><p>───────────────────────────</p><p>Table2 DatabaseName DemosDB</p><p>TableName orders.db</p><p>━━━━━━━━━━━━━━━━━━━━━━━━━━━</p><p> 该应用运行时,当用户修改和插入记录到ORDERS.DB表中时,Terms字段的值可以从组合框中的Prepaid、Net30、COD三个值中任选,EmpNo字段的值是从另一个表Employee中获得的雇员号码,用户可以从中选择。</p><p> </p><hr width="94%"></TD><TD CLASS="tt3" VALIGN="bottom" width="8%" ><strong><A HREF="036.htm"><FONT style="FONT-SIZE: 9pt">后一页</font></A><BR><A HREF="034.htm"><FONT style="FONT-SIZE: 9pt">前一页</font></A><BR><A HREF="index.html"><FONT style="FONT-SIZE: 9pt">回目录</font></A><BR></strong></TD></TR></table></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -