【问题标题】:MS Access 2019 - SQL Server 2017 - Recordset cannot be updatedMS Access 2019 - SQL Server 2017 - 无法更新记录集
【发布时间】:2019-10-04 07:45:34
【问题描述】:

我在 SQL Server 2017 数据库中创建了一个表。然后我在 MS Access 2019 中创建了一个使用 ADO 对象作为“记录源”的表单。在表单上,​​有一个带有 controlsource 属性=Field 的文本框。然后,当我打开表单时,一切都按预期工作(字段的内容显示在文本框中,我可以前后移动光标等等),除了一件事:无法更改、添加或删除记录.

在 SQL Server 上创建表(使用 SSMS):

CREATE TABLE Table1 (Field INT PRIMARY KEY)
INSERT INTO Table1 (Field) VALUES (15)
INSERT INTO Table1 (Field) VALUES (12)

在访问模块中:

#Const EarlyBinding = -1

#If EarlyBinding Then
  ' Irrelevant in this context
#Else
  Global Const adUseClient As Long = 3
  Global Const adLockBatchOptimistic As Long = 4
  Global Const adOpenDynamic As Long = 2
#End If

在访问表单的 VBA 代码中:

Private Sub Form_Load()
  Dim sqldb as Object, adocom as Object, rs As Object
  Set sqldb = CreateObject("ADODB.Connection")
  Set adocom = CreateObject("ADODB.Command")
  Set rs = CreateObject("ADODB.Recordset")
  SQLDB.Open "Driver={SQL Server Native Client 11.0};Server=SQL;Database=Test;Trusted_Connection=yes;"
  SQLDB.CursorLocation = adUseClient
  rs.LockType = adLockBatchOptimistic
  rs.CursorType = adOpenDynamic    
  adocom.CommandText = "SELECT Field FROM Table1"
  set rs = adcom.execute
  set Me.Recordset=rs
end sub

这个问题是从更复杂的代码“归结”出来的。如果我使用 DAO,我传递给 SQL Server 的查询需要几分钟才能执行,所以重点是让 SQL Server 执行查询(需要

那么我必须做什么才能添加、修改或删除记录?

DML 命令,如

adocom.execute ”UPDATE Table1 SET Field=25 WHERE Field=15” 

有效。

但是,问题是,我希望访问表单与连接到 SQL Server 的 ADO 记录集的行为方式完全相同,就像如果记录集由连接到后端 .accdb 的 DAO 对象处理时一样-文件。所以记录集应该是可更新的。属性 rs.recordcount 为 -1,表示记录集不可更新。如果该属性在 adocom.execute 行之后不是 -1,那么我们就到了。

【问题讨论】:

  • 您不能只“更新”主键,它们由数据库分配并且不可变(除非您启用INSERT IDENTITY)。
  • @steenbergh 如果我相信这篇文章,主键不是标识列,因此应该是可更新的。
  • 您是否测试过记录集是否可以通过代码更新(例如,您可以使用rs.AddNew)吗?
  • 这也可能与 SQL Server 处理查询的方式有关。如果它不是一个真正的表而是一个查询,那么如果在 SQL Server 中执行它就很少可更新。相反,可以使用带有INSTEAD OF UPDATE 触发器的视图。
  • 在本地窗口中检查记录集属性(CursorLocation 等),因为它们可能与您的设置不同,如果它们是非法的(例如,您在打开连接后设置 CursorLocation,不确定这是否有效)。

标签: sql-server ms-access ado recordset


【解决方案1】:

似乎.Execute 方法返回只读、只进游标记录集。

您必须使用Recordset.Open方法来获取非只读记录集。

这对我有用:

Private Sub Form_Load()

Dim sqldb As Object, adocom As Object, rs As Object
Set sqldb = CreateObject("ADODB.Connection")
Set adocom = CreateObject("ADODB.Command")
Set rs = CreateObject("ADODB.Recordset")
sqldb.Open "Driver={SQL Server Native Client 11.0};Server=SQL;Database=Test;Trusted_Connection=yes;"
sqldb.CursorLocation = adUseClient
rs.LockType = adLockBatchOptimistic
rs.CursorType = adOpenDynamic

rs.Open "SELECT Field FROM Table1", sqldb 'changed code

Set Me.Recordset = rs

End Sub

正如我在上面的评论中告诉你的,你应该经常检查本地窗口中记录集的设置,因为它们可能与你设置的不同!

在您的代码中,记录集.LockTypegetsadLockReadOnly 解释了只读表单。

顺便说一句,您的代码看起来像使用late-boundADODB,但使用ADODB-ConstantslikeadUseClient。如果您使用late-boundADODB,则需要单独定义它们

【讨论】:

  • 谢谢,明天我会测试你的建议。直到那时;似乎我没有使用编译器指令在早期绑定和后期绑定之间切换,以在开发期间获得智能感知,但在生产期间获得稳定性,并在后期绑定时“手动”声明所有枚举。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多