Using Variable in SQL Query Raises ADO Error - sql

I am trying to get a single itemcode from a SQL Server table (items) to be compared with an itemcode entered in an Excel sheet. To make this possible I have written the following VBA code in Excel 2019.
Function GetItemcodeFromSQLTable(sSQLArtikel As String) As String
Dim connection As New ADODB.connection
connection.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Data Source=SQL01;Initial Catalog=110"
Dim query As String
query = "select itemcode from items where itemcode = " & sSQLArtikel
Dim rs As New ADODB.Recordset
rs.Open query, connection
connection.Close
End Function
I keep getting an error executing the line rs.open query, connection.
The purpose of this all is that I want to know if an itemcode already exists in the SQL table or not. If not, the rest of my VBA code wil create a XML file to import a new itemcode into the SQL table.
I have added a reference to "Microsoft Active X Data Objects 6.1 Library" in the VBA window.
Can anybody help me with this problem?
Many thanks.
The code I am using now is
Function CheckIfArticleCodeExistsInSQLDatabase(sSQLArtikel As String) As String
Dim query As String
Dim connection As ADODB.connection
Dim rs As ADODB.Record
Dim cmd As ADODB.Command
' PREPARED STATEMENT WITH PARAM PLACEHOLDERS
query = "select itemcode from items where itemcode = " & "'" & sSQLArtikel & "'"
' OPEN CONNECTION
Set connection = New ADODB.connection
connection.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;" _
& "Data Source=SQL01;Initial Catalog=110"
' DEFINE COMMAND AND RECORDSET
Set cmd = New ADODB.Command
cmd.ActiveConnection = connection
Set rs = cmd.Execute(query, sSQLArtikel) ' BIND PARAM VALUES
' ... DO SOMETHING WITH rs
rs.Close: connection.Close
Set cmd = Nothing: Set rs = Nothing: Set connection = Nothing
End Function
When executing the command "Set rs = cmd.Execute(query, sSQLArtikel)" an errormessage is displayed "the command text is not set for the command object".
I am doing something wrong but what?

Consider the industry best practice of parameterization whenever running SQL in application layer like VBA. Doing so, you avoid the need to concatenate and punctuate variables to an SQL string.
Specifically, the missing quotes around string literals (sSQLArtikel) is your issue. With ADO Command.Execute, you can define recordsets with binded parameters.
Dim query As String
Dim connection As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
' PREPARED STATEMENT WITH PARAM PLACEHOLDERS
query = "select itemcode from items where itemcode = ?"
' OPEN CONNECTION
Set connection = New ADODB.Connection
connection.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;" _
& "Data Source=SQL01;Initial Catalog=110"
' DEFINE COMMAND AND RECORDSET
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = connection
.CommandType = adCmdText
.CommandText = query
.Parameters.Append .CreateParameter(, adVarChar, adParamInput, _
Len(sSQLArtikel), sSQLArtikel)
Set rs = .Execute
End With
' ... DO SOMETHING WITH rs
rs.Close: connection.Close
Set cmd = Nothing: Set rs = Nothing: Set connection = Nothing

Related

Excel VBA to update an SQL date field

I'm trying up date an SQL table (Date field) with a date cell in excel and getting an error
Error #-2147217913: Operand type clah int is incompatible with Date
Connection to the database is fine.
This is the code i'm using
Private Sub CommandButton1_Click()
On Error GoTo FormLoadError
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
Dim FromDate As Date
Dim ToDate As Date
Dim FromNumber As String
Sheet2.Range("a2:zz9999").ClearContents
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=SQL;" & _
"Initial Catalog=M2MTECLIVE;" & _
"Integrated Security=SSPI;"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
' Open the connection and execute.
conn.Open sConnString
FromDate = Worksheets("Parameters").Range("b4") 'Cell be contains a date in the format YYYY-MM-DD
Set rs = conn.Execute("update dbo.M2MDates set FD = " & FromDate)
conn.Close
Any ideas ?
Consider using ADO parameters via ADO command object which avoids need of concatenating and punctuating values to SQL statement:
conn.Open sConnString
' PREPARED STATEMENT WITH QMARKS ?
strSQL = "update dbo.M2MDates set FD = ?"
FromDate = Worksheets("Parameters").Range("b4")
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = strSQL
.CommandType = adCmdText
' BIND DATE PARAMETER
.Parameters.Append .CreateParameter("date_prm", adDate, adParamInput, , FromDate)
' EXECUTE ACTION QUERY (NO RECORDSET)
.Execute
End With
conn.Close
Set cmd = Nothing: Set conn = Nothing

