在 SQL 传递查询中使用 Access 函数

Use Access function in SQL pass-through query

我有一个带有 Oracle SQL 后端数据库的 MS Access 前端。

我正在尝试创建一个传递查询,其中包含 Access 中的一个函数。该函数用于根据用户在登录屏幕中键入的内容设置 jobnumber

SELECT 
    CC_QAQC_SPEC_MASTER.JOBNUMBER, 
    CC_QAQC_SPEC_MASTER.SPECSECTION,
    CC_QAQC_SPEC_MASTER.SPECDESCRIPTION,
    CC_QAQC_SPEC_MASTER.ID
FROM 
    CC_QAQC_SPEC_MASTER
WHERE 
    CC_QAQC_SPEC_MASTER.JOBNUMBER=GET_QAQC_JOB()
ORDER BY 
    CC_QAQC_SPEC_MASTER.SPECSECTION, 
    CC_QAQC_SPEC_MASTER.SPECDESCRIPTION;

当我 运行 以上时,我收到一条错误消息:

ODBC--call failed [Oracle][ODBC][Ora]ORA-00942:table or view does not exist(#942)

假设该函数是在Access中用VBA编写的函数,您不能从查询中调用它。我相信查询中的 DML 已完整发送到源系统,在本例中为 Oracle。 Oracle 不知道该函数是什么,并且有错误。

Option-1: 在VBA

中通过ADO.NET提交查询

放弃 Access 中的 pass-thru 查询对象。从 VBA 通过 ADO 或类似的东西连接到 Oracle 执行查询。有很多关于如何使用 ADO 从外部数据源提取数据的资源,例如 How To Open ADO Connection and Recordset Objects. Here 是一个使用 DAO 的示例。

Option-2:将 Pass-thru 查询包装在另一个查询

Access 允许您创建调用其他查询的查询。创建不带 WHERE 谓词的 pass-thru 查询。这是 pass-thru 查询。创建另一个调用 pass-thru 查询的访问查询。这是包装查询。包装查询(自其本机 Access SQL)应该具有用于​​过滤结果集的参数。

完全披露。我没有在 Oracle 上尝试过。

现在,如果 pass-thru 查询正在抓取大量数据。此选项效果不佳。

Option-3:动态创建 Pass-Thru 查询

您有一个事件(单击按钮或其他)调用 VBA sub-procedure,它动态创建并分配查询的 SQL:

Public Sub foo()
    Let qaqc_job_number = GET_QAQC_JOB()
    Set Query = CurrentDb.QueryDefs("<your-pass-thru-function-name>")

    Let sql_job_data = "SELECT" & _
                       "CC_QAQC_SPEC_MASTER.JOBNUMBER, " & _
                       "CC_QAQC_SPEC_MASTER.SPECSECTION, " & _
                       "CC_QAQC_SPEC_MASTER.SPECDESCRIPTION, " & _
                       "CC_QAQC_SPEC_MASTER.ID " & _
                       "FROM " & _
                       "CC_QAQC_SPEC_MASTER " & _
                       "WHERE " & _
                       "CC_QAQC_SPEC_MASTER.JOBNUMBER)= " & qaqc_job_number & " " & _
                       "Order BY " & _
                       "CC_QAQC_SPEC_MASTER.SPECSECTION, " & _
                       "CC_QAQC_SPEC_MASTER.SPECDESCRIPTION; "

    Let Query.Sql = sql_job_data

End Sub

然后你运行查询。

您在此 Access 查询对象中 SQL 中的所有内容都必须存在于 Oracle 中,并且仅存在于 Oracle 中。

好吧,既然 sql 被发送 "raw" 到 Oracle,那么服务器端数据库当然不知道如何处理 VBA 函数。

因此,一种可能的解决方案是 re-create VBA 函数作为缩放器 oracle 函数。

但是,因为给定的函数没有参数,所以我们可以假设函数 returns 给定的值 - 该死的接近静态值,或者你 wish/want 传递的值到甲骨文。

该方法意味着我们必须在尝试使用或执行该 PT 查询之前解析函数客户端。

因此,我建议您采用上述 PT 查询,并将其复制。 (接入端)。您现在有两个 PT 查询。

现在,在代码中,我们抓取 sql,对其进行修改,将其推入第二个查询,现在您可以自由启动 + 使用 pass-though 查询(对于报告,记录集、表格或其他)

因此,您的代码将如下所示:

Sub MyOraclePT()

  Dim strSQL     As String

  strSQL = CurrentDb.QueryDefs("PT1").SQL    ' <-- this change

  strSQL = Replace(strSQL, "GET_QAQC_JOB()", GET_QAQC_JOB())

  CurrentDb.QueryDefs("PT2").SQL = strSQL

  ' now you can open or use this query.

  '
  Dim rst     As DAO.Recordset
  Set rst = CurrentDb.OpenRecordset("PT2")

  ' or open a report/form based on that PT2 query
  ' such as
  DoCmd.OpenReport "MyReport", acViewPreview


End Sub

所以,我们使用了两个 PT 查询,因为第一个是上面的 sql。然后我们修改第二个 PT 查询,将函数值替换为函数的实际值。

上面假设函数是一个数字(不是字符串)。如果列 CC_QAQC_SPEC_MASTER.JOBNUMBER 是一个字符串,那么您将 could/would 在第一个 PT 查询中将函数名称放在单引号内。

我还注意到一个 bug/syntax 错误,正如您所遇到的那样:

WHERE 
    CC_QAQC_SPEC_MASTER.JOBNUMBER)=GET_QAQC_JOB()

在上面,我看到上面有一个乱七八糟的“)” - 你想修复它。