run query from different database on separate server connected via ODBC - sql

I'm using Access 2010. Right now I have a function called SetQuerySource:
Private Sub SetQuerySource()
Dim sql As String
sql = DLookup("QueryText", "tblQuery", "QueryName ='qselDailyMilkYield'")
CurrentDb.QueryDefs("qselDailyMilkYield").sql = sql
sql = sql & vbCrLf & "where pt.DLVDate between '" & Me.txtDate
& "' AND '" & Me.txtEndDate & "' and pb.ITEMID like '%pm%' and pjb.ITEMID
like '%pm%' group by pt.ITEMID, pb.ITEMID, pt.NAME, pt.DLVDATE"
CurrentDb.QueryDefs("qselDailyMilkYield").sql = sql
End Sub
I use this to run a query located in a table named tblQuery in my Access database. I then append the Where clause to the query using VBA in case (as shown above) I need to point to a named control which holds a value based on user input.
I came into this setup. By that I mean I didn't create this function I just began using it. My question is how do I point to a different database on a different server? The query I need to run has tables (connected via ODBC) already linked to this Access database but my search of OpenDatabase proved futile as I didn't understand how to use it in my environment.
I receive this error:
[Microsoft][ODBC SQL Server Driver][SQL Server]Invalid object name 'dbo.MilkReceived'. (#208)
Private Sub cmdTruckDeliveries_Click()
SetQuerySource
DoCmd.OpenReport "rptTruckDeliveries", acViewPreview
End Sub
This is my code for the button click event jic.
Thank you,

Related

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.

Updating a SQL Table using data from an Access 2016 Form

I'm trying to create an Access 2016 Form that allows users to correct information located on a SQL Server Table but having trouble. First some restrictions; I can't create anything new in the SQL Server, The users do not have access to the password for the ODBC connection.
I know with an Access Pass-Through Query you can save an ODBC connection, however you have to use VBA to update the query with the data from a Access Form.
Currently my code in VBA is;
mysql = "Update dbo.MRollData Set dbo.MRollData.PolyPart = '" + Me.ActiveControl.Value + "' WHERE dbo.MRollData.LotNum = '" + Me.MRollLotNum.Value + "' AND dbo.MRollData.Side = '" + Me.MRollSide.Value + "' AND dbo.MRollData.MRIndex = '" + Me.MRollIndex.Value + "' AND dbo.MRollData.PolyPart = '" + Me.CurrentValue.Value + "'"
CurrentDb().QueryDefs("PolyPartChange").SQL = mysql
DoCmd.OpenQuery "PolyPartChange", , acEdit
This is activated by an OnClick command, however running this I get run-time error '438' Object doesn't support this property or method.
The VBA code was written using a similar bit of code from another database that updates a query that executes a SQL query.
I've also tried to just run the query on its own and keep getting the Error "Query must have at least one destination field"
Am I missing something or is it not possible to run execute an SQL Update query in an Access pass-through query? Also is there an easier way to do what I am trying?
UPDATE; I have a tag listed here that I didn't see auto generate as ActiveControl, this should have been Me.ActualValue.Value
You could try with:
CurrentDb.QueryDefs("PolyPartChange").SQL = mysql
CurrentDb.QueryDefs("PolyPartChange").Execute
The query must be a pass-through query for your SQL syntax to work.

How to copy data from non-linked to linked table in Access 2010 using VBA

So what I'm trying to do is to either copy data from an Access local table to a linked table on a SQL Server. I'd like this to work via a macro so it can be triggered upon opening a report. Or I could just bypass the linked table and insert directly to the remote server.
What I'm having a difficult time finding is the proper syntax to accomplish this. It should be very easy but apparently it's not.
Public Sub CopyPT()
Dim strSQL As String
Dim strConnect As String
Dim strDatabase As String
Dim strTableName As String
ODBC_String = "ODBC;DRIVER={SQL Server};SERVER=aaa;DATABASE=bbb;UID=ccc;PWD=ddd;" _
& "LANGUAGE=us_english;TRUSTED_CONNECTION=No"
' Id also like to truncate the Destination table here too
strSQL = "SELECT * INTO dbo_DESTINATION_TABLE IN [" & ODBC_String & "]" _
& " FROM [ACCESS_LOCAL_TABLE];"
DoCmd.RunSQL strSQL
MsgBox "Success!"
End Sub
Either I need to get the proper format for the IN statement, which doesn't appear to have ODBC option, or I need another method to copy to the linked table. Such a simple copy and paste line by line macro - which I also can't find anywhere since most sane people would just write a query.
Thanks!

How to do a MS Access Update query for a table in external database

Im trying to perform an update query on a table that its on a separate database, so far i have this SQL:
UPDATE [;database=C:\QA_Daily_YTD_Report_Export.accdb].[YTD-Daily_Report] AS EXT_DB
SET EXT_DB.Category1 = "1"
WHERE (EXT_DB.Category1 = "status1");
When i run this it returns an "invalid operation" error. Any idea what im doing wrong?
I would recommend linking the table [YTD-Daily_Report] into your database because you can easily put the update query into your code without having your code execute the connection to the other database.
You can link a table in Access by clicking on the External Data. Then click on the Access symbol.
You should then get a dialog box like this:
Be sure you choose the second radio button because you don't want to import the data from the database, just link it.
Navigate to the location of the Database and click on it. Then make sure your database is shown in the dialog box above and click okay.
You should then get a dialog box like this one that will show the table you won't. Highlight it and click okay. Now you can rename the linked table with any name you want and this will be a much less of a stumbling block for your work.
Try to omit ;database=
UPDATE [C:\QA_Daily_YTD_Report_Export.accdb].[YTD-Daily_Report] AS EXT_DB SET EXT_DB.Category1 = "1" WHERE (EXT_DB.Category1 = "status1");
I ended up using VBA in a form, just in case someone is wondering how here it is:
Dim SQL As String
Dim db_external As Database
Set db_external = OpenDatabase(CurrentProject.Path & "\QA_Daily_YTD_Report_Export.accdb")
SQL = "UPDATE [YTD-Daily_Report]" & Chr(13) & _
"SET [YTD-Daily_Report].Category1 = '" & New_value & "'" & Chr(13) & _
"WHERE ([YTD-Daily_Report].Category1= '" & Look_up_value & "');"
db_external.Execute SQL

Schema changes not updated in MS Access front end linked to the database

I created a new table in SQL server using SQL Server Management Studio but the MS Access front end linked to the database was not updated.
I tried reopening Access but still the new tables cannot be found. Yet when I check the SQL Server database they are there.
My tables in Access are linked to the database so I assumed any table or changes made in the SQL server database would be reflected in the Access front end. When I run a query in Access looking for the tables nothing is found. Another bit of information is when I right click and press view dependencies it says unable to view dependencies because
"unable to cast object of type 'System.DBNull' to type
'System.string'"
Something is maybe wrong with the way i save the query but I am not sure.
Your assumption:
I assumed any table or changes made in the SQL server database would
be reflected in the Access front end
...is not correct. Access does not automatically re-link when the SQL Server's schema changes, and it really can't. You're expecting Access assumes the data models between SQL Server and Access are the same. Even if your table and column names are exactly the same there are still differences to deal with since the data types have some differences. So, even in the best-case scenario Access does not have enough info to automatically re-link.
When you modify the SQL Server db you have to re-link from Access. Here's an article with some code that will allow you to do that quickly but note that you still have to launch it manually. And beware, as mentioned above, linking isn't that straightforward. If you use an automated method for linking the process will have to make some decisions, some of which make take you by surprise.
I have found the management of linked tables in access to be administratively tedious. In order to make my life simpler I have used the functions below that can be called to update the linked tables in access. This will take care of updating the structure of any changed table in SQL. Adding values to the SetTableNames function will bring in new tables
Private mstrTableNames(100) As String
Private const gcSQLDB as string = "MySQLServer"
Private const gcUserID as string = "SQLUserName"
Private const gcUserPassword as string = "SQLPassword"
Private const gcLiveDSN as string = "DSN"
Private const gcEmpty as string = ""
Public Function LinkLiveTables() As Boolean
Dim tdfLinked As TableDef
Dim strConnect As String
Dim intLoop As Integer
'Remove all non system tables from the application:
' !!!NB Add other exclusions so as to not delete tables that are not linked!!!
For Each tdfLinked In CurrentDb.TableDefs
If Left(tdfLinked.Name, 2) <> "MS" Then
If Left(tdfLinked.Name, 7) <> "tblTemp" Then
CurrentDb.TableDefs.Delete tdfLinked.Name
End If
End If
Next
'Create a linked table that points to SQL Server
strConnect = "ODBC;DATABASE=" & gcSQLDB & ";UID=" & gcUserID & _
";PWD=" & gcUserPassword & ";DSN=" & gcLiveDSN
SetTablesNames
For intLoop = 1 To 100
If mstrTableNames(intLoop) = gcEmpty Then GoTo ProcExit
Set tdfLinked = CurrentDb.CreateTableDef(mstrTableNames(intLoop))
With tdfLinked
.Connect = strConnect
.SourceTableName = "dbo." & mstrTableNames(intLoop)
End With
CurrentDb.TableDefs.Append tdfLinked
Next
ProcExit:
MsgBox "Connection to the LIVE tables was successful.", vbInformation
Exit Function
ProcError:
MsgBox "Link to LIVE tables Failed." & vbCrLf & vbCrLf & _
"Error Number : " & Err.number & vbCrLf & _
"Error Description : " & Err.Description, vbCritical
End Function
Private Sub SetTablesNames()
mstrTableNames(1) = "tblMoistureHist"
mstrTableNames(2) = "tblRawMaterials"
' ... add the additional table that you need as mstrTableNames(n) = "tablename"
End Sub