Using VBA to call a stored procedure in SQL Server, passing one parameter. I'm getting an error, multiple-step OLD DB

Going round in circles on this. I'm using VBA to call a stored procedure to pull in some data from SQL Server.
It passes one parameter which is valuation date. I have tested this SQL Server stored procedure and it works fine in sql with all dates. Now the strange thing is the query works perfectly fine from VBA and SQL for dates 10/31/2019 and previous, but for 11/30/2019 and 12/31/2019, I get an error
Run-time error '-20147217887 (8004e21)': Multiple-step OLe DB operation generated errors.
I can't figure out why it would work for the some dates but not others when it works for all date directly in SQL. Thanks in advance.
Here is the VBA code:
Sub GroupExperience()
'SQL code
Dim ValDate As Date
ValDate = Format(Range("ValDate"), "mm-dd-yyyy")
Dim rs As ADODB.Recordset
Dim cnSQL As ADODB.Connection
Dim sqlcommand As ADODB.Command, prm As Object
Set cnSQL = New ADODB.Connection
cnSQL.Open "Provider=SQLOLEDB; Data Source=bddc1didw1;Initial Catalog=Actuarial; Trusted_connection=Yes; Integrated Security='SSPI'"
Set sqlcommand = New ADODB.Command
sqlcommand.ActiveConnection = cnSQL
'GroupExperience
sqlcommand.CommandType = adCmdStoredProc
sqlcommand.CommandText = "[HRT\akapur].[AllGroupExperience]"
Set prm = sqlcommand.CreateParameter("ValDate", adDate, adParamInput)
sqlcommand.Parameters.Append prm
sqlcommand.Parameters("ValDate").Value = ValDate
Set rs = New ADODB.Recordset
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Open sqlcommand
Sheets("Experience Data").Range("A2").CopyFromRecordset rs
Dim pt As PivotTable
Set pt = Sheets("Experience").PivotTables("PivotTable1")
pt.RefreshTable
End Sub

Derive parameters of a stored procedure in VBA

I've tried searching a lot of places and can't quite find what I'm looking for.
I want to write a sub routine in vba that will tell me the parameters of a stored procedure stored on SQL Server.
I know how to execute a stored proc with parameters from excel vba. And I have written a stored proc that takes a stored proc name and returns the parameters. So I could use this. But I thought maybe there is a better way that I don't know about. I found a SQLCommandBuilder Class for VB that would be perfect but I need it in VBA. Is this available in VBA and I just don't know where to activate it?
Thanks
**Additional information: After the helpful comments below I am getting closer to what I am aiming to achieve.
I want to be able to pass any stored procedure into my subroutine and it will be able to figure out how many parameters it needs and what they will be
Here is my code so far
Private Sub execStoredProcedureWithParameters(strServer As String,
strDatabase As String, strSchema As String, strUSPName As String)
'Declare variables
Dim cmd As ADODB.Command
Dim conn As ADODB.Connection
Dim prm As ADODB.Parameter
Dim rs As ADODB.Recordset
Dim intParamCount As Integer
'Open database connection
Set conn = New ADODB.Connection
conn.ConnectionString = "Provider=sqloledb;Data Source=" + strServer + ";Initial Catalog=" + strDatabase + ";Integrated Security=SSPI;"
conn.CommandTimeout = 0
'Here's where the connection is opened.
conn.Open
'This can be very handy to help debug!
'Debug.Print conn.ConnectionString
Set cmd = New ADODB.Command
With cmd
.CommandText = strSchema + "." + strUSPName
.CommandType = adCmdStoredProc
.ActiveConnection = conn
.Parameters.Refresh
For intParamCount = 0 To .Parameters.Count - 1
Debug.Print .Parameters(intParamCount).Name, .Parameters(intParamCount).Type, .Parameters(intParamCounti).Size, .Parameters(intParamCount).Attributes, .Parameters(intParamCount).NumericScale
' Set prm = cmd.CreateParameter(.Parameters(i).Name, adVarChar, adParamInput, 255)
' cmd.Parameters.Append prm
' cmd.Parameters(.Parameters(i).Name).Value = "DBName"
Next
End With
Set rs = New ADODB.Recordset
'Execute the Stored Procedure
Set rs = cmd.Execute
'Populate the sheet with the data from the recordset
Sheet1.Range("RecordSet").CopyFromRecordset rs
'Cleanup
rs.Close
Set rs = Nothing
conn.Close
Set conn = Nothing
End Sub
Concerning the parameters. Is there a way to convert the DataTypeEnum from the value to the constant. So the type is currently coming through as 202 for the first parameter which I would set to adVarWChar according to this table
https://learn.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum
You can do this with ADODB, add a reference to Microsoft ActiveX Data Objects then you can:
With New ADODB.Command
Set .ActiveConnection = myAdoDbConnection
.CommandText = "[dbo].[usp_XXX]"
.CommandType = adCmdStoredProc
.Parameters.Refresh
For i = 0 To .Parameters.Count - 1
Debug.Print .Parameters(i).Name, .Parameters(i).Type, .Parameters(i).Direction
Next
End With
There should be a necessity requiring this as it requires a round trip to the server.

