VB6 数据库程序设计

错误更正


更正日期:99/06/07


p.169 程序:

原书内容:

Private Sub Adodc1_Error(DataErr AS Integer, Response _
As Integer)
    If ErrorNumber = 3662 Then
        '处理错误程序码,例如显示错误信息
        Response = 0 '请Adodc控件不必再显示任何信息
    End If
End Sub

更正后内容:

Private Sub Adodc1_Error(ByVal ErrorNumber As Long, Description As String,
ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal
HelpContext As Long, fCancelDisplay As Boolean)
    If ErrorNumber = 16389 Then
        '处理错误程序码,例如显示错误信息
        fCancelDisplay = True '请Adodc控件不必再显示任何信息
    End If
End Sub

更正日期:99/05/26


p.90 第一段文字:

原书内容:

执行「Recordset.Update」语句将数据记录(也就是所有栏位)数据写
缓冲区之前。

更正后内容:

执行「Recordset.Update」语句将数据记录(也就是所有栏位)数据写
数据库之前。

p.120 参考解答:

原书内容:

(1) Where 成交量 >= 3500
(2) Where 股票名称 = '旗阵'
(3) Where 涨跌 > 3 Or 涨跌 < -3
(4) Where 交易日期 > #97/8/30#
(5) Where 股票名称 Like "台*"
(6) Where 股票名称 Like "**"
(7) Where 股票名称 Is Null
(8) Where 股票名称 Like "*泥"
(9) Where Len(股票名称) < 3

更正后内容:

(1) Where 成交量 >= 3500
(2) Where 股票名称 = '旗阵'
(3) Where 涨跌 > 3 Or 涨跌 < -3
(4) Where 交易日期 > #97/8/30#
(5) Where 股票名称 Like "台%"
(6) Where 股票名称 Like "%%"
(7) Where 股票名称 Is Null
(8) Where 股票名称 Like "%泥"
(9) Where Len(股票名称) < 3

特别说明:

* 是 DAO(Data Access Objects) SQL 的万用字符, 而 % 是 ADO (ActiveX Data Objects) SQL 的万用字符, 对于写过 VB5 数据库程序的人来说, 往往会顺手写 * 为 SQL 的万用字符。 (注:VB6 可以同时使用 DAO 及 ADO 来存取数据库,但由于书本的介绍以 ADO 为主,所以应该采用 % 为万用字符)

p.120 参考解答:

原书内容:

(1) Select *, 涨跌/收盘价*100 As 涨幅 From 股票行情表
Order By 涨跌/收盘价*100
(2) Select *, (最高价-最低价)/收盘价*100 As 震荡幅度
From 股票行情表 Order By (最高价-最低价)/收盘价*100
(3) Select *, 收盘价*成交量 As 成交金额 From 股票行情表
Order By 收盘价*成交量

更正后内容:

(1) Select *, 涨跌/收盘价*100 As 涨幅 From 股票行情表
Order By 涨跌/收盘价*100 Desc
(2) Select *, (最高价-最低价)/收盘价*100 As 震荡幅度
From 股票行情表 Order By (最高价-最低价)/收盘价*100 Desc
(3) Select *, 收盘价*成交量 As 成交金额 From 股票行情表
Order By 收盘价*成交量 Desc

p.167 最后一行、p.169 最后一行、p.170 第一段程序:

原书内容: -2147217887
更正后内容: -2147467259


更正日期:99/04/23


p.47 第一段文字

原书内容:

笔者判定这是 VB 的 bug,经研究之后,找到避开这个 bug 的方法 
-- 在 Delete 方法之后加上 DoEvents 语句,修改后的程序如下:

Adodc1.Recordset.MoveFirst
Adodc1.Recordset.Delete
DoEvents
Adodc1.Recordset.Delete
DoEvents
Adodc1.Recordset.Delete
DoEvents

更正后内容:(致歉! 这不是 VB 的错误,是笔者一时糊涂, 弄错了)

当第一个 Delete 方法被执行之后,目前数据记录即被删除,接着目前
数据记录便不存在,以致再执行第二个 Delete 及 第三个 Delete 都
会产生错误,修正的方法是在删除目前数据记录之后,利用 MoveNext 
方法将目前数据记录设定到下一笔:
Adodc1.Recordset.MoveFirst
Adodc1.Recordset.Delete
Adodc1.Recordset.MoveNext
Adodc1.Recordset.Delete
Adodc1.Recordset.MoveNext
Adodc1.Recordset.Delete

特别说明:为什么 DoEvents 也能够解决连续 Delete 的问题

