级别: 初级 Essma Hasin, 质量保证工程师, Neneva Technologies
2003 年 7 月 01 日 您所要求的会得到满足!作者 Essma Hasin 向您介绍使用 DB2 V8 执行的基本 ADO 数据库操作,包括如何用开发中心(Development Center)Visual Studio 开发外接程序实现许多功能。
简介
IBM® DB2® V8.1 是很强大的新版本,它在引擎能力方面有大量新的增强,如 MDC(多维群集,multi-dimensional clustering)和联机重组等,并且有一些很好的新工具,如健康中心(Health Center)、开发中心(Development Center)和 Microsoft® Visual Studio 6 的开发外接程序(Development Add-In)。
尽管 Visual Basic 6 的 DB2 开发外接程序是一种极大简化了
n层应用程序(尤其是那些依靠数据库过程和函数的应用程序)开发的极佳工具,但对于 Visual Basic 开发人员而言,理解使用 ADO 编程 API 进行 DB2 开发的基础知识仍很重要。
在本文中,我将介绍如何使用 ADO 对象模型执行四项基本数据库操作;即:使用 Visual Basic 客户机应用程序从 DB2 Universal Database 表选择、插入、更新和删除记录。在适当的地方,我将介绍完成这些操作的两种不同方法:
- 直接使用 SQL 语句
- 使用 ADO 记录集(recordset)方法调用
BasicADO 客户机-服务器应用程序
在整篇文章中,我将用一个样本 Visual Basic 应用程序 BasicADO 的代码片段来演示如何使用 ADO 进行 DB2 应用程序开发。
图 1. BasicADO 样本应用程序
BasicADO 应用程序从一个具有六个基本 DB2 数据类型(IDENTITY、INTEGER、VARCHAR、DATE、TIME 和 DECIMAL)的表中选择、插入、更新和删除记录。
请参阅标题为
样本应用程序下载的一节,以获得关于下载、安装和运行该应用程序的指示信息。
选择 DB2 记录
选择 DB2 记录
通过使用针对 ADO Connection 对象执行的 SQL SELECT 语句,并使用 ADO Command 对象或 ADO Recordset 对象,您就可以使用 ADO 从 DB2 选择记录。
查询数据记录所需的典型步骤为:
- 创建并设置 ADO Connection 对象。
- 使用连接的
Open方法连接到 DB2 数据库。
- 通过将适当的 SQL SELECT 语句作为
CommandText,创建并设置 ADO Command 对象。
- 创建 ADO Recordset 对象,然后将其分配给通过调用命令的
Execute方法所产生的返回值。
- 使用连接的
Close方法关闭 ADO Connection 对象。
使用 IBMDADB2 创建并初始化 ADO Connection 对象
从 Visual Basic 应用程序访问 DB2 数据库要做的第一步是创建并设置所需的 ADO Connection 对象。要连接到 DB2,必须设置两个属性:
建议:连接到 DB2 数据库时请使用客户机端游标。这可以通过将值
adUseClient赋给
CursorLocation属性来实现。
因为 DB2 附带了自己的 OLE DB 提供程序 IBMDADB2,所以连接到 DB2 所需的连接字符串的格式如下:
Provider=IBMDADB2; DSN=DatabaseAlias;
|
您还可以按下面的格式将可选的用户名和密码包含到连接字符串中:
User ID=UserName; Password=UserPassword;
|
清单 1中的代码片段显示了创建并初始化 ADO Connection 对象的 GetConnection 函数。
清单 1. BasicADO — GetConnection 函数
' Create and return ADO Connection Object
Public Function GetConnection( _
strDBName As String, _
Optional strUserName As String = "", _
Optional strPassword As String = "") As ADODB.Connection
On Error GoTo GetConnection_ErrHandler
Dim strConnectionString As String
strConnectionString = "Provider=IBMDADB2; DSN=" & strDBName
If strUserName <> "" And strPassword <> "" Then
strConnectionString = strConnectionString & "; User ID=" & strUserName _
& "; Password=" & strPassword
End If
' Create new ADO connection object
Dim adoConnection As New ADODB.Connection
With adoConnection
.CursorLocation = adUseClient
.ConnectionString = strConnectionString
End With
' Return new ADO connection object
Set GetConnection = adoConnection
Set adoConnection = Nothing
Exit Function
GetConnection_ErrHandler:
MsgBox "Error Code: " & Err.Number & vbNewLine & _
"Description: " & Err.Description & vbNewLine & _
"Source: " & Err.Source, _
vbOKOnly + vbCritical
Err.Clear
Set GetConnection = Nothing
End Function
|
请注意,在对连接执行任何 SQL 之前,必须首先打开连接,并且必须在完成时关闭连接。这可以通过使用 ADO Connection 对象的
Open和
Close方法实现。
使用 IBM DB2 V8 开发外接程序
通过使用
Visual Basic 6 的 DB2 开发外接程序,您可以自动生成创建和初始化您工程数据库的 ADO Connection 对象所需的 ADO 代码。以上
清单 1中提供的样本代码就基于外接程序本身生成的代码。我强烈建议在使用 Visual Studio 6.0 构建 DB2 应用程序时使用 DB2 开发外接程序。
创建 ADO Command 对象
要对 DB2 数据库服务器执行任何 SQL,必须先创建并初始化 ADO Command 对象。然后可以使用 ADO Recordset 对象的
Open方法执行所期望的 SQL 命令。
清单 2中的代码片段显示了 QueryRecords 函数,它创建并初始化 ADO Command 对象并执行 ADO Recordset 对象的 Open 方法。
清单 2. BasicADO — QueryRecords 函数
Function QueryRecords(ByRef adoConnection As ADODB.Connection) As
ADODB.Recordset
'Create ADO objects
Dim adoCommand As ADODB.Command
Dim adoRecordSet As ADODB.Recordset
On Error GoTo QueryRecords_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
.CommandText = "SELECT tINT, tVARCHAR, tDATE, tTIME, tDECIMAL FROM BASICADO"
End With
'Create record set
Set adoRecordSet = New ADODB.Recordset
adoRecordSet.Open adoCommand, , adOpenStatic, adLockOptimistic
Set QueryRecords = adoRecordSet
Set adoRecordSet = Nothing
Set adoCommand = Nothing
Exit Function
QueryRecords_ErrHandler:
Call ShowAllErrors(adoConnection)
Set QueryRecords = Nothing
End Function
|
创建并初始化 ADO Command 对象
要使用 ADO Command 对象,您必须先创建一个该对象的新实例,然后初始化其所需的属性。
必须将
CommandType属性设置为
adCmdText以执行 SQL 语句。如果您选择调用数据库存储过程,则将该属性设置为
adCmdStoredProc。
必须将 CommandText 属性设置为要执行的实际 SQL 或存储过程名称。对于 BasicADO 应用程序,我们指定查询所有表记录的所有相关列所需的 SELECT 语句。
必须将
ActiveConnection属性设置为我们所期望的先前已打开的 ADO Connection 对象。
创建并初始化 ADO Recordset 对象
要执行 ADO Command 对象中包含的 SQL,必须创建 ADO Recordset 对象的新的实例,然后调用
Open方法,并传入我们所期望的 ADO Command 对象。Open 方法的其余必需参数包括
CursorType和
LockingType。
可将
CursorType参数设置为
adOpenStatic。请参考联机 ADO 文档以了解所有可能的值。可将
LockingType参数设置为
adLocOptimistic。请参考联机 ADO 文档以了解所有可能的值。
使用 IBM DB2 V8 开发外接程序
通过使用 Visual Basic 6 的 DB2 开发外接程序,您可以自动生成调用服务器端存储过程和函数所需的 ADO 代码。它创建 ADO Command 对象和 Recordset 对象,以及那些具有参数的过程和函数所必需的任何 ADO 参数对象。
您也可以调用 SQL Assist 查询构建器以图形方式构建 ADO Command 对象所需的 SQL。
我觉得非常有用的一个功能是在测试应用程序时对服务器端表的内容进行采样这一能力。
访问 ADO Recordset 数据
执行了返回结果集的 ADO 命令后,您可以使用 ADO Recordset 对象访问那些结果集。对于那些返回多个结果集的 ADO 命令,您可以使用 ADO Recordset 对象的
NextRecordSet方法移至下一个多记录结果集。
有三种方法可以访问当前结果集中当前行的各列:
无论使用哪种方法,您都可以使用以下访问机制来获取或设置各列的值:
SomeVar = Recordset!FiledName ' To lookup the field value
Recordset!FieldName = SomeValue ' To set the field value |
使用 Recordset!FieldName
通过使用 Recordset!FieldName 语法,您可以很方便地访问当前行的各列,该语法中的 FieldName 代表列名称。如果列名称是定界的,那么您应当避免使用这种表示法。字段名称是不区分大小写的。这是我最常使用的语法。
使用 Recordset.Fields("FieldName")
使用 Recordset.Fields("FieldName") 语法与使用 Recordset!FieldName 非常相似,不同之处在于此时可以使用定界的列名称。
使用 Recordset.Fields(FieldIndex)
对于那些不含列名称的结果集,或者为了更快地访问结果集的各列,您可以使用 Recordset.Fields(FieldIndex) 语法。该语法规定您必须知道结果集的各列的顺序。如果为了包含其它列而修改了查询,那么必须回头且调整字段索引。
使用 ADO Recordset 填充 ListView
您可以用编程方式通过迭代结果集的行并使用 ListView 的 Add 方法,将给定 ADO Recordset 对象的数据行填充到 Visual Basic ListView 对象中。
通过使用
MoveFirst、MoveLast、MoveNext和
MovePrevious这些方法,您可以在 ADO Recordset 的行之间来回移动。您还可以使用 EOF 布尔方法来检查是否到达结果集的末尾。
清单 3中的代码片段显示了 DisplayRecords 函数,该函数用
清单 2中所示的 QueryRecords 函数产生的记录填充了 BasicADO 应用程序的 ListView 对象。
清单 3. BasicADO — DisplayRecords 子例程
Private Sub DisplayRecords()
Dim adoRecordSet As ADODB.Recordset
Set adoRecordSet = modDBUtil.QueryRecords(adoCon)
'Populate list view with records manually
lstRecords.ListItems.Clear
If Not adoRecordSet Is Nothing Then
Dim lstItem As ListItem
While Not adoRecordSet.EOF()
Set lstItem = lstRecords.ListItems.Add(, , adoRecordSet!tINT)
lstItem.SubItems(1) = adoRecordSet!tVARCHAR & ""
lstItem.SubItems(2) = GetDateValue(adoRecordSet!tDATE & "")
lstItem.SubItems(3) = GetTimeValue(adoRecordSet!tTIME & "")
lstItem.SubItems(4) = FormatCurrency(adoRecordSet!tDECIMAL & "")
adoRecordSet.MoveNext
Wend
End If
Set adoRecordSet = Nothing
Set lstItem = Nothing
End Sub
|
提示 — 有效地处理空值
通过象上面所示的那样包括一个 & "",可以方便地处理空列值。代码片段表示空字符串被并置到字段值。这将避免在您将空字段值赋给 Visual Basic 变量时生成运行时错误。
作为另一种选择,您可以使用以下代码在进行赋值
之前检查空值:
If adoRecordSet.Fields("SomeField").ActualSize > 0 Then
SomeVar = adoRecordSet.Fields("SomeField")
End If
|
提示 — 格式化日期列
您可以使用 Format 或 FormateDateTime Visual Basic 函数来正确地格式化记录集的日期列。使用 Format 函数能给您较大的灵活性,因为它让您指定自己的定制格式。使用 FormateDateTime 让您使用标准的、特定于语言环境的日期格式化选项,如 vbShortDate、vbLongDate 和 vbGeneralDate。
在使用这些格式化函数之前,使用 DateValue Visual Basic 函数将值转换成正确的日期数据类型。
清单 4中的代码片段显示了 GetDateValue 函数,可使用该函数正确地格式化 DATE 列类型。
清单 4. BasicADO — GetDateValue 函数
Public Function GetDateValue(ByRef strDate As String) As String
If strDate <> "" Then
GetDateValue = Format(DateValue(strDate), "mm/dd/yyyy")
'GetDateValue = FormatDateTime(DateValue(strDate), vbGeneralDate)
Else
GetDateValue = ""
End If
End Function
|
提示 — 格式化时间列
与 DATE 数据类型不同,当显示 TIME 数据类型列的值时,您会看到一些后面跟着实际的时间值的伪日期。您可以使用 Format 或 FormateDateTime Visual Basic 函数正确地格式化记录集的日期列。使用 Format 函数能给您较大的灵活性,因为它让您指定自己的定制格式。使用 FormateDateTime 允许您使用标准的、特定于语言环境的时间格式化选项,如 vbShortTime 和 vbLongTime。
在使用这些格式化函数之前,使用 TimeValue Visual Basic 函数将值转换成正确的时间数据类型。
清单 5中的代码片段显示了 GetTimeValue 函数,可使用该函数正确地格式化 TIME 列类型。
清单 5. BasicADO — GetTimeValue 函数
Public Function GetTimeValue(ByRef strTime As String) As String
If strTime <> "" Then
GetTimeValue = Format(TimeValue(strTime), "hh:nn:ss")
'GetTimeValue = FormatDateTime(TimeValue(strTime), vbLongTime)
Else
GetTimeValue = ""
End If
End Function
|
提示 — 格式化小数列
您可以用不同的方式格式化小数类型。譬如:
- FormatCurrency 函数将小数转换为特定于语言环境的货币值。
- FormatPercent 函数将小数转换为百分比值。
- FormatNumber 函数将小数转换为有指定数目的前导零和/或小数位的特定数字值。
插入新的 DB2 记录
通常有必要根据用户输入或某些生成的数据将新的记录插入现有的数据库表中。您可以用不同的方法完成这一操作。下面是两个这样的方法:
- 使用 SQL INSERT 语句
- 使用 ADO Recordset 对象的
Add方法
这两个方法之间的主要差异在于:对每个要插入的记录都需要使用一条 INSERT 语句;而通过使用 ADO Recordset 方法,您可以批处理多个插入,然后使用 ADO Recordset 对象的
Update方法把这些插入作为一个单元来执行。
使用 INSERT 语句进行插入
要使用 SQL INSERT 语句插入记录,必须:
- 用正确的 SQL INSERT 语句作为命令文本,创建并初始化 ADO Command 对象。可使用“?”参数标记符将实际的列值作为位置参数传递。这允许使用同一 ADO 命令插入多条记录。
- 将位置参数的值设置为新行的实际列值。
- 使用 ADO Command 对象的 Execute 方法执行命令。
- 复位参数值,然后对每个要插入的其它行重新执行命令。
清单 6中的代码片段显示了 InsertUsingInsert 子例程,它使用一条 SQL INSERT 语句执行多行插入操作。使用同一 ADO 命令来插入多行。
清单 6. BasicADO — InsertUsingInsert 子例程
Sub InsertUsingInsert(ByRef adoConnection As ADODB.Connection)
'Create ADO objects
Dim adoCommand As ADODB.Command
On Error GoTo InsertUsingInsert_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
.CommandText = "INSERT INTO BASICADO (tINT, tVARCHAR, tDATE,
tTIME, tDECIMAL) VALUES(?,?,?,?,?)"
End With
'Add Parameters to the Command object
Dim adoParm_tINT As Parameter
Set adoParm_tINT = adoCommand.CreateParameter("tINT", _
adInteger, _
adParamInput)
Call adoCommand.Parameters.Append(adoParm_tINT)
Dim adoParm_tVARCHAR As Parameter
Set adoParm_tVARCHAR = adoCommand.CreateParameter("tVARCHAR", _
adVarChar, _
adParamInput, _
256)
Call adoCommand.Parameters.Append(adoParm_tVARCHAR)
Dim adoParm_tDATE As Parameter
Set adoParm_tDATE = adoCommand.CreateParameter("tDATE", _
adDBDate, _
adParamInput)
Call adoCommand.Parameters.Append(adoParm_tDATE)
Dim adoParm_tTIME As Parameter
Set adoParm_tTIME = adoCommand.CreateParameter("tTIME", _
adDBTime, _
adParamInput)
Call adoCommand.Parameters.Append(adoParm_tTIME)
Dim adoParm_tDECIMAL As Parameter
Set adoParm_tDECIMAL = adoCommand.CreateParameter("tDECIMAL", _
adDecimal, _
adParamInput)
Call adoCommand.Parameters.Append(adoParm_tDECIMAL)
'Set the values and execute the 1st insert
adoParm_tINT.Value = 1
adoParm_tVARCHAR.Value = "Hello world at 1!"
adoParm_tDATE.Value = "21/02/1997"
adoParm_tTIME.Value = "12:00:01"
adoParm_tDECIMAL.Value = "1111.11"
Call adoCommand.Execute
'Set the values and execute the 2nd insert
adoParm_tINT.Value = 2
adoParm_tVARCHAR.Value = "Hello world at 2!"
adoParm_tDATE.Value = "01/03/1999"
adoParm_tTIME.Value = "12:00:02"
adoParm_tDECIMAL.Value = "2222.22"
Call adoCommand.Execute
Set adoCommand = Nothing
Exit Sub
InsertUsingInsert_ErrHandler:
Call ShowAllErrors(adoConnection)
End Sub
|
创建并初始化 ADO 参数对象
在使用需要位置参数或存储过程参数的 ADO Command 时,可以使用 ADO Command 的 ADO Parameters 集合来设置和获取这些参数的值。
必须创建并初始化每个参数对象,然后将其附加到 ADO Command 对象的参数集合中。必须在执行命令之前设置输入参数值。必须在执行命令之后读取输出参数值。
正如
清单 6所示,按以下步骤使用命令参数:
- 使用命令的
CreateParameter方法创建新的 ADO Parameter 对象。应指定参数名称、类型、大小和可选值。
- 使用集合的
Append方法将参数追加到命令的
Parameters集合。
- 通过将输入值赋给参数的
Value属性指定任何输入参数的值。
- 执行命令。
- 使用参数的
Value属性读取任何输出参数的值。
重要:对每个参数使用正确映射至 DB2 SQL 类型的 ADO 数据类型。如果您使用 DB2 V8.1 开发外接程序,那么将自动为您创建并设置存储过程参数,这将使您更方便地开发基于 DB2 的应用程序。
使用 ADO Recordset 进行插入
要使用 ADO Recordset 插入记录,必须:
- 创建 ADO Command 以及作为结果产生的 ADO 记录集以便保存新记录列表。ADO 记录集无需包含任何记录。重要的是,对于要插入的行要有正确的列的列表。为此,ADO Command 的 SELECT 语句可能有一条带假(false)条件的 WHERE 子句。
- 打开 ADO 连接。
- 执行 ADO 命令并检索可能的空 ADO 记录集。
- 使用
AddNew方法将新记录追加到 ADO 记录集中。
- 使用访问记录集数据的三种方法中的任意一种设置每个新增记录各列的值。
- 调用 ADO 记录集的
Update方法将新的记录插入 DB2 表。
- 关闭 ADO 连接。
清单 7中的代码片段显示了 InsertUsingRecordset 子例程,它使用 ADO Recordset 对象执行多行插入操作。
清单 7. BasicADO — InsertUsingRecordset 子例程
Sub InsertUsingRecordset(ByRef adoConnection As ADODB.Connection)
'Create ADO objects
Dim adoCommand As ADODB.Command
Dim adoRecordSet As ADODB.Recordset
On Error GoTo InsertUsingRecordset_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
.CommandText = "SELECT tINT, tVARCHAR, tDATE, tTIME, tDECIMAL FROM
BASICADO WHERE tINT = 0"
End With
'Create record set
Set adoRecordSet = New ADODB.Recordset
adoRecordSet.Open adoCommand, , adOpenStatic, adLockOptimistic
'Update values for row 1
adoRecordSet.AddNew
adoRecordSet!tINT = 1
adoRecordSet!tVARCHAR = "Hello world at 1!"
adoRecordSet!tDATE = "21/02/1997"
adoRecordSet!tTIME = "12:00:01"
adoRecordSet!tDECIMAL = "1111.11"
'Update values for row 2
adoRecordSet.AddNew
adoRecordSet!tINT = 2
adoRecordSet!tVARCHAR.Value = "Hello world at 2!"
adoRecordSet!tDATE = "01/03/1999"
adoRecordSet!tTIME = "12:00:02"
adoRecordSet!tDECIMAL = "2222.22"
'Execute all inserts
Call adoRecordSet.Update
Set adoRecordSet = Nothing
Set adoCommand = Nothing
Exit Sub
InsertUsingRecordset_ErrHandler:
Call ShowAllErrors(adoConnection)
End Sub
|
请注意,必须用正确的 DATE 和 TIME 值字符串来为新插入的记录设置相应的列值。
更新现有的 DB2 记录
记录常常被更新,这是数据库应用程序的一部分。这种更新可能由于用户修改给定对象记录的属性对话框中的字段而产生的,也可能由某些用户操作或事务间接产生。您可以用不同的方法完成这一操作。下面是两个这样的方法:
- 使用 SQL UPDATE 语句
- 通过 ADO Recordset 对象直接操作字段值
使用 Recordset 更新机制的主要优点之一:出于显示的目的,通常您已经查询了那些记录;这样,更新记录就成了一件简单的事情,在将记录发回服务器之前先在客户机上修改它们。相反,UPDATE 语句必须通过使用 WHERE 子句在服务器上执行。这意味着您需要重新标识那些要更新的记录。
使用 UPDATE 语句进行更新
要使用 SQL UPDATE 语句更新记录,必须:
- 用正确的 SQL UPDATE 语句作为命令文本,创建并初始化 ADO Command 对象。通过使用“?”参数标记符,可以将实际的列的更新值和这些列的 WHERE 子句值作为位置参数传递。这允许使用同一 ADO 命令进行动态更新,更新多条记录或更新多组记录。
- 将位置参数的值设置为实际列的值。
- 使用 ADO Commmand 对象的
Execute方法执行命令。
- 复位参数值,然后对每个要更新的其它行或几组行重新执行命令。
清单 8中的代码片段显示了 UpdateUsingUpdate 子例程,它使用 SQL UPDATE 语句执行多行更新。同一 ADO 命令可用于更新多行或多组行。
清单 8. BasicADO — UpdateUsingUpdate 子例程
Sub UpdateUsingUpdate(ByRef adoConnection As ADODB.Connection)
'Create ADO objects
Dim adoCommand As ADODB.Command
On Error GoTo UpdateUsingUpdate_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
.CommandText = "UPDATE BASICADO " & _
"SET tVARCHAR = 'Bye world!' " & _
"WHERE tINT = ?"
End With
'Add Parameters to the Command object
Dim adoParm_tINT As Parameter
Set adoParm_tINT = adoCommand.CreateParameter("tINT", _
adInteger, _
adParamInput)
Call adoCommand.Parameters.Append(adoParm_tINT)
'Update all records having tINT = 1
adoParm_tINT.Value = 1
Call adoCommand.Execute
Set adoCommand = Nothing
Exit Sub
UpdateUsingUpdate_ErrHandler:
Call ShowAllErrors(adoConnection)
End Sub
|
使用 ADO Recordset 进行更新
要使用 ADO Recordset 更新记录,必须:
- 创建 ADO Command 以及作为结果产生的 ADO 记录集以便保存将被显示并稍后更新的记录列表。ADO 记录集不必只包含要更新的那些记录。
- 打开 ADO 连接。
- 执行 ADO 命令并将合适行的初始列表作为 ADO 记录集检索。您必须包括主键列以便 Recordset 更新能够进行。请参阅下面的
提示。
- 使用
Find方法迭代并定位 ADO 记录集中的每条记录。
- 通过使用访问记录集数据的三种方法中的任意一种,用新值设置每条要更新的记录各列的值。
- 调用 ADO 记录集的
Update方法来更新 DB2 表中的多个行。
- 关闭连接。
清单 9中的代码片段显示了 UpdateUsingRecordset 子例程,它使用 ADO Recordset 对象执行多行更新。
清单 9. BasicADO — UpdateUsingRecordset 子例程
Sub UpdateUsingRecordset(ByRef adoConnection As ADODB.Connection)
'Create ADO objects
Dim adoCommand As ADODB.Command
Dim adoRecordSet As ADODB.Recordset
On Error GoTo UpdateUsingRecordset_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
'Update requires primary key, so need to select tKEY
.CommandText = "SELECT tKEY, tINT, tVARCHAR, tDATE, tTIME, tDECIMAL
FROM BASICADO"
End With
'Create record set
Set adoRecordSet = New ADODB.Recordset
adoRecordSet.Open adoCommand, , adOpenStatic, adLockOptimistic
'Update all records having tINT = 2 (requires primary key)
Call adoRecordSet.Find("tINT = 2")
While Not adoRecordSet.EOF()
adoRecordSet!tVARCHAR = "Bye world!"
adoRecordSet.MoveNext
Call adoRecordSet.Find("tINT = 2")
Wend
'Workaround for BOF ADO bug!
If adoRecordSet.RecordCount > 0 Then
adoRecordSet.MoveFirst
End If
'Execute the update
Call adoRecordSet.Update
Set adoRecordSet = Nothing
Set adoCommand = Nothing
Exit Sub
UpdateUsingRecordset_ErrHandler:
Call ShowAllErrors(adoConnection)
End Sub
|
提示 — 包括主键
尽管记录对象中的主键极少被更新,但您必须在查询中包括主键列。这是为了允许 ADO 通过使用这些主键来标识必须更新的记录,以便生成正确的底层 UPDATE SQL。
没有包括主键将导致生成运行时错误,如
图 2所示。
图 2. BasicADO — 不使用主键更新时生成的错误
提示 — 避免 EOF ADO 错误
在使用 BasicADO 应用程序时,我注意到当 ADO 记录集行索引经过最后一个记录时调用
Update方法会引发一个错误。正如您在
清单 9中的 UpdateUsingRecordset 代码片段中看到的那样,我们使用一个 while 循环遍历所有的记录。如果我们在循环之后直接调用
Update方法,我们会看到一个如
图 3所示的错误消息。
图 3. BasicADO — 在 EOF 上调用 Update 时生成的错误
要避免这一错误,先将记录指针移到 ADO 记录集中的第一条记录,然后再调用
Update方法。要做到这一点,您可以在调用
Update之前插入以下代码片段:
'Workaround for EOF ADO bug!
If adoRecordSet.RecordCount > 0 Then
adoRecordSet.MoveFirst
End If
|
删除旧的 DB2 记录
从表中删除记录和更新记录类似,不同之处在于不是修改行的列值,实际上是删除行。您可以用下列不同的方法删除行:
- 使用 SQL DELETE 语句
- 调用 ADO Recordset 对象的 Delete 方法
和前面讨论的更新操作一样,使用 Recordset 删除机制的一个主要优点之一是:出于显示的目的,通常您已经查询了那些记录;这样,删除记录就成了一件简单的事情:在将已更新的记录发回服务器之前先在客户机上删除它们。相反,DELETE 语句必须使用 WHERE 子句在服务器上执行。这意味着您需要重新标识那些要删除的记录。
使用 DELETE 语句进行删除
要使用 SQL DELETE 语句删除记录,必须:
- 用正确的 SQL DELETE 语句作为命令文本,创建并初始化 ADO Command 对象。通过使用“?”参数标记符,可以将标识要删除的行所需的列的 WHERE 子句值作为位置参数传递。这允许使用同一 ADO 命令动态删除多条记录。
- 将位置参数的值设置为标识要删除的记录所需的实际列值。
- 使用 ADO Command 对象的 Execute 方法执行命令。
- 复位参数值,然后对每个要删除的其它行或几组行重新执行命令。
清单 10中的代码片段显示了 DeleteUsingDelete 子例程,它使用 SQL DELETE 语句执行多行删除操作。同一 ADO 命令可用于删除多行或多组行。
清单 10. BasicADO — DeleteUsingDelete 子例程
Sub DeleteUsingDelete(ByRef adoConnection As ADODB.Connection)
'Create ADO objects
Dim adoCommand As ADODB.Command
On Error GoTo DeleteUsingDelete_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
.CommandText = "DELETE FROM BASICADO WHERE tINT = ?"
End With
'Add Parameters to the Command object
Dim adoParm_tINT As Parameter
Set adoParm_tINT = adoCommand.CreateParameter("tINT", _
adInteger, _
adParamInput)
Call adoCommand.Parameters.Append(adoParm_tINT)
'Delete all records having tINT = 1
adoParm_tINT.Value = 1
Call adoCommand.Execute
Set adoCommand = Nothing
Exit Sub
DeleteUsingDelete_ErrHandler:
Call ShowAllErrors(adoConnection)
End Sub
|
使用 ADO Recordset 进行删除
要使用 ADO Recordset 删除记录,必须:
- 创建 ADO Command 以及作为结果产生的 ADO 记录集以便保存要显示的记录的列表以及以后要删除的子集。ADO 记录集不必只包含要删除的那些记录。
- 打开 ADO 连接。
- 执行 ADO 命令并将合适行的初始列表检索为 ADO 记录集。您必须包括主键列以便 Recordset 更新能够进行。
- 使用
Find方法迭代并定位 ADO 记录集中要删除的每条记录。
- 对 ADO 记录集调用
Delete方法以删除记录。
- 继续执行记录集迭代直到完成工作。
- 调用 ADO 记录集的
Update方法将多行删除传递给 DB2 表。
- 关闭 ADO 连接。
清单 11中的代码片段显示了 DeleteUsingRecordset 子例程,它使用 ADO Recordset 对象执行多行删除。
清单 11. BasicADO — DeleteUsingRecordset 子例程
Sub DeleteUsingRecordset(ByRef adoConnection As ADODB.Connection)
'Create ADO objects
Dim adoCommand As ADODB.Command
Dim adoRecordSet As ADODB.Recordset
On Error GoTo DeleteUsingRecordset_ErrHandler
Set adoCommand = New ADODB.Command
With adoCommand
.CommandType = adCmdText
.ActiveConnection = adoConnection
'Delete requires primary key, so need to select tKEY
.CommandText = "SELECT tKEY, tINT, tVARCHAR, tDATE, tTIME, tDECIMAL
FROM BASICADO"
End With
'Create record set
Set adoRecordSet = New ADODB.Recordset
adoRecordSet.Open adoCommand, , adOpenStatic, adLockOptimistic
'Delete all records having tINT = 2 (requires primary key)
Call adoRecordSet.Find("tINT = 2")
While Not adoRecordSet.EOF()
adoRecordSet.Delete
adoRecordSet.MoveNext
Call adoRecordSet.Find("tINT = 2")
Wend
'Workaround for EOF ADO bug!
If adoRecordSet.RecordCount > 0 Then
adoRecordSet.MoveFirst
End If
'Execute the delete
Call adoRecordSet.Update
Set adoRecordSet = Nothing
Set adoCommand = Nothing
Exit Sub
DeleteUsingRecordset_ErrHandler:
Call ShowAllErrors(adoConnection)
End Sub
|
提示 — 包括主键
必须在查询中包括主键列,以便使用记录集执行删除。这是为了允许 ADO 使用这些主键来标识必须删除的记录,以便生成正确的底层 DELETE SQL。
结束语
IBM DB2 V8.1 Development Add-In for Visual Basic 6 是很棒的工具,它极大简化了 n 层应用程序开发。本文详细描述了如何使用 ADO 编程 API 执行四种基本的数据库操作:SELECT、INSERT、DELETE 和 UPDATE。本文还描述了一些有用的提示和技巧,它们应能够帮助您使用 ADO 开发高质量的 DB2 应用程序。
样本应用程序下载
在整篇文章中,我用一个样本 Visual Basic 应用程序 BasicADO 的代码片段演示了如何使用 ADO 进行 DB2 应用程序开发。本节向您提供下载、安装和运行该应用程序的指示信息。
该应用程序是
按原样
提供的,未承诺任何担保或支持。您可以在自己的项目中自由地使用和再分发该应用程序代码的全部或一部分。
下载 BasicADO 应用程序
BasicADO 应用程序是一个 Visual Basic 6.0 工程,带有创建所需表的 DB2 脚本文件。basicado.zip 文件包含以下文件:
-
BasicADO.vbp— 工程文件
-
frmMain.frm— 主应用程序窗体
-
modDBUtil.bas— 包含 DB2 ADO 函数的模块
-
createtb.bat— 运行 createtb.ddl DB2 脚本文件的批处理文件
-
createtb.ddl— 连接到 SAMPLE 数据库并创建所需表所需的 DB2 脚本文件
BasicADO 应用程序的系统需求:
- IBM DB2 通用数据库 V8.1 或更高版本
- IBM DB2 OLE DB 提供程序(IBMDADB2)
- Microsoft Windows 2000®、XP® 或 NT®
- Microsoft Visual Studio V6.0
- MDAC 2.6 或更高版本
| 描述 | 文件类型 | 文件大小 | 下载方法 | | basicado.zip | zip | 7 KB | HTTP
|
安装 BasicADO 应用程序
尽管 BasicADO 应用程序被配置为使用 SAMPLE 数据库运行,但您可以用自己的数据库名称更改 SAMPLE 的所有实例。涉及的文件是
createtb.ddl 和
frmMain.frm 。
在启动 Visual Basic 之前,运行创建 BasicADO 应用程序表所需的脚本。为此,只需打开 DB2 命令窗口并运行批处理文件
createtb.bat 。
既然您已经创建了所需的表,那么只需启动 Visual Basic,然后打开
BasicADO.vbp 工程文件。
运行 BasicADO 应用程序
要运行 BasicADO 应用程序,您需要将工程编译成可执行文件,或直接在 Visual Basic 中运行它。
运行该应用程序之后,您将看到先前
图 1所示的窗体。该应用程序期望您完成一系列预先定义的操作;因此,操作按键按照这一顺序启用或禁用:
- 连接到数据库
- 使用
INSERT进行插入
- 使用记录集进行插入
- 使用
UPDATE进行更新
- 使用记录集进行更新
- 使用
DELETE进行删除
- 使用记录集进行删除
- 断开连接
关于作者  | |  | Essma Hasin是获得认证的 Visual Basic 和 C 程序员,她是 Neneva Technologies 的质量保证工程师,这是一家专门利用 IBM DB2 通用数据库和 Microsoft .Net 框架为中小型公司构建定制解决方案的咨询公司。可以通过
essma@neneva.com与 Essma 联系。
|
对本文的评价
|