简体   繁体   中英

Use Access function in SQL pass-through query

I have an MS Access front-end with an Oracle SQL back-end database.

I'm trying to create a pass-through query that contains a function within Access. The function is for setting the jobnumber based on what the user types into the login screen.

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;

When I run the above I receive an error message that says:

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

Well, since the sql is sent "raw" to Oracle, then of course the server side database has no idea what to do with a VBA function.

So, one possible solution would be to re-create the VBA function as a scaler oracle function.

However, because that given function has no paramters, then we can assume that the function returns a given value - darn near close to a static, or a value that you wish/want to pass to oracle.

The approach then means we have to resolve the function client side BEFORE we attempt to use or execute that PT query.

So, I recommend that you take the above PT query, and copy it. (access side). You now have two PT queries.

Now, in code, we grab the sql, modify it, shove it into the 2nd query, and now you are free to launch + use that pass-though query (for a report, recordsets, forms or whatever)

So, your code will look like this:

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

So, we used two PT query, because the first one is the sql you have as a above. We then modify the 2nd PT query to replace the function value with the actual value of the function.

The above assumes the function is a number (not a string). If the column CC_QAQC_SPEC_MASTER.JOBNUMBER was a string, then you would could/would place single quotes around the function name in the first PT query.

I also note a bug/syntax error, as you have:

WHERE 
    CC_QAQC_SPEC_MASTER.JOBNUMBER)=GET_QAQC_JOB()

In above, I see a stray ")" in above - you want to fix that.

Assuming the function is a function written in VBA in Access, you can't call it from the query. I believe the DML in the query is sent in its entirety to the source system, Oracle in this case. Oracle has no idea what the function is and errors.

Option-1 : Submit the Query via ADO.NET in VBA

Abandon the pass-thru query objects in Access. Execute the query from VBA connecting to Oracle via ADO or something like it. There are lots of resources on how to use ADO to pull data from external data sources such as How To Open ADO Connection and Recordset Objects . Here is an example using DAO.

Option-2 : Wrap the Pass-thru Query in Another Query

Access lets you create queries that call other queries. Create the pass-thru query without the WHERE predicate. This is the pass-thru query. Create another access query that calls the pass-thru query. This is the wrapping query. The wrapping query (since its native Access SQL) should have the parameter you use to filter the result set.

Complete disclosure. I didn't try this with Oracle.

Now, if the pass-thru query is grabbing a lot of data. This option won't perform well.

Option-3 : Dynamically Create the Pass-Thru Query

You have an event (button click or whatever) call a VBA sub-procedure, which dynamically creates and assigns the SQL for the query:

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

Then you run the query.

Everything in the SQL you stick in this Access query object has to exist in Oracle and ONLY in Oracle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM