访问VBA - 运行时错误'3197'

时间:2011-11-01 10:58:11

标签: mysql ms-access vba

我正在尝试运行以下代码来循环记录集并在必要时进行更新。

我有一个连接到MySql后端的Microsoft Access数据库。每当我运行此代码时,我都会收到以下错误:

  

Microsoft Office Access数据库引擎已停止该过程,因为您和另一个用户正在尝试同时更改相同的数据。

代码如下:

Private Sub test()

Dim rs As DAO.Recordset, rsCnt As Long, i As Long
Set rs = CurrentDb.OpenRecordset("qryMyQuery", DB_OPEN_DYNASET)
rs.MoveLast
rsCnt = rs.RecordCount
rs.MoveFirst
For i = 1 To rsCnt

rs.Edit
rs!MyFieldInTable = "test"
rs.Update

Next i

End Sub

我认为Access数据库可能已损坏所以我提取了一个早期的备份,但是它做了同样的事情,这让我觉得这是一个MySql问题。

我们在链接到不同MySql表的此数据库的另一个版本上使用相同的代码,它可以正常工作。

另外,当我打开查询时,记录集基于我可以编辑查询中的数据而没有任何问题。

只需添加,在第一个循环中,rs!MyFieldInTable被更新,然后我收到错误。

8 个答案:

答案 0 :(得分:4)

您似乎没有移动到记录集中的另一条记录。简单地递增i不会移动到下一条记录。更传统的方法是迭代记录集而不需要其他变量(irsCnt)。

Dim rs as DAO.Recordset
Set rs = CurrentDb.OpenRecordset("qryMyQuery", DB_OPEN_DYNASET)
rs.moveFirst
Do Until rs.EOF
    rs.Edit
    rs!FieldNameHere = "test"
    rs.Update
    rs.MoveNext
Loop

修改 经过一番搜索,我遇到了this thread这似乎与您的问题类似。在线程的底部,建议通过选择“高级”选项卡并选择“返回匹配行”选项来修改MySQL DSN的ODBC设置。该帖子还说要删除链接表,然后将其重新链接到Access数据库。 我以前没有使用Access和MySQL,所以我不知道这是否有效,所以请谨慎行事!

你也可以尝试更改你的记录集,使用dbOptimistic标志来记录集锁定选项,看看它是否有帮助:

set rs = CurrentDB.OpenRecordSet("qryMyQuery", DB_OPEN_DYNASET, dbOptimistic)

答案 1 :(得分:2)

你可以尝试两件事。首先,尝试在打开记录集时添加dbSeeChanges选项:

Dim rs as DAO.Recordset, db As DAO.Database
Set db = Currentdb
Set rs = db.OpenRecordset("qryMyQuery", dbOpenDynaset, dbSeeChanges)
Do Until rs.EOF
    rs.Edit
    rs!FieldNameHere = "test"
    rs.Update
    rs.MoveNext
Loop

正如@HansUp建议的那样,另一个选项是使用SQL更新语句而不是动态记录集。关键是打开记录集作为快照,这样您对记录所做的更改不会影响记录集本身。

Dim rs as DAO.Recordset, db As DAO.Database
Set db = Currentdb
Set rs = db.OpenRecordset("qryBatchPayments", dbOpenSnapshot)
Do Until rs.EOF
    db.Execute "UPDATE Payments " & _
               "SET DCReference='test' " & _
               "WHERE PaymentID=" & !PaymentID, dbFailOnError
    rs.MoveNext
Loop

答案 2 :(得分:2)

我遇到了同样的问题,我的解决方案被证明是BIT(1)字段的默认值。 Access不希望这些为null。确保在mysql中对这些字段使用0或1。

答案 3 :(得分:1)

我没有MySQL在这里试试这个,但它看起来好像你的代码在rs.Update方法执行后没有推进记录集,所以你试图在相同的字段中使用fierst记录。

在rs.Update:

之后添加此行
rs.MoveNext

希望有所帮助。

答案 4 :(得分:1)

尝试从设置为CurrentDb()的对象变量调用OpenRecordset,而不是直接从CurrentDb()调用。

Dim rs as DAO.Recordset
Dim db As DAO.Database
Set db = Currentdb
Set rs = db.OpenRecordset("qryMyQuery", DB_OPEN_DYNASET)
rs.moveFirst
Do Until rs.EOF
    rs.Edit
    rs!FieldNameHere = "test"
    rs.Update
    rs.MoveNext
Loop

该建议的原因是我发现直接对CurrentDb的操作可能会抛出“block not set”的错误。但是在使用对象变量时我没有得到错误。 ISTR OpenRecordset是一个这样的操作,这是一个问题。

另外,我的印象是你的方法是一种繁琐的方法来实现相当于:

UPDATE qryMyQuery SET FieldNameHere = "test";

但是,我怀疑该示例是记录集方法有用的真实世界情况的代理。仍然这让我想知道在执行UPDATE语句时是否会看到相同或不同的错误。

如果您仍然遇到此问题,可能有助于向我们展示qryMyQuery的SQL视图。

答案 5 :(得分:0)

我发现如果试图保存与MySql记录中已有的数据相同的数据Access将显示此类错误。我已尝试过这个帖子的一些建议,但没有帮助。

对此的简单解决方案是使用手动时间戳保存稍微不同的数据。这是一个提升排序顺序字段并将其设置为10,20,30 ......

的示例
    i = 10
    timeStamp = Now()
    Do Until Employee.EOF
        Employee.Edit
        Employee!SortOrderDefault = i
        Employee!LastUpdated = timeStamp
        Employee.Update
        i = i + 10
        Employee.MoveNext
    Loop

我在MySql表中尝试过自动时间戳,但在新条目数据与旧条目数据相同时没有帮助。

答案 6 :(得分:0)

我的一点点有用的提示是,在将SQL表链接到Microsoft Access时要使用的数据类型是非常非常非常糟糕的,因为只有SQL Server能够理解它的含义,Microsoft Access很难解释它的含义。将任何位数据类型更改为int(整数)并重新链接应清除的表。此外,确保您的布尔值在您的VBA代码中始终包含1或0(不是是/否或真/ / flase),否则您的更新将无法链接到SQL表,因为Microsoft Access将尝试使用True更新它们/ False或是/否和SQL不会那样。

答案 7 :(得分:0)

我也有同样的问题;我解决了他们使用dao.recordset将代码添加到代码中:

**rst.lockedits = true**
rst.edit
rst.fields(...).value = 1 / rst!... = 1
rst.update
**rst.lockedits = false**

这似乎解决了刚打开的数据(例如表单中)和用代码更新它们之间的冲突。

抱歉我的英语不好......我读了很多但我从未学过它!我只是意大利人。