其实 DoEvents(原来的作用是让程序暂停一下) 并不具备将目前数据记录移到
下一笔的功用, 当我们暂停程序时,DataGrid 会获得 CPU 的使用权(注:
虽然 DataGrid 属于程序的一部分, 但对于 Windows 来说, 它也是独立的视
窗, 所以一样会因事件驱动而被执行), 所以就在程序暂停的时候,DataGrid
会主动将目前数据记录移到下一笔, 这也使得 DoEvents 好像具备就目前数据
录移到下一笔的功用,但实际上, 将目前数据记录移到下一笔的却是 DataGrid。

由于我们可能在没有使用 DataGrid 的情况下(例如直接利用第 8 章介绍的 ADO
对象), 而使用 Recordset.Delete 方法来删除数据记录, 若是此一情况, DoEvents
就会充分暴露出它不具备将目前数据记录移到下一笔的功能。

p.47 参考解答:

原书内容:

Adodc1.Recordset.MoveFirst
While Not Adodc1.Recordset.EOF
    If Adodc1.Recordset("涨跌") = 0 Then
        Adodc1.Recordset.Delete
        DoEvents
    Else
        Adodc1.Recordset.MoveNext
    End If
Wend

更正后内容:

承续上一错误的更正说明,程序应该改成:
Adodc1.Recordset.MoveFirst
While Not Adodc1.Recordset.EOF
    If Adodc1.Recordset("涨跌") = 0 Then
        Adodc1.Recordset.Delete        
    End If
    Adodc1.Recordset.MoveNext
Wend

更正日期:99/04/16


p.43 「自我练习」上一行程序

原书内容:

Data1.Recordset.Fields("栏位名称").Value

更正后内容:

Adodc1.Recordset.Fields("栏位名称").Value

p.210 表格

原书内容:

AbsolutePosition的属性值 意 义
adPosEOF 目前数据记录移过了第一笔
adPosBOF 目前数据记录移过了最后一笔
adPosUnknown 无法判定目前数据记录的位置, 对于一个空的Recordset对象而言, 目前数据记录的绝对位置就等于此一属性值。

更正后内容:

AbsolutePosition的属性值 意 义
adPosBOF 目前数据记录移过了第一笔
adPosEOF 目前数据记录移过了最后一笔
adPosUnknown 无法判定目前数据记录的位置, 对于一个空的Recordset对象而言, 目前数据记录的绝对位置就等于此一属性值。

p.206 最下面两行程序

原书内容:

rs.CursorLocation = adUseClient
rs.Open 数据表或SQL指令, conn, adOpenDynamic, adLockOptimistic

更正后内容:

rs.CursorLocation = adUseClient
rs.Open 数据表或SQL指令, conn, adOpenStatic, adLockBatchOptimistic

特别说明:

原书内容执行之后并不会产生错误, 而且所得到的 Recordset 也和书本的说明一样, 具有完整的 Recordset 功能, 但原书内容却很容易让人产生误会, 主要原因是我们一旦将 CursorLocation 属性指定成 adUseClient 之后, Open 方法的 CursorType 参数(参数三) 不管如何指定, Recordset 对象最后的 CursorType 都会被 ADO 转变成 adOpenStatic, 而 LockType 参数(参数四) 不管被指定成 adLockOptimistic 、 adLockPessimistic 、或 adLockBatchOptimistic, LockType 都会被转换成 adLockBatchOptimistic。所以在此将 Open 语句改成

rs.Open 数据表或SQL指令, conn, adOpenStatic, adLockBatchOptimistic

这样子方才不会引起误会。

p.389 表格

原书内容:

RptTextBox 属性 属性值
股票代号 Command1 股票代号
以下略
...

更正后内容:

RptTextBox DataMember 属性 DataField属性
股票代号 Command1 股票代号
以下略
...

p.505 图-7 底下的小图

原书内容:

更正后内容:

p.512 最 下面

原书内容:

就程序部分,则保留cmdOpenDB_Click事件程序(「打开数据库」
命令钮)、cmdOpenDB_Click事件程序(「停止下载」命令钮)、

更正后内容:

就程序部分,则保留cmdOpenDB_Click事件程序(「打开数据库」
命令钮)、cmdStop_Click事件程序(「停止下载」命令钮)、


p.45

原书内容:

(3):没有目前数据记录
(10):此一存取格式的栏位名称不能接受变量

更正后内容:

(3):没有目前数据记录          (7) 参阅 p.43
(10):此一存取格式的栏位名称不能接受变量