根据我上面的评论和 Yawar 的回答,我不知道传递查询是可编辑/可更新的。从某种意义上说,它们是可编辑的,您可以编辑保存的 Pass Through Query 对象,但我认为 Pass Through Query 不可能生成可编辑的记录集。
基本上有两种方法可以将 Access 连接到非 Access 数据源。
第一种方法,也是最流行的,是使用某种形式的链接表,通常是 ODBC 链接表。有多种方法可以通过 MS Access 使用 ODBC 链接表,但大多数开发人员更喜欢使用在应用程序启动时刷新或重建(删除和重新连接)的 DSN-Less 连接。请注意,当您使用 ODBC 时,您仍在使用 DAO。DAO 是内置于 MS Access 中的默认数据访问对象,即使您没有专门编写任何 DAO 代码,MS Access 仍在后台使用 DAO 将您的表单、报表和查询链接到您的数据源。在 ODBC 的情况下,您实际上最终有两个数据访问层在工作,DAO 和 ODBC。但是您可以使用性能相当不错的 ODBC/DAO 而无需编写代码(除了维护 ODBC 链接表)。
第二种方法是使用 ADO。与流行的看法相反,这并不意味着您必须使用未绑定的表单。但这确实意味着您必须编写比使用 JET/DAO/MSAccess 或 DAO/ODBC/SSQL Server 更多的代码。您必须编写代码将数据库中的记录引入 ADO Recordset,然后使用代码将您的表单绑定到该 Recordset。您必须编写更多代码以使子表单与父表单保持同步,在创建新记录时将外键插入子表单,以及进行各种其他事情,例如过滤和排序作为表单的内置过滤和排序选项通常不适用于 ADO 记录集。ADO 是一种与 SQL Server 对话的好方法,因为它确实为您提供了很多控制权,但因为它的代码密集,而且因为 ODBC 链接表工作得很好,大多数开发人员不建议使用 ADO,除非没有其他方法可以做您想做的事情。一个例子是调用存储过程。我相信传递查询可以用来调用存储过程,但我也认为那里有一些限制(例如使用参数)。我相信在大多数情况下,开发人员使用 ADO 来调用存储过程。我经常使用 ADO,但我不经常使用存储过程(还没有),所以我没有很多关于这方面的信息。
值得一提的另一件事是,带有 ODBC 的 DAO 使用“延迟加载”,但 ADO 会强制您提取所有数据,如果您有超过数百万行,这可能非常耗时并消耗大量内存。否则,您将需要实现某种分页。
下面是我自己创建单个 DSN-Less ODBC 链接表的函数。如果您是 Access 新手和 VBA 新手,那么这对您来说可能没有多大意义。该代码会删除您尝试链接的表已经存在的任何表定义,这有点危险,因为我相信它可能会删除您不想要的本地非链接表。这里的错误处理也没有真正达到速度,但是由于涉及的复杂性,大多数在线示例代码都没有很好的错误处理。在链接表上创建主键索引并不总是必要的。我只是将它内置到我的函数中,因为我有一次需要它用于一个特定的项目,所以现在我把它留在那里并使用它,无论好坏。
要正确使用此代码,您确实需要在某处拥有所有链接表的列表,并遍历该列表并为每个表调用此函数。此函数允许您使用与 SQL Server 中的实际名称不同的名称来链接表。您还需要有一种方法来构建一个有效的 ODBC 连接字符串,该字符串也必须传递给这个函数。
Private Sub LinkODBCTable(sSourceTableName As String, _
sLocalTableName As String, _
sPrimaryKeyField As String, _
sConString As String)
Dim dbCurrent As DAO.Database
Dim tdfCurrent As DAO.TableDef
Set dbCurrent = DBEngine.Workspaces(0).Databases(0)
On Error Resume Next
'Be Careful, this could delete a local, non-linked table.
dbCurrent.TableDefs.Delete sLocalTableName
If Err.Number <> 0 Then
If Err.Number = 3011 Then
'Table does not exist
Else
MsgBox "Error in LinkODBCTable" & vbCrLf & vbCrLf & Err.Number & " " & Err.Description
End If
Err.Clear
End If
On Error GoTo 0
Set tdfCurrent = dbCurrent.CreateTableDef(sLocalTableName)
tdfCurrent.Connect = sConString
tdfCurrent.sourceTableName = sSourceTableName
dbCurrent.TableDefs.Append tdfCurrent
On Error Resume Next
If sPrimaryKeyField <> "" Then
dbCurrent.Execute "CREATE INDEX __UniqueIndex ON [" & sLocalTableName & "] (" & sPrimaryKeyField & ")", dbFailOnError
If Err.Number <> 0 Then
If Err.Number = 3283 Then
'Primary Key Already Exists
Else
MsgBox "Error in LinkODBCTable" & vbCrLf & vbCrLf & Err.Number & " " & Err.Description
End If
Err.Clear
End If
End If
Set tdfCurrent = Nothing
Set dbCurrent = Nothing
End Sub
关于 DAO、ADO、传递查询、SQL Server 等,您应该查看一些非常好的资源:
http://technet.microsoft.com/en-us/library/bb188204%28v=sql.90%29.aspx
http://www.utteraccess.com/wiki/Choosing_between_DAO_and_ADO
下面是一个将表单绑定到 ADO 记录集的示例。虽然这有点误导,因为最好有一个在应用程序运行时保持打开状态的全局连接对象。这允许您使用可自动更新的 ADO 记录集。使用这种做法还可能使您的记录集成为表单级对象。
http://msdn.microsoft.com/en-us/library/office/bb243828%28v=office.12%29.aspx