MS Access 2013 从 VBA 调用插入查询并出现奇怪的错误

Posted

技术标签:

【中文标题】MS Access 2013 从 VBA 调用插入查询并出现奇怪的错误【英文标题】:MS Access 2013 calling insert queries from VBA with strange errors 【发布时间】:2016-08-23 16:32:35 【问题描述】:

我有一个保存的插入查询来向表中添加一条记录。查询的参数来自未绑定的表单。该表的 2 个字段是是/否数据类型。这些字段的表单控件是一个复选框。

这是保存的查询“qryInsertLog”

PARAMETERS UserPar Text ( 255 ), ApprovedByPar Text ( 255 ), CCedByPar Text ( 255 ), 
           UnitIdPar Short, NotePar LongText, Z3Par Bit, Z5Par Bit, FollowupNotesPar LongText;

INSERT INTO tblLogBook ( [User], ApprovedBy, CCedBy, UnitID, Notes, Z3, Z5, FollowupNotes )

SELECT [UserPAR] AS Expr1, [ApprovedByPar] AS Expr2, [CCedByPar] AS Expr3, 
       [UnitIDPar] AS Expr4, [NotePar] AS Expr5, [Z3Par] AS Expr6, [Z5Par] AS Expr7, 
       [FollowupNotesPar] AS Expr10;

这是绑定到表单上的保存按钮的 VBA 代码:

Private Sub cmdSaveandNew_Click()

Dim db As DAO.Database
Dim qdf1 As DAO.QueryDef

Set db = CurrentDb
Set qdf1 = db.QueryDefs("qryInsertLog")

'put form parameters into insert query
qdf1.Parameters(0).Value = Me.cboUser.Value
qdf1.Parameters(1).Value = Me.cboApprover.Value
qdf1.Parameters(2).Value = Me.cboCCer.Value
qdf1.Parameters(3).Value = Me.cboUnit.Value
qdf1.Parameters(4).Value = Me.txtNotes.Value
qdf1.Parameters(5).Value = Me.chkZ3.Value
qdf1.Parameters(6).Value = Me.chkz5.Value
qdf1.Parameters(7).Value = Me.txtFollowup.Value

qdf1.Execute

Set qdf1 = Nothing
Call resetForm

End Sub

“resetForm”是一个简单地将表单控件返回到其默认值的例程。

当我点击我的保存按钮时,有时会添加记录,但没有获得 Me.chkZ3.Value 和 Me.chkZ5.Value 的正确值(这意味着如果我检查了它们,记录会使用这些值输入为错误的)。几次点击保存按钮后,我开始收到以下错误:

Run-time error '3000':

Reserved error (-3033); there is no message for this error.

然而,最有趣的部分是,当我将查询修改为仅包含 1 个是/否字段时,我没有收到任何错误,并且记录已正确更新。

这到底是怎么回事?

编辑:我忘了提到,当我从“访问对象”窗口(而不是 VBA)运行查询时,它完全可以正常工作。

【问题讨论】:

至少有一个消息来源说 -3033 是权限错误。 (groups.google.com/forum/#!topic/…) 至于为什么只有在使用两个复选框时才会发生...不知道 如果您将PARAMETERS 声明中的Bit 更改为Short(甚至Long),它会更好(或根本没有?)? 更改参数数据类型声明时根本不起作用。 其中一个复选框是否设置为三态? 两者都具有 No 的三重状态 【参考方案1】:

问题在于LongText 参数。我尝试了类似的查询:

PARAMETERS pText1 Text ( 255 ), pInt1 Short, pMemo1 LongText, pYesno1 Bit, pYesno2 Bit;
INSERT INTO ForInsert ( text1, int1, Memo1, yesno1, yesno2 )
SELECT [pText1] AS A1, [pInt1] AS A2, [pMemo1] AS A3, [pYesno1] AS A4, [pYesno2] AS A5;

使用此代码

Set db = CurrentDb
Set qdf1 = db.QueryDefs("qAppForInsert")

qdf1.Parameters(0).Value = "asdf"
qdf1.Parameters(1).Value = 77
qdf1.Parameters(2).Value = String(3, "a")
qdf1.Parameters(3).Value = True
qdf1.Parameters(4).Value = False

qdf1.Execute

以及 LongText 参数的各种长度 (2, 10, 3)。

导致这个疯狂的数据(是/否字段总是yesno1 = Trueyesno2 = False!):

+----+-------+------+------------+--------+--------+
| ID | text1 | int1 |   Memo1    | yesno1 | yesno2 |
+----+-------+------+------------+--------+--------+
|  8 | asdf  |   77 | aa         | True   | False  |
|  9 | asdf  |   77 | aaaaaaaaaa | False  | False  |
| 10 | asdf  |   77 | aaa        | False  | True   |
+----+-------+------+------------+--------+--------+

显然,对于 LongText 参数,您最好使用 RecordSet.AddNew 而不是参数化查询。

反正参数是limited to 255 characters。

附录

如果我在循环中运行代码来查找系统,我也会得到Reserved error (-3033)

【讨论】:

使用 RecordSet.AddNew 效果很好。非常感谢您的帮助!【参考方案2】:

在将它们分配给表格之前,您可能应该在表单字段中添加更多错误跟踪和检查 Null 值。话虽如此,这一修复可能会解决您的直接问题。

我假设您的 Z3 和 Z5 字段是位字段 - 因为这就是您声明匹配参数类型的方式。

如果是这样,您可能应该捕获 Null 复选框并将 true(-1) 转换为 1

' Set to 0 if checkbox is Null, Set to 1 if checked=true
' Bit fields can't take -1 values
qdf1.Parameters(5).Value = IIf(Nz(Me.chkZ3.Value, 0), 1, 0)
qdf1.Parameters(6).Value = IIf(Nz(Me.chkz5.Value, 0), 1, 0)

作为旁注,我还建议使用命名参数而不是数字索引,以防它们的顺序发生变化 - 并且为了可读性和未来维护方便

代替

qdf1.Parameters(0).Value = Me.cboUser.Value

使用

qdf1.Parameters("UserPar").Value = Me.cboUser.Value

【讨论】:

以上是关于MS Access 2013 从 VBA 调用插入查询并出现奇怪的错误的主要内容,如果未能解决你的问题,请参考以下文章

MS Access:使用 VBA 进行 SQL 插入的日期格式

我希望从 ms-access 2013 数据库中的所有表单、报告和模块中导出 vba 源代码

在列表框 ms-access 2013 VBA 中将多个不同的字段作为列表项返回

从 C#.NET 应用程序调用 MS Access 中的 VBA 代码

Access 2013 - VBA - 记录集插入获取 ID

大型记录集 (VBA) 的 MS Access 插入慢