SQL Management Studio 2012 with Excel vba connection string set up - sql

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:

Related

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

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!

VBA is unable to create a connection to a remote SQL Database

I've created an excel front end interface to connect with and manipulate an SQL database. I recently received a laptop, and would like to be able to manipulate the data from excel on said laptop. I established a connection using SQL Server Management Studios to the database.
I've tried to update my excel file; however, the VBA code can not connect to the SQL database. I've changed a few of the variables around and set Integrated Security too, but nothing has worked so far. The error message readouts can be seen here:
Here is the code related to the DB connection:
Dim cnSQL As ADODB.Connection
Set cnSQL = New ADODB.Connection
cnSQL.Open "Provider = SQLOLEDB; Integrated Security = SSPI, Data Source = IP Address,Static TP Port; UID = username; PWD =pwd#; Initial Catalog = database"
The error message highlights the second line of code. I'm hoping to be able to connect to the DB from my laptop.
After struggling for a few days, I finally got this to work. There are two important steps you need to take to make excel work with a Remote SQL network. First here is the code used to connect:
Dim cnSQL As ADODB.Connection
Dim ServerName As String
Dim DatabaseName As String
Dim userID As String
Dim password As String
ServerName = "IP Addresss,Port"
DatabaseName = "DB Name"
userID = "username"
password = "pwd"
Set cnSQL = New ADODB.Connection
sqlCommand.ActiveConnection = cnSQL
After I changed the code to this, I got a new error: "optional feature not implemented." To fix this error, I changed the data type of all 'adDate' to 'adDBTimeStamp.' This works for some reason, I don't know why. It works.

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.

Execute Query from Access via Excel Query in VBA

Access has saved a query that was designed with the query builder called 'myQuery'. The database is connected to the system via ODBC connection. Macros are all enabled.
Excel Has makes a ADODB connection to connect to the database via
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
With con
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open "MyDatabase.accdb"
End With
Usually you would go ahead and just write your SQL, which is perfectly fine and then just do something like
Dim sqlQuery As String
sqlQuery = "SELECT * FROM myTable"
Set rs = New ADODB.Recordset
rs.Open sqlQuery, con, ...
But I want to access the query that I saved in the access database. So how do I call the saved query in the database that I just connected.
Tried already
con.Execute("EXEC myQuery") but that one told me it could not be find myQuery.
rs.Open "myQuery", con but that one is invalid and wants SELECT/etc statements from it
I think you can treat it like a stored procedure.
If we start right before Dim sqlQuery As String
Dim cmd as new ADODB.Command
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "myQuery"
cmd.ActiveConnection = con
Set rs = cmd.Execute()
Then pickup your recordset work after this.
You were nearly there:
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
With con
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open "z:\docs\MyDatabase.accdb"
End With
con.Execute "MyQuery"
Just leave out Exec.
You can add parameters, too, this is a little old, but should help: update 2 fields in Access database with Excel data and probably a Macro
I was able to run an update query that was already saved in Access using:
Connection.Execute "My_Update_Query_Already_Saved_In_Access", adExecuteNoRecords, adCmdStoredProc
This gave me errors until I replaced spaces in the query name with underscores in both the Access database and the execute statement.
This is sort of a hack job, but you can query a query. That is, replace your sql string with the following:
sqlQuery = "SELECT * FROM QueryName;"
Before running this, one must ensure that the Access Database has been saved ie. press Ctrl+S (it is not sufficient that the query was run in Access).
Long time since this thread was created. If I understand it correctly, I might have something useful to add. I've given a name to what the OP describes, that being the process of using SQL from a query saved in an ACCDB to run in VBA via DAO or ADOBD. The name I've given it is "Object Property Provider", even with the acronym OPP in my notes, and for the object name prefix/suffix.
The idea is an existing object in an ACCDB (usually a query) provides a property (usually SQL) that you need to use in VBA. I slapped together a function just to suck SQL out of queries for this; see below. Forewarning: sorry, but this is all in DAO, I don't have much use for ADODB. Hope you will still find the ideas useful.
I even went so far as to devise a method of using/inserting replaceable parameters in the SQL that comes from these OPP queries. Then I use VBA.Replace() to do the replacing before I use the SQL in VBA.
The DAO object path to the SQL of a query in an ACCDB is as follows:
mySqlStatement = Access.Application.CurrentDb.QueryDefs("myQueryName").SQL
The way I use replaceable parameters is by evaluating what needs to be replaced, and choosing an unusual name for the paramater that cannot possibly exist in the real database. For the most part, the only replacements I've made are field or table names, or the expressions of WHERE and HAVING clauses. So I name them things like "{ReplaceMe00000001}" and then use the Replace() function to do the work...
sqlText = VBA.Replace(sqlText, "{ReplaceMe00000001}", "SomeActualParameter")
...and then use the sqlText in VBA. Here's a working example:
Public Function MySqlThing()
Dim sqlText as String
Dim myParamater as String
Dim myExpression as String
'Set everything up.
sqlText = getSqlTextFromQuery("myQuery")
myParameter = "{ReplaceMe00000001}"
myExpression = "SomeDateOrSomething12/31/2017"
'Do the replacement.
sqlText = VBA.Replace(sqlText, myParameter, myExpression)
'Then use the SQL.
db.Execute sqlText, dbFailOnError
End Function
Function getSqlTextFromQuery(ByVal oppName As String) As String
Dim app As Access.Application
Dim db As DAO.Database
Dim qdefs As DAO.QueryDefs
Dim qdef As DAO.QueryDef
Dim sqlText As String
Set app = Access.Application
Set db = app.CurrentDb
Set qdefs = db.QueryDefs
Set qdef = qdefs(oppName)
oppGetSqlText = qdef.SQL
End Function

