ODBC connection from MS Access to MySQL server fails to execute stored procedure - vba

I just started out with mySQL and need some help here. I have a 10.4.27-MariaDB- Server with a mySQL database. I want to execute several queries from a Microsoft Access document. I have a stored procedure on the server named "task_data_proc". This procedure returns the task data for a given task number. It is working fine on the server. It contains the following code:
BEGIN
SELECT * FROM task_data WHERE TASKNUMBER = uTasknumber;
END
In my VBA-code I tried to call the Procedure via ODBC using ADO:
Private Sub Test()
Dim conn As Object, cmd As Object, rst As Object
Const adCmdStoredProc = 4, adParamInput = 1, adVarInt = 3
Dim asked_number As Integer
'defining random task-number for testing purpose
asked_number = 1200
Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
' DSN-LESS CONNECTION
conn.Open "Driver={MySQL ODBC 8.0 ANSI Driver};host=localhost;database=expert_db;" _
& "UID=root;PWD=generic_password"
' CONFIGURE ADO COMMAND
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandText = "task_data_proc"
.CommandType = adCmdStoredProc
.CommandTimeout = 15
End With
' APPEND NAMED PARAM
cmd.Parameters.Append cmd.CreateParameter("uTasknumber", adVarInt, _
adParamInput, 6, asked_number)
Set rst = cmd.Execute
' FREE RESOURCES
rst.Close
Set rst = Nothing
Set cmd = Nothing
Set conn = Nothing
End Sub
When I run this I get:
Runtime error '-2147467259 (80004005)':
[MySQL][ODBC 8.0(a) Driver]Access denied for user 'root'#'localhost' (using password: YES)
However I used the same "generic_password" in my code that I use to log into the server with PHPmyAdmin. I tried it without a password as well and I got the same error message, except "(using password: NO)".
I also included the "skip-grant-tables" command in the "my.ini" document for the SQL-Server.
Is the String that I defined for conn.Open incorrect?
I have also tried using a pass-through-query in Access. When I setup the ODBC connection for the pass-through-query I chose the database and hit "Test". It says "connection successful". I hit OK.
The ODBC connection String is then automatically named "ODBC;DSN=unfall;SERVER=localhost;UID=root;PWD={generic_password};DATABASE=expert_db;PORT=3307;COLUMN_SIZE_S32=1;DFLT_BIGINT_BIND_STR=1"
I define the pass-through-query as "SELECT * FROM task_data"
I run the query. It returns the entire table with the task data, as I intended. But if I filter for a specific task number in the table or scroll through the data for a while, suddenly an error pops up:
ODBC-call failed
[MySQL][ODBC 8.0(a) Driver]mysqld-5.5.5-10.4.27-MariaDB
After that message the entire table just contains "#NAME" in every single cell. When I run the query again, the data is back there until I scroll/filter and the message pops up again. Am I using the wrong ODBC driver? Or are pass-through-queries not suitable for select-statements?
I also tried using linked tables with ODBC instead. It worked fine but was quite slow. I wanted to improve the performance by either using pass-through-queries or calling procedures using ADO.
Thank you very much for any help or guidance!

Related

PostgreSQL & Access -- Connecting at start vs. Connect when needed

I have a PostgreSQL 9.5 database with an Access 2016 front-end, using an ODBC driver to connect the two. If I wanted to query data, I would start with the following commands:
Dim conn As New ADODB.Connection
conn.Open "Driver={PostgreSQL ANSI};Server=localhost;Database=[name];User Id=[UID];Password=[pass];"
Dim cmd As New ADODB.Command
cmd.ActiveConnection = conn
My question is this: Is there any reason why I shouldn't establish this connection the moment the application opens, using that connection whenever I need to run a query, as opposed to opening and closing the connection each time I run a query?
I'm unsure what, if any, overhead is involved in establishing such a connection in Access, and I've been unable to find any information on the topic. Apologies if this is a naive question.
I the connection is cached by Access anyway.
Once you touch, or open any linked table, then the connection is now active, and re-used by Access.
In general if the query is against a single table, then there little reason to not just code against the linked table.
Eg:
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = "select * from tblInvoices where invoiceNum = 13355"
Set rst = CurrentDb.OpenRecordset(strSQL)
If you using a pass-though query, then this works well:
Sub Test555()
Dim rst As DAO.Recordset
With CurrentDb.QueryDefs("qryPass")
.SQL = "select * from tblInvoices where invoiceNum = 13355"
Set rst = .OpenRecordset
End With
End Sub
The reason for above is you thus don’t mess or have to bother with connection strings in your code.
Just ensure that you table re-link code also re-links any pass-through query.

SQL Management Studio 2012 with Excel vba connection string set up

