【问题标题】:MS Access Passthrough Query UpdateMS Access 直通查询更新
【发布时间】:2014-01-28 23:00:08
【问题描述】:

我正在尝试使用 MS Access 对我无法控制的 ODBC 服务器更新直通查询。我必须使用 Passthrough 的原因是我正在访问的记录有超过 255 个字段(如果可以的话,我会使用链接表)。

我一直在使用此资源通过 Passthrough (http://www.techonthenet.com/access/tutorials/passthrough/basics09.php) 获取数据

查询很简单:SELECT FullName, PointNumber FROM DNP3.CDNP3AnalogIn

ODBC 连接字符串为:ODBC;DSN=SCX6_DB;LOCATION=Main;UID=admin;PWD=password;LOCALTIME=False;

现在在 Access 数据库中,我有一个表(SCADA DB 标记)与字段(FullName、PointNumber)同名,我想使用更新直通查询更新 ODBC 数据库中的字段,但我不确定这该怎么做。

我将之前的 Query 保存为 DNP3_CDNP3AnalogIn Query,并尝试创建一个新 Query:

UPDATE [DNP3_CDNP3AnalogIn Query] INNER JOIN [SCADA DB Tags] ON 
[DNP3_CDNP3AnalogInQuery].FullName = [SCADA DB Tags].FullName 
SET [DNP3_CDNP3AnalogIn Query].[PointNumber] = [SCADA DB Tags].[PointNumber];

但我从 Access 收到错误消息:Operation must use an updateable query.

我知道有办法做到这一点,但我似乎找不到一个例子(我可能没有在谷歌上搜索正确的短语)。微软页面 (http://technet.microsoft.com/en-us/library/bb188204%28v=sql.90%29.aspx) 说:There is, however, one important limitation: the results returned by SQL pass-through queries are always read-only. If you want to enable users to perform updates based on the data retrieved, you must write code to handle this. 不幸的是它没有给出一个例子!

谁能给我一个解决方案,如果需要,我可以使用 VBA 吗?如果需要,我还可以提供更多背景信息。不幸的是,我不是 Access 方面的专家,我只是想提出一个可以节省我一些时间的自动化解决方案。

【问题讨论】:

    标签: ms-access odbc ms-access-2007 passthru pass-through


    【解决方案1】:

    当他们说“如果您希望用户能够根据 [从传递查询] 检索到的数据执行更新,您必须编写代码来处理这个问题”,他们的意思可能是这样的:

    Option Compare Database
    Option Explicit
    
    Public Sub UpdateSqlServer()
        Dim cdb As DAO.Database, rst As DAO.Recordset
        Dim con As Object  ' ADODB.Connection
        Dim cmd As Object  ' ADODB.Command
        Const adParamInput = 1
        Const adInteger = 3
        Const adVarWChar = 202
    
        Set cdb = CurrentDb
        Set rst = cdb.OpenRecordset( _
                "SELECT " & _
                    "[SCADA DB Tags].FullName, " & _
                    "[SCADA DB Tags].PointNumber " & _
                "FROM " & _
                    "[DNP3_CDNP3AnalogIn Query] " & _
                    "INNER JOIN " & _
                    "[SCADA DB Tags] " & _
                        "ON [DNP3_CDNP3AnalogIn Query].FullName = [SCADA DB Tags].FullName", _
                dbOpenSnapshot)
    
        Set con = CreateObject("ADODB.Connection")
        con.Open "DSN=SCX6_DB;"
        Set cmd = CreateObject("ADODB.Command")
        cmd.ActiveConnection = con
        cmd.CommandText = _
                "UPDATE DNP3.CDNP3AnalogIn SET " & _
                    "PointNumber=? " & _
                "WHERE FullName=?"
        cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput)  ' PointNumber
        cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255)  ' FullName
        cmd.Prepared = True
    
        Do Until rst.EOF
            cmd.Parameters(0).Value = rst!PointNumber
            cmd.Parameters(1).Value = rst!FullName
            cmd.Execute
            rst.MoveNext
        Loop
        Set cmd = Nothing
        con.Close
        Set con = Nothing
        rst.Close
        Set rst = Nothing
        Set cdb = Nothing
    End Sub
    

    注意事项:

    1. 代码使用您现有的 ODBC DNS。
    2. 它使用 Prepared Statement 来执行更新,提高效率并防止与 SQL 注入相关的故障。
    3. 源 Recordset 对传递查询执行 INNER JOIN,以确保代码仅尝试更新服务器上实际存在在服务器上的行。

    【讨论】:

    • 感谢您的详细回复。我在 cmd.Execute 上遇到错误(Microsoft ODBC 驱动程序管理器:SQL 数据类型超出范围)。我猜这是因为 PointNumber 发送了错误的类型。从数据库模式:PointNumber 是一个字(无符号)。我真的不确定如何制作这个演员而不是你所说的整数?
    • 实际上问题出在 FullName 字段上,因为它是一个带有 '.' 的字符串。和 ' ' 字符。如果我使用示例 FullName 对更新查询进行硬编码,它可以工作,例如“WHERE FullName='this is. a test fullname'”。但是如果我封装 ?像 '?' (“WHERE FullName='?'”)它不起作用。有什么提示吗?
    • 修复了 FullName 字段的问题,使用 adVarChar 而不是 adVarWChar 并且它有效!!!非常感谢!我只希望错误返回的地方更容易调试。
    【解决方案2】:

    您是说 [DNP3_CDNP3AnalogIn Query] 是基于服务器端的,而表 [SCADA DB Tags] 是基于本地的吗?在这种情况下,您不能使用传递查询。

    但是,由于桌子位于不同的位置,pass-through 不能同时接触 BOTH。

    但是,您可以在循环中执行“单个”服务器端(通过)。如果您设置传递查询并保存它,则此代码将起作用:

      Dim qdfPass       As DAO.QueryDef
    
      Dim rstLocal      As DAO.Recordset
      Dim strSQL        As String
      Dim strSQL2       As String
    
      Set qdfPass = CurrentDb.QueryDefs("MyPass")
    
      strSQL = "UPDATE [DNP3_CDNP3AnalogIn Query] " & _
               "SET [DNP3_CDNP3AnalogIn Query].[PointNumber] = 'xxxx' " & _
               "WHERE [DNP3_CDNP3AnalogInQuery].FullName = 'zzzz' "
    
      Set rstLocal = CurrentDb.OpenRecordset("[SCADA DB Tags]")
    
      Do While rstLocal.EOF = False
         strSQL2 = Replace(strSQL, "xxxx", rstLocal!PointNumber)
         strSQL2 = Replace(strSQL2, "zzzz", rstLocal!FullName)
         qdfPass.SQL = strSQL2
         qdfPass.Execute
         rstLocal.MoveNext
      Loop
    
      rstLocal.Close
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 2013-09-05
      • 1970-01-01
      相关资源
      最近更新 更多