记录集对象
“记录集(RecordSet)”对象描述来自数据表或命令执行结果的记录集合,其组成为记录(行)。常用于指定可以检查的行、移动行、指定移动行的顺序、添加、更改或删除行、通过更改行而更新数据源等。
在实际操作中使用什么记录集取决于要完成的任务。表类型的记录集已建立了索引,适合快速定位与排序,但内存开销太大。动态集类型的记录集则适合更新数据,但其搜索速度不及表类型。快照类型的记录集内存开销最小,只适合显示读数据。
使用RecordSet对象的属性与方法的一般格式为:
数据控件名.RecordSet.属性/方法
一、记录集对象的属性
(1)CursorType
用于设置记录集游标(指针)类型,取值参见表9-5,默认为0,即指针只能前移。如果要让指针自由移动,一般设为键盘指针1。语法如下:
记录集.CursorType=值
表9-5 记录集游标类型
常数 |
值 |
说明 |
adOpenForwardOnly |
0 |
缺省值,启动一个只能向前移动的游标(Forward Only)。 |
adOpenKeyset |
1 |
启动一个Keyset类型的游标。 |
adOpenDynamic |
2 |
启动一个Dynamic类型的游标。 |
adOpenStatic |
3 |
启动一个Static类型的游标。 |
(2)BOF
用于判断当前记录指针是否在记录集的开头,如果是在开头,返回True,否则返回False。如果记录集为空,也返回True。
(3)EOF
用于判断当前记录指针是否在记录集的结尾,如果是在结尾,返回True,否则返回False。如果记录集为空,也返回True。
记录集有两个特殊位置:BOF和EOF。BOF表示记录集的开头,位于第一条记录之前;EOF表示记录集结尾,位于最后一条记录之后。如果记录集不为空,指针可以在BOF、所有记录和EOF移动。如果记录集为空,此时指针同时指向BOF和EOF,它们的值均为True。
具体判断如下:若当前记录的位置是在一个RecordSet对象第一行记录之前时,BOF属性返回True,反之则返回False;若当前记录的位置是在一个RecordSet对象最后一行记录之后时,EOF属性返回True,反之则返回False;BOF与EOF都为False,表示指标位于RecordSet的当中;BOF与EOF都为True,在RecordSet里没有任何记录。
从以上可知,通过检验BOF与EOF属性,可以得知当前指针所指向的RecordSet的位置,使用BOF与EOF属性,可以得知一个RecordSet对象是否包含有记录或者得知移动记录行是否已经超出该RecordSet对象的范围。
例:
l 判断记集录是否为空的代码如下:
If Not rs.bof And rs.EOF Then ' 如果不是开头,也不是结尾,则执行
…
End If
l 循环输出记录集记录的代码如下:
Do While Not rs.EOF ' 如果没有到达记录集未尾,则循环输出下面的记录
…
rs.MoveNext
(4)RecordCount
用于返回记录集中的记录总数。值得注意的是,使用RecordCount必须设置指针类型为键盘指针1或是静态指针3。
(6)AbsolutePosition
返回当前指针所在的记录行,如果是第一条记录,其值为0,该属性只读。
(6)BookMark属性
BookMark属性的值采用字符串类型,用于设置当前指针的书签。当创建或打开一个非仅向前类型RecordSet对象(向前类型RecordSet对象是指CursorType=adOpenForwardOnly的RecordSet对象),其中的每一行均已有一个唯一的书签。可以通过将Bookmark属性的值赋给某个变量,为其当前行保存书签,在移动了指针后,可在任意时刻设置RecordSet对象的Bookmark属性为该个变量的值以快速地返回该行。
为了确保RecordSet能支持书签,使用Bookmark属性前,可先检查它的Bookmarkable属性。如果Bookmarkable为False,该RecordSet就不支持书签。
Bookmark属性的值不保证一定与行号相同。
(7)NoMatch属性
在记录集中进行查找时,如果找到相匹配的记录,则RecordSet的NoMatch属性为False,否则为True。该属性常与Bookmark属性一起使用。
二、记录集对象的方法
(1)AddNew方法
AddNew用于添加一条新记录,新记录的每个字段若有默认值将以默认值表示,如果没有则为空。例如,给Data1的记录集添加新记录:
Data1.RecordSet.AddNew
(2)Delete方法
Delete用于删除当前记录的内容。注意:在删除后,当前记录仍是被删除记录,因此通常在删除后将当前记录移到下一条记录。
(3)Find方法群组
Find方法用于查找指定记录,它是多种查找方法的统称,称为方法群组。包含FindFirst、FindLast、FindNext和FindPreviou方法,这4种方法的主要区别是查找的起点不同。
l FindFirst:从第一条记录开始向后查找。
l FindLast:从最后一条记录开始向前查找。
l FindNext:从当前记录开始向后查找。
l FindRrevious:从当前记录开始向前查找。
通常,当查找不到符合条件的记录时,需要显示信息提示用户,因此使用NoMatch属性,若Find或Seek方法找不到相符的记录,NoMatch属性为True。
[例9-8]查找“学号”字段为“
Data1.RecordSet.FindFirst ("学号='0809001'")
If Data1.RecordSet.NoMatch Then ′如果没找到
MsgBox ″找不到0809001号同学!″
End If
(5)Seek方法
Seek方法适用于数据表类型(Table)记录集,通过一个已被设置为索引(Index)的字段,查找符合条件的记录,并使该记录为当前记录。
使用Seek方法必须打开表的索引,它只能在Table表中查找与指定索引规则相符的第一条记录,并使之成为当前记录。其语法格式为:
数据表对象.Seek comparison,keyl,key2,…,key13
Seek允许接受多个参数,第一个是比较运算符comparison,该字符串确定比较的类型。Seek方法中可用的比较运算符有=、>=、>、<>、<、<=等。
在使用Seek方法定位记录时,必须通过Index属性设置索引。若在同一个记录集中多次使用同样的Seek方法(参数相同),那么找到的总是同一条记录。
(5)Move方法群组
Move方法群组是用于移动记录,包含MoveFirst、MoveLast、MoveNext和MovePrevious 方法,这4种方法分别移动记录到第一条、最后一条、下一条和前一条。
注意:当在最后一条记录时,使用了MoveNext方法EOF的值会变为True,如果再使用MoveNext方法就会出错。对于MovePrevious方法前移,结果也类似。
Move [n] 方法向前或向后移n个记录,n为指定的数值。
(6)Update方法
用于保存对RecordSet对象的当前记录所做的修改。
Data控件是浏览和编辑记录集的好工具。数据库记录的查找、增加、删除和修改操作需要使用Find、AddNew、Delete、Edit、Update和Refresh方法。它们的语法格式为:
数据控件.记录集.方法名
1.增加记录
AddNew方法在记录集中增加新记录。增加记录的步骤为:
(1)调用AddNew方法。
(2)给各字段赋值。给字段赋值格式为:RecordSet.Fields(“字段名”)=值。
(3)调用Update方法,确定所做的添加,将缓冲区内的数据写入数据库。
注意: 如果使用AddNew方法添加了新的记录,但是没有使用Update方法而移动到其他记录,或者关闭了记录集,那么所做的输入将全部丢失,而且没有任何警告。当调用Update方法写入记录后,记录指针自动从新记录返回到添加新记录前的位置上,而不显示新记录。为此,可在调用Update方法后,使用MoveLast方法将记录指针再次移到新记录上。
2.删除记录
要从记录集中删除记录的操作分为三步:
(1)定位被删除的记录使之成为当前记录。
(2)调用Delete方法。
(3)移动记录指针。
注意: 在使用Delete方法时,当前记录立即删除。删除一条记录后,被数据库所约束的绑定控件仍旧显示该记录的内容。因此,需移动记录指针刷新绑定控件,一般移至下一记录。在移动记录指针后,应该检查EOF属性。
3.编辑记录
数据控件能自动修改现有记录,当直接改变被数据库所约束的绑定控件的内容后,需单击数据控件对象的任一箭头按钮来改变当前记录,确定所做的修改。也可通过程序代码来修改记录,使用程序代码修改当前记录的步骤为:
(1)调用Edit方法。
(2)给各字段赋值。
(3)调用Update方法,确定所做的修改。
注意:如果要放弃对数据的所有修改,可使用UpdateControls方法放弃对数据的修改,也可用Refresh方法,重读数据库,刷新记录集。由于没有调用Update方法,数据的修改没有写入数据库,所以这样的记录会在刷新记录集时丢失。
下面通过两个实例对这些应用予以讨论。此处实例均是基于名为ClassVB.mdb,存放于应用程序所在文件夹的Access数据库中名为Student的学生信息表,其表结构为:学号(char(7))、姓名(varchar(8))、专业(varchar(10))、出生年月(datetime)、性别(char(2))、照片(varbinary),表记录如下:
表9-6 Student表
姓名 |
专业 |
出生年月 |
性别 |
照片 | |
0809001 |
张三 |
物理 |
|
男 |
|
0809002 |
李四 |
物理 |
|
女 |
|
0809003 |
王五 |
数学 |
|
男 |
|
0809004 |
张小前 |
数学 |
|
女 |
|
0809005 |
张克良 |
数学 |
|
男 |
|
0809006 |
程序 |
计算机 |
|
女 |
|
0809007 |
黎艳宁 |
计算机 |
|
女 |
|
0809008 |
章万南 |
电气 |
|
男 |
|
0809009 |
陈友东 |
电气 |
|
男 |
[例9-9]记录浏览可用[例9-6]来实现,但Data控件的浏览按钮不美观,为此在窗体上设置“首记录”、“上一条”、“下一条”和“末记录”四个按钮,以代替Data控件的四个箭头按钮来浏览Student表。要求获得如图9-13所示的运行效果。
图9-13 记录浏览
显示照片用图片框。因为要用按钮代替Data控件的浏览按钮,因此需要把Data控件的Visible属性设为False,以免影响界面效果。另外,由于ClassVB.mdb存放于应用程序所在文件夹,所以Data控件的DatabaseName属性不能在设计时设定,必须在运行时由程序设定。其余约束控件与数据源的有关字段绑定。程序清单如下:
Private Sub Command1_Click() '“首记录”按钮
Data1.RecordSet.MoveFirst
End Sub
Private Sub Command2_Click() '“上一条”按钮
Data1.RecordSet.MovePrevious
If Data1.RecordSet.BOF Then '检查是否越界
MsgBox "第一条记录"
Data1.RecordSet.MoveFirst
End If
End Sub
Private Sub Command3_Click() '“下一条”按钮
Data1.RecordSet.MoveNext
If Data1.RecordSet.EOF Then '检查是否越界
MsgBox "最后一条记录"
Data1.RecordSet.MoveLast
End If
End Sub
Private Sub Command4_Click() '“末记录”按钮
Data1.RecordSet.MoveLast
End Sub
Private Sub Form_Load() '窗体加载事件
mPath = App.Path
If Right(mPath, 1) <> "\" Then mPath = mPath + "\"
Data1.DatabaseName = mPath + "ClassVB.mdb"
Data1.RecordSource = "Student"
End Sub
[例9-10]在[例9-9]的基础上增加“新增”、“删除”、“修改”、“放弃”和“查找”5个功能,如图9-14所示。
图9-14 记录维护
程序清单如下:
Private Sub cmdAdd_Click()
On Error Resume Next
cmdDel.Enabled = Not cmdDel.Enabled
cmdCancel.Enabled = Not cmdCancel.Enabled
cmdFind.Enabled = Not cmdFind.Enabled
Command1.Enabled = Not Command1.Enabled
Command2.Enabled = Not Command2.Enabled
Command3.Enabled = Not Command3.Enabled
Command4.Enabled = Not Command4.Enabled
If cmdAdd.Caption = "新增" Then
cmdAdd.Caption = "确认"
Data1.RecordSet.AddNew
Text1.SetFocus
Else
cmdAdd.Caption = "新增"
Data1.RecordSet.Update
End If
End Sub
cmdAdd_Click事件的功能是完成“新增”和新增“确认”,并控制其余按钮的可用性。当按钮提示为“新增”(Caption=“新增”)时,调用AddNew方法,并将提示文字改为“确认”,同时除“放弃”按钮外,其余按钮设为不可用。新记录输入完成后,需再次单击cmdAdd按钮调用Update方法以“确认”输入,提示文字改回“新增”,并设“放弃”按钮不可用,其余可用。程序中语句“On Error Resume Next”是VB的错误捕获语句,表示程序在运行时发生错误,忽略错误行,继续执行下一语句。
Private Sub cmdCancel_Click()
On Error Resume Next
cmdAdd.Caption = "新增": cmdModify.Caption = "修改"
cmdAdd.Enabled = True: cmdDel.Enabled = True
cmdModify.Enabled = True: cmdCancel.Enabled = False
Command1.Enabled = Not Command1.Enabled
Command2.Enabled = Not Command2.Enabled
Command3.Enabled = Not Command3.Enabled
Command4.Enabled = Not Command4.Enabled
cmdFind.Enabled = True
Data1.UpdateControls
Data1.RecordSet.MoveLast
End Sub
cmdCancel_Click事件使用UpdateControls方法放弃操作,并设置各按钮的可用性。
Private Sub cmdDel_Click()
On Error Resume Next
If MsgBox("操作将删除当前记录,是否继续?", vbYesNo, Me.Caption) = vbYes Then
Data1.RecordSet.Delete
Data1.RecordSet.MoveNext
If Data1.RecordSet.EOF Then Data1.RecordSet.MoveLast
End If
End Sub
事件调用Delete方法删除当前记录。因为错误的删除操作会导致数据的丢失,所以删除之前使用MsgBox函数要求用户确认。另外,在删除掉所有记录后执行Move操作会发生错误,这时由On Error Resume Next语句处理错误。
Private Sub cmdFind_Click()
mno = InputBox$("请输入学号", "查找窗")
Data1.RecordSet.FindFirst "学号 like '" & mno & "'"
If Data1.RecordSet.NoMatch Then MsgBox "无此学号!", , Me.Caption
End Sub
查找操作调用Find方法,并在查询条件中使用“like”操作符以实现模糊查找。
Private Sub cmdModify_Click()
On Error Resume Next
cmdAdd.Enabled = Not cmdAdd.Enabled
cmdDel.Enabled = Not cmdDel.Enabled
cmdCancel.Enabled = Not cmdCancel.Enabled
cmdFind.Enabled = Not cmdFind.Enabled
Command1.Enabled = Not Command1.Enabled
Command2.Enabled = Not Command2.Enabled
Command3.Enabled = Not Command3.Enabled
Command4.Enabled = Not Command4.Enabled
If cmdModify.Caption = "修改" Then
cmdModify.Caption = "确认"
Data1.RecordSet.Edit
Text1.SetFocus
Else
cmdModify.Caption = "修改"
Data1.RecordSet.Update
End If
End Sub
修改操作调用Edit方法修改记录。使用Edit方法后,移动记录或者使用Update方法把数据存入到数据库中。
Private Sub Picture1_DblClick()
If cmdAdd.Caption = "新增" And cmdModify.Caption = "修改" Then Exit Sub
If MsgBox("操作将会用剪贴板内容替换照片,是否继续?", vbYesNo, Me.Caption) = vbYes Then
Picture1.Picture = Clipboard.GetData
End If
End Sub
关于照片的输入或修改,较简单的方法是通过剪贴板将照片复制到Picture1中。输入或修改照片之前,在图片编辑工具把照片复制到剪贴板中,然后再复制到Picture1中。本例Picture1_DblClick来完成照片的输入或修改。语句“If cmdAdd.Caption = "新增" And cmdModify.Caption = "修改" Then Exit Sub”在输入或修改照片之前先判断当前是否处于“新增”或“修改”状态,若不是则不复制照片到控件。语句“Picture1.Picture = Clipboard.GetData”完成从剪贴板复制照片到控件。
Command1_Click~Command4_Click事件及Form_Load事件与[例9-9]相同。
以上的代码给出了处理数据表数据的基本方法。值得注意的是:对于一条新记录或修改的记录必须保证数据的完整性,这可以通过Data1_Validate事件过滤无效记录。以下代码对学号字段进行测试,如果学号为空则输入无效。在本例中被学号字段约束绑定的控件是Text1,可用Text1.DataChanged属性检测Text1控件所对应的记录中的字段值的内容是否发生了变化,Action = 6表示Update操作(参见表9-4)。
Private Sub Data1_Validate(Action As Integer, Save As Integer)
If Text1.Text = "" And (Action = 6 Or Text1.DataChanged) Then
Data1.UpdateControls
MsgBox "数据不完整,必须要有学号!", , Me.Caption
End If
If Action >= 1 And Action < 5 Then
cmdAdd.Caption = "新增": cmdModify.Caption = "修改"
cmdAdd.Enabled = True: cmdDel.Enabled = True
cmdModify.Enabled = True: cmdCancel.Enabled = False
cmdFind.Enabled = True
End If
End Sub