I would like to set up a vba code that would connect to sql management studio 2012 a run the query, which I would specify in the vba code. I have read every similar question here on stack overflow but when I try to replicate them, I always get an error, ussualy that the login failed for user.
I think I am setting up the string connection wrong. Also, I would need the user authentication by Windows authentication.
I know the database name, server name and my user name.
This is the code I am using and which is giving me an error.
Sub ConnectionExample6()
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cnn = New ADODB.Connection
' Open a connection by referencing the ODBC driver.
cnn.ConnectionString = "driver={SQL Server};" & _
"server=SERVER NAME;uid=USER ID;pwd=MyPassword;database=DATABASE NAME"
cnn.Open
' Create a Recordset by executing an SQL statement.
Set rs = cnn.Execute("Select top 100 * from "TABLE NAME" aac " & _
"where aac.EffectiveDate = '10/04/16'")
' Close the connection.
rs.Close
End Sub
Can someone walk me through the connection string and how to set it up step by step? Thank you.
Authentication
If you're connecting to SQL Server, you should prefer Windows Authentication if that's available: you create a Login at server level for a group of Active Directory users, and then you create a Windows-Authenticated User in your database using that login.
That way you are keeping passwords and usernames out of hard-coded strings, and let the network deal with authentication.
Assuming you don't want to be maintaining passwords in dozens of copies of macro-enabled workbooks across your network, you'll want to use Windows Authentication.
Integrated Security=SSPI; Persist Security Info=True;
Server
Connection strings are annoying - seems there's a different format/wording for every single different thing that's able to parse them!
Since you're using ADODB, you'll want to specify a Provider, a Data Source and, optionally, an Initial Catalog:
Provider=SQLOLEDB.1; Data Source=SQL Server instance name; Initial Catalog=Database name;
Who?
Each connection can be monitored on the server; when building your connection string you can optionally specify a Workstation ID to identify the machine the connection is for.
Workstation ID=computer name;
You can get the computer name by fetching the environment variable value, using Environ$:
Private Function GetWorkstationId() As String
GetWorkstationId = Environ$("ComputerName")
End Function
Given a SQL Server instance named SomeSqlServer, a database named SomeDatabase, and using Windows Authentication, the ADODB connection string would look like this:
Dim connString As String
connString = "Provider=SQLOLEDB.1; Data Source=SomeSqlServer; Initial Catalog=SomeDatabase; Integrated Security=SSPI; Persist Security Info=True;"
Given SQL Authentication (with a hard-coded user name and password) for SomeUser with SomePassword:
connString = "Provider=SQLOLEDB.1; Data Source=SomeSqlServer; Initial Catalog=SomeDatabase; UID=SomeUser; PWD=SomePassword;"
Commands
You don't want to be concatenating arbitrary user input into a WHERE clause; avoid executing an SQL string directly from the ADODB.Connection object.
Instead, create an ADODB.Command, and parameterize your query.
Dim sql As String
sql = "SELECT Foo, Bar FROM dbo.FooBars WHERE Foo = ? AND DateInserted > ?"
Here we have 2 parameters.
First we create the command:
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
cmd.CommandText = sql
Then its parameters, assuming we have their respective values in param1Value and param2Value local variables:
Dim param1 As ADODB.Parameter ' a string parameter
Set param1 = New ADODB.Parameter
param1.Type = adVarWChar
param1.Direction = adParamInput
param1.Size = Len(param1Value)
param1.Value = param1Value
cmd.Parameters.Append param1
Dim param2 As ADODB.Parameter ' a date parameter
Set param2 = New ADODB.Parameter
param2.Type = adDate
param2.Direction = adParamInput
param2.Value = param2Value
cmd.Parameters.Append param2
Then we retrieve the recordset by executing the command:
Dim results As ADODB.Recordset
Set results = cmd.Execute
Of course this looks very verbose, but it can easily be refactored into functions dedicated to creating a parameter given a value of a certain type.
As a result, you avoid this situation, because you're no longer executing arbitrary user input concatenated into a query:

OLEDB Connection from Excel to Oracle Issue

Everyone,
A VBA problem has been killing me the past two days. I have a Macro Based Model in Excel that has data sets bought into the spreadsheets from Oracle via OLEDB. To illustrate the problem simply I have created two functions within the Model. One using ODBC("odbc") and another using OLEDB("OraOLEDB"). The code was working completely fine last week and it has not been changed.
Now, however I get an error message that states "Run-Time Error '424': Object Required when I execute the line "conn.Open strCon" in sub "OraOLEDB".A connection can't be established with the database! So when I am trying to establish a connection to the database with that line of code, it fails. What is interesting is that via ODBC, a connection can be established. The line "conn.Open strCon" in sub "odbc" executes successfully and I am able to establish a connection to the database.
I did not change anything in the Excel Model but I did have a bunch of windows updates recently. I don't know if that corrupted anything. I think it may have. The reason why I don't want to use the ODBC connection is that it is significantly slower. I get run times 10x faster using OLEDB. Please let me know if you can help.
Sub odbc()
Dim conn As Object
Dim strCon As String
strCon = "Driver={Microsoft ODBC for Oracle};
CONNECTSTRING=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
(HOST=xxx)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=xxx)));
uid=xxx;pwd=xxx;"
Set conn = CreateObject("ADODB.Connection")
conn.Open strCon
End Sub
Sub OraOLEDB()
Dim conn As Object
Dim strCon As String
strCon = "Provider=OraOLEDB.Oracle;
Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)
(HOST = xxx)(PORT = 1521))
(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = xxx)));
User Id=xxx;Password=xxx"
Set conn = CreateObject("ADODB.Connection")
conn.Open strCon
I see the host for the OLEDB connection is modn-ast-fdb1. ... while for the ODBC connection you have modn-ast-tdb1. ... Shouldn't the host be the same?
This means Set conn = CreateObject("ADODB.Connection") returns nothing. Check ADODB.dll registration. Alternatively you may use
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
and you'll see if ADODB is available at the moment you edit the script not waiting for runtime errors.