ADODB Recordset.Open giving syntax error excel to SQL

I'm toast, cannot figure out why I'm getting a SYNTAX error on the line
rst.Open strSQL
I've tried it with rst.Open strSQL, cnt, adOpenStatic, adLockReadOnly, adCmdText
But it still gives me an error.
I have a sneaking suspicion it has to do with how strSQL is taking a cell value and appending it to the end of a string.
Any help is highly appreciated.
Public Sub EzPz()
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Set cnt = New ADODB.Connection
Set rst = New ADODB.Recordset
Dim strSQL As String
'Open connection
cnt.ConnectionString = "Driver={SQL Server};Server=HIDDEN;Database=HIDDENXX;Trusted_Connection=yes;UID=HIDDENU;PWD=HIDDENP;"
cnt.Open
'String for SQL cmd
Dim p1 As Range
Set p1 = ActiveSheet.Cells(1, 4)
strSQL = "SELECT DBNAME.vItem.Upc FROM DBNAME.vItem WHERE vItem.ItemDesc=" & p1.Value
rst.ActiveConnection = cnt
rst.Open strSQL
ActiveSheet.Cells(1, 1).CopyFromRecordset rst
End Sub
Your code is subject to SQL injection. You could enclose the string literal in single quotes as shown in this answer to fix the syntax error, but that wouldn't fix the serious security issue.
Obligatory XKCD
So how do you securely parameterize a query? With parameterized queries!
Dim conn As ADODB.Connection
Set conn = New ADOBD.Connection
.ConnectionString = "connection string ideally using Windows Authentication"
.Open
Ideally your connection string doesn't contain any username or password; your server needs to be configured to support Windows Authentication for this to work - the query then executes with the credentials of the logged-in Windows user, with the privileges of that user.
Dim cmd As ADODB.Command
Set cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
cmd.CommandText = "SELECT DBNAME.vItem.Upc FROM DBNAME.vItem WHERE vItem.ItemDesc = ?;"
Set up a Command object. The CommandText will be your SQL statement, but instead of concatenating the parameters into it, you use a ? question mark for each.
Dim itemDesc As ADODB.Parameter
Set itemDesc = New ADODB.Parameter
itemDesc.Type = adVarChar
itemDesc.Direction = adParamInput
itemDesc.Value = p1.Value
cmd.Parameters.Append(itemDesc)
Create a Parameter for each ? question mark in the SQL statement. You must supply a parameter for each ? question mark.
Dim results As ADODB.Recordset
Set results = cmd.Execute
You obtain the Recordset by calling the command's Execute method; the server deals with the parameters.
ActiveSheet.Cells(1, 1).CopyFromRecordset results
If all went well, the Recordset contains your results.
Always use parameterized queries: user input concatenated into SQL statements is a plague.
SQL needs to understand string literals as such; you need to delimit string literals with single quotes for the syntax to be valid.
Can you try this to see if that works?
strSQL = "SELECT DBNAME.vItem.Upc FROM DBNAME.vItem WHERE vItem.ItemDesc= '" & p1.Value & "'"

Write in a field's record in an Access' table

Issue :
I wrote this code which is supposed to write in a specific record of the WPRCPart field, but for some unknown reasons, nothing happens when I run it.
There are no errors though, it's just that this execution produces no result.
The data type of the WPRCPart field is Short Text.
The data type of the PartNo field is Number and its values come from a value List in Combo Box which can contains Multiple values.
Any ideas ?
Dim conn As New ADODB.Connection
Dim connStr As String
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & "mypath" & "NewVersion.accdb" & ";"
conn.ConnectionString = connStr
conn.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = "UPDATE OverViewNew Set WPRCPart = 'Yes' WHERE PartNo = 9165267"
End With
Set rs = cmd.Execute
'rs.close