如何使passthrough / passthru查询可编辑?

时间:2013-09-19 14:53:05

标签: sql-server ms-access ms-access-2007 passthru pass-through

在带有SQL Server后端的Microsoft Access 2007中,我们通常将SQL Server中的链接表作为可编辑表单的Form.RecordSource用于单个表数据修改。本地查询用于组合来自多个链接表的字段的交叉表版本。本地查询本身必须是可更新的,以便修改编辑表单上的数据。

现在我们计划用Passthrough查询替换所有本地查询,以便直接使用本机SQL Server表。

我尝试使用以下SQL字符串创建一个名为qrySelProductsPassThroughEditable的非常简单的passthru查询:

SELECT dbo.Products.ID, dbo.Products.Name FROM dbo.Products;

ID字段是在SQL Server中定义为主键的IDENTITY字段,作为定义:

CREATE TABLE [dbo].[Products](
    [ID] [int] IDENTITY(1,1) NOT NULL,
        ....
)

但Access传递查询返回的数据表根本不可编辑。所以它不能用作.RecordSource来编辑表单。

这与the link相反,后者表示如果passthru查询包含所有相关表的所有主键,则查询将是可编辑的。

结论添加了后验

通过下面的讨论,Microsoft Access 2007 .accdb,.accde或.accdr(Access运行时)中的直通查询始终是只读的,它永远不可编辑。您应该将它用作最终列表,或者作为报表的.RecordSource,而不是用于必须使用链接表的表单,或者是涉及数据IO的链接表的可写普通查询。

4 个答案:

答案 0 :(得分:6)

根据我上面的评论和Yawar的回答,我不知道Pass Through Queries是可编辑/可更新的。它们是可编辑的,您可以编辑保存Pass Through Query对象,但我不相信Pass Through Query可以生成可编辑的记录集。

基本上有两种方法可以将Access连接到非Access数据源。

第一种方法,也是最流行的方法,是使用某种形式的链表,通常是ODBC链表。有多种方法可以将ODBC链接表与MS Access一起使用,但大多数开发人员更喜欢使用在应用程序启动时刷新或重建(删除并重新连接)的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,除非没有其他方法可以做什么你想做什么。这方面的一个例子是调用存储过程。我相信Pass Through Queries可用于调用存储过程,但我也认为存在一些限制(例如使用参数)。我相信在大多数情况下,开发人员使用ADO来调用存储过程。我经常使用ADO,但是我没有使用存储过程(还没有),所以我没有很多关于它的信息。

另外值得一提的是,带有ODBC的DAO使用“延迟加载”,但是ADO会强制您提取所有数据,这些数据非常耗时并且如果您拥有>则需要大量内存。数百万行。否则你需要实现某种分页。

我自己创建单个DSN-Less ODBC Linked表的功能如下所示。如果您是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,Pass Through Queries,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 Recordset的示例。这有点误导,因为最好让一个全局连接对象在应用程序运行时保持打开状态。这允许您使用可自动更新的ADO记录集。使用此练习还可能使您的记录集成为表单级对象。

http://msdn.microsoft.com/en-us/library/office/bb243828%28v=office.12%29.aspx

答案 1 :(得分:4)

在MsAccess查询窗口中打开任何SQL Server Select语句(包含许多连接表的表,视图或sql-select)并且可编辑/可更新,这是一种更容易记录的方法:

打开Access查询窗口并输入您的SQL语句。将带有完整ODBC字符串的表名替换为方括号内的SQL Server,后跟一个点以及模式和表名,如下例所示:

在:

SELECT SOH.SalesOrderID, SOH.OrderDate
FROM   Sales.SalesOrderHeader as SOH 

后:

SELECT SOH.SalesOrderID, SOH.OrderDate
FROM   [ODBC;Driver=SQL Server;Server=myServer;Database=AdventureWorks2012;Trusted_Connection=Yes;MarsConn=yes;].Sales.SalesOrderHeader as SOH 

Query现在可以更新: The Access Query Window shows Data from the SQL Server according to the SQL Select statement

备注:

  • 并非每个SQL语句都使表或视图可更新。有关限制和限制,请参阅CREATE VIEW(Transact-SQL)(https://msdn.microsoft.com/en-us/library/ms187956.aspx)中的“可更新视图”部分。
  • 要在Access中更新的基础表必须具有时间戳或RowVersion列。

答案 2 :(得分:1)

传递查询结果集不可编辑,但基于链接表的Access查询肯定是。

答案 3 :(得分:0)

是的,#34;第二种方法是使用ADO&#34; LinkMasterFields和LinkChildFields属性不能在多表单中工作,并且ADO记录集在Access 2013报表中不起作用,因此我使用了传递查询。我使用ADP + ADPX.accde在多表单和多报表中模拟LinkMasterFields和LinkChildFields属性。