The microsoft access database engine cannot find the input table or query 'dbo'.. (VBA, Access2010)

Helllo!
I'm an MS Access-beginner. After an upgrade from Access2003 to Access2010 I am changing the database connection of our MS Access-Application from ODBCDirect (not supported anymore) to ADODB.
After (hopefully) successfully establishing a DB connection over an ADODB.Connection object I am initializing an ADODB.Command object:
Dim qdfWork As ADODB.Command
...
Set qdfWork = New ADODB.Command
Set qdfWork.ActiveConnection = CurrentProject.Connection
qdfWork.CommandText = "[dbo].[storedProcedureName]"
qdfWork.CommandType = adCmdStoredProc
qdfWork.Parameters.Refresh 'HERE THE ERROR-MESSAGE OCCURS
...
There is a stored procedure with the exactly same name "[dbo].[storedProcedureName]" stored on the server, but I still get the error-message:
"the microsoft access database engine cannot find the input table or query 'dbo'. Make sure it exists and that its name is spelled correctly."
If I don't write "[dbo]" in the CommandText I still get the same message, telling that "[storedProcedureName]" can't be found.
Here is my ADODB.Connection.connectionString:
"Driver={Microsoft Access Driver (*.mdb)};Dbq=\\folder1\folder2\User1\Database.mdb; Uid=Admin;Pwd=password;"
The connection via this connectionString works fine I think, I don't get any error-messages when connecting to the DB.
I checked that CurrentProject.Connection is really the connection I need.
I don't understand why my Application can't find this stored procedure although it is stored on the server.
Thanks for reading

How Do I Return Multiple Recordsets from SQL Stored Procedure in Access 2010

I’ve created a pass-through query in Access which executes a stored procedure that searches for a string across all tables in my SQL database. The stored procedure on the SQL server runs as expected, returning multiple Recordsets that contain the value of my search string. However, when I double-click on the pass-through query in Access, in Datasheet View I see the results of only one Recordset. Since it appears that Access is not designed to handle multiple result sets, then how do I use VBA in Access to accomplish this?
exec sqlsp_searchalltables #Tablenames='', #SearchStr='%motion%'
I'm not quite sure how you expected to "bind" your form to the multiple recordsets returned by the stored procedure, but as far as I know the only way to deal with SQL Server stored procedures that return multiple recordsets is to use ADODB.Recordset objects.
(Don't be misled by the "Recordset.NextRecordset Method (DAO)" article here. If you try that approach you will receive run-time error '3847': "ODBCDirect is no longer supported. Rewrite the code to use ADO instead of DAO.")
For example, I have a SQL Server stored procedure that returns two recordsets and I create a pass-through named [dbo_myMultiRsSp_1] to call it:
EXEC dbo.myMultiRsSp #id=1
If I open it in Datasheet View by double-clicking it I see the results of the first recordset.
If I want to process all of the recordsets in VBA I cannot use the pass-through query directly, but I can use its .Connect and .SQL properties as follows
Option Compare Database
Option Explicit
Sub MultiRsSpTest()
Dim cdb As DAO.Database
Dim con As ADODB.Connection, cmd As ADODB.Command
Dim r1 As ADODB.Recordset, r2 As ADODB.Recordset
Set cdb = CurrentDb
Set con = New ADODB.Connection
' connect directly to the SQL Server
' (by using the .Connect property of the pass-through query)
con.Open Mid(cdb.QueryDefs("dbo_myMultiRsSp_1").Connect, 5) ' omit "ODBC:" prefix
Set cmd = New ADODB.Command
cmd.ActiveConnection = con
cmd.CommandType = adCmdText
cmd.CommandText = cdb.QueryDefs("dbo_myMultiRsSp_1").SQL
Set r1 = cmd.Execute
Debug.Print
Debug.Print "First Recordset:"
Do Until r1.EOF
Debug.Print r1(0).Value
r1.MoveNext
Loop
Set r2 = r1.NextRecordset
Debug.Print
Debug.Print "Second Recordset:"
Do Until r2.EOF
Debug.Print r2(0).Value
r2.MoveNext
Loop
' r1.Close (happens implicitly)
Set r1 = Nothing
r2.Close
Set r2 = Nothing
Set cmd = Nothing
Set con = Nothing
Set cdb = Nothing
End Sub