【问题标题】:How to make a passthrough / passthru query editable?如何使直通/直通查询可编辑?
【发布时间】:2013-09-24 17:39:31
【问题描述】:

在带有 SQL Server Backend 的 Microsoft Access 2007 中,我们通常会从 SQL Server 中获取一个链接表作为可编辑表单的 Form.RecordSource 来对单个表数据进行修改。本地查询用于组合来自多个链接表的字段的交叉表版本。本地查询本身必须是可更新的,才能修改编辑表单上的数据。

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

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

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

ID字段是在SQL Server中定义为Primary Key的IDENTITY字段作为定义:

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

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

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

结论增加了后验

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

【问题讨论】:

  • 我不知道传递查询可以更新。我的印象是产生只读记录集。
  • 如果是这样,如何在SQL Server中使用Access表单直接编辑表:必须通过链接表?

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


【解决方案1】:

根据我上面的评论和 Yawar 的回答,我不知道传递查询是可编辑/可更新的。它们是可编辑的,因为您可以编辑保存的传递查询对象,但我认为传递查询不可能生成可编辑的记录集。

基本上有两种方法可以将 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

【讨论】:

  • 不错! John Viescas 解释了为什么直通查询结果集永远不可编辑 here。我特别喜欢“您可以在 Passthrough 查询中输入“Your Mommy Wears Combat Boots”,Access 会尝试为您发送到服务器!” :-)
  • 很好的解释。因此,我们为表单 .RecordSource 设置链接表和本地查询,并仅对 Reports 使用 Passthru 查询。
【解决方案2】:

在 MsAccess 查询窗口中打开任何 SQL Server Select 语句(表、视图或带有许多连接表的 sql-select)并可以编辑/更新,有一种更简单但没有详细记录的方法:

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

之前:

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 

查询现在可以更新:

备注:

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

【讨论】:

    【解决方案3】:

    直通查询结果集不可编辑,但基于链接表的 Access 查询绝对可以。

    【讨论】:

      【解决方案4】:

      是的,“第二种方法是使用 ADO”确实如此,LinkMasterFields 和 LinkChildFields 属性在多表单中不起作用,并且 ADO 记录集在 Access 2013 报告中不起作用,所以我正在使用传递查询.我正在使用 ADP+ ADPX.accde 来模拟多表单和多报表的 LinkMasterFields 和 LinkChildFields 属性。

      【讨论】:

        猜你喜欢
        • 2021-06-28
        • 1970-01-01
        • 2013-03-16
        • 1970-01-01
        • 2017-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多