VBScript to connect to SQL Server 2005 and update a table

I am new to VBScript. Can someone please help me to connect to SQL Server 2005 (OLEDB) using VBScript and update a table in the database.
My server: sql14\qw
My database: fret
User id: admin
Pasword: pass
Table name: lookup
Const DB_CONNECT_STRING = "Provider=SQLOLEDB.1;Data Source=sql14\qw;Initial Catalog=fret;user id ='admin';password='pass'"
Set myConn = CreateObject("ADODB.Connection")
Set myCommand = CreateObject("ADODB.Command" )
myConn.Open DB_CONNECT_STRING
Set myCommand.ActiveConnection = myConn
myCommand.CommandText = "UPDATE lookup SET Col1 = 'Hello'"
myCommand.Execute
myConn.Close
Tested using Integrated Windows Security, did not test with SQL Login.
Easy stuff, actually. First, you have to define the connection and recordset that you'll be using:
Set AdCn = CreateObject("ADODB.Connection")
Set AdRec = CreateObject("ADODB.Recordset")
After that, it's all about the connection string:
connstr="Provider=SQLOLEDB.1;Data Source=" & server & ";Initial Catalog=" & database & ";user id = '" & uid & "';password='" & pwd & "'"
The string consists of a few parts:
Provider: the type of connection you are establishing, in this case SQL Server.
Data Source: The server you are connecting to.
Initial Catalog: The name of the database.
user id: your username.
password: um, your password. ;)
Note that if you want to use your Windows login credentials and are running the script locally then you can substitute the following for the username and password fields:
Integrated Security=SSPI
Of course, this won't work if you're using your script on a website, so you'll have to explicitly use username and password. Then, making sure your connection is open, you just open the recordset, hand over the SQL query, and capture the returned data as an array.
SQL="Select ##version as name"
AdCn.Open connstr
AdRec.Open SQL, AdCn,1,1
queryReturn=Adrec("name")
Just remember that the data is being returned as an array (often two dimensional, where the results you want are actually in the second dimension of the array!) and that you may need to either Trim to kill blank spaces at the end of results or parse the results with string functions like Left. Personally, I always Trim() a result while assigning it to a variable as I've been bitten by hidden blanks more times than I can count.