Syntax error Inserting values into SQL Server via MS Access VBA - sql-server

From a form fields in MS Access I'm attempting to move the values to a SQL Server table.
Thanks
When I execute the VBA code I receive the following message of "Syntax error in INSERT INTO statement".
I can take the code from the Immediate display and copy it to the SQL Server New Query tab and execute it and it performs the command perfectly. What suggestions does anyone have as to what I'm performing incorrectly?
Private Sub btnSixClicksAdmittedPatientsByDates_Click()
On Error GoTo Err_btnSixClicksAdmittedPatientsByDates_Click
Dim Response As Integer
Dim dbs As DAO.Database
Dim rs As DAO.Recordset
Dim sqlstr As String
Dim objControl As Control
Set dbs = CurrentDb
sqlstr = "INSERT INTO [mcif].[dbo].[tblSixClicks_Report_Criteria] ([Rehab_SixClicks_Campus],[Rehab_SixClicks_Department]) " & _
"VALUES ('" & cboReportCampusSelection.Value & "','" & CBOReportDepartmentSelection.Value & "')"
Debug.Print sqlstr
DoCmd.SetWarnings False
DoCmd.RunSQL sqlstr
DoCmd.SetWarnings True
Immediate view that works in SQL Server:
INSERT INTO [mcif].[dbo].[tblSixClicks_Report_Criteria] ([Rehab_SixClicks_Campus],[Rehab_SixClicks_Department]) VALUES ('DMM','DML 3 EAST')

Related

How to overcome resource limitation of IN operator in Microsoft SQL Server

I am trying to pass over 37K values in the WHERE clause using IN operator through Excel VBA macro. However, due to resource limitation in Microsoft SQL Server, the query won't execute. I have tried to pass the values in an array in VBA as well as tried creating a list in in SQL. Neither are able to accommodate these many values. Can somebody help? Sharing the code I have tried below.
Dim i as Long
Dim str As String
Dim dict_pn
Set dict_pn = CreateObject("Scripting.Dictionary")
i = 1
With InputS
For i = 1 to 50000
str = Trim(.Cells(i, PN_Col).Value)
dict_pn.Add str, 0
Next
With rsPubs
' Assign the Connection object.
.ActiveConnection = cnPubs
.Open Worksheets("SQL Script").Range("A1") & "('" & Join(dict_pn.keys, "','") & "') " & Worksheets("SQL Script").Range("A2") & "('" & Join(dict_pn.keys, "','") & "') " & Worksheets("SQL Script").Range("A3") & "('" & Join(dict_pn.keys, "','") & "') "
ActiveWorkbook.Worksheets("SQL Results").Range("A3").CopyFromRecordset rsPubs
You should transmit data to SQL Server like in related post
Sub UpdateTable()
Dim cnn As Object
Dim wbkOpen As Workbook
Dim objfl As Variant
Dim rngName As Range
Workbooks.Open "C:\your_path_here\Excel_to_SQL_Server.xls"
Set wbkOpen = ActiveWorkbook
Sheets("Sheet1").Select
Set rngName = Range(Range("A1"), Range("A1").End(xlToLeft).End(xlDown))
rngName.Name = "TempRange"
strFileName = wbkOpen.FullName
Set cnn = CreateObject("ADODB.Connection")
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
nSQL = "INSERT INTO [odbc;Driver={SQL Server};Server=Server_Name;Database=[Your_Database].[dbo].[TBL]]"
nJOIN = " SELECT * from [TempRange]"
cnn.Execute nSQL & nJOIN
MsgBox "Uploaded Successfully"
wbkOpen.Close
Set wbkOpen = Nothing
End Sub
and then you can do any you want - use operator IN or LEFT JOIN whith check for null on SQL server side.
You can use temporary table if you will not close connection - temp table exists only in session level.
This is way from VBA code.
Second way - you can use SSIS package to work with excel files. In package you will have same steps - data frlow to transmit data from excel to server and then run sql code to join data. Or you can use join block inside SSIS package.
Third way that you can implement if data in SQL server less than excel row count limit. You can import data from SQL into Excel sheet, and than use VLOOKUP() function to join tables and find related data.

Running SQL queries from inside spreadsheet cells

I have an Excel spreadsheet with several SQL queries stored in different cells and I'd like to execute these queries on SQL Server to generate a new sheet where each cell is the query result from the original spreadsheet. The idea behind this is to preserve the sheet formatting when generating the results (conditional formatting and etc.).
Something like this:
Input spreadsheet:
Database
Information A
Information B
DB 1
SQL Query 1
SQL Query 2
DB 2
SQL Query 3
SQL Query 4
Output spreadsheet:
Database
Information A
Information B
DB 1
Result of Query 1
Result of Query 2
DB 2
Result of Query 3
Result of Query 4
I wasn't able to find ideas on how to do exactly this during my research of the subject, but I do believe it should be doable using either VBA or some scripting language.
Any thoughts on how should I approach this?
I've got it done using Power Query. It was way easier than I thought. Special thanks to Jacek Wróbel for providing the idea in the comments.
As an aside, you could do something like this.
Sub ADOExcelSQLServer()
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "EXCEL-PC\SQLEXPRESS" ' Enter your server name here
Database_Name = "Northwnd" ' Enter your database name here
User_ID = "" ' enter your user ID here
Password = "" ' Enter your password here
SQLStr = "SELECT * FROM Orders" ' Enter your SQL here
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
rs.Open SQLStr, Cn, adOpenStatic
With Worksheets("Sheet1").Range("A1:Z500")
.ClearContents
.CopyFromRecordset rs
End With
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
That sits in a VBA Module. Of course, you could store the SQL in an Excel cell, and do this...
SQLStr = Worksheets("Sheet1").Range("A1").Value
Also, you could loop through a bunch of cells and run a bunch of SQL jobs.
Your own imagination is your only limitation.

Excel VBA: ODBC SQL server driver query timeout expired

I have the below VBA query used in Excel 2016 that exacutes a MS Sql stored procedure, sometimes it executes smoothly and returns the recordset, but more often I get an error [Microsoft][ODBC SQL Server Driver] query timeout expired.
At the same time when we go to SSMS and execute the query it runs without issues.
This assumes the issue is rather caused by Excel/VB than by SQL or the query itself.
Searching for this error results in checking network firewalls, but we tried on other machines without firewalls, problems persists.
Here is the VB code:
Public Sub GetDataset2()
Dim cn As ADODB.Connection
Dim cm As Object
Dim rs As ADODB.Recordset
Dim UID, PWD, DB As String
UID = "userId"
PWD = "passworD"
DB = "192.168.1.1"
Set cn = New ADODB.Connection
Set cm = CreateObject("ADODB.Command")
cm.CommandTimeout = 0
cn.Open ("Driver={SQL Server};Server=" & DB & ";Database=myDatabaseName;Trusted_Connection=no;Timeout=900;Uid=" & UID & ";Pwd=" & PWD)
Set rs = cn.Execute("Get_dataset2 '" & Format(Range("dateFrom"), "yyyy-mm-dd") & "' ,'" & Format(Range("dateTo"), "yyyy-mm-dd") & "' ")
Dim lRow As Long
'Find the last non-blank cell in column A(1)
lRow = Sheets("data").Cells(Rows.Count, 1).End(xlUp).Row
lr = "A" & lRow + 1
Sheets("data").Range(lr).CopyFromRecordset rs 'insert data
cn.Close
End Sub
Any suggestion is appreciated.
Joel
After some more thought about the question and the comments on my prior answer, here are some additional points. To BitAccesser, cn.CommandTimeout is the same as Connection.CommandTimeout since the originally submitted code had already dimensioned and set the cn object as an ADODB.Connection. Also worth noting is the difference between ConnectionTimeout and CommandTimeout. The connection timeout is network level, while the command timeout is SQL Server level. In this case, even though a ADODB.Command object is instantiated, it isn't used. Another point relates to the connection string. The connection timeout could be referenced in the connection string, but often, is not used. The connection will be defaulted to 15 seconds. So, its worth resetting those attributes explicitly.
Cn.CommandTimeout = 50
Cn.ConnectionTimeout = 50
One possible solution is to lengthen the connection command timeout value. Your current script has the value set to 0. This could be increased. Running the query in SSMS should give you a rough idea of the time needed to complete the query. Then, adjust the value accordingly.
cm.CommandTimeout = 100
After weeks of testing various code changes, we found that when changing the SQL call to QueryTable method instead of CopyFromRecordset method, it is working fine.
So I am pasting the code if anyone needs it in future.
Sub GetDataset3()
Dim cn As ADODB.Connection
Dim Rs As ADODB.Recordset
Dim UID, PWD, SRV As String
UID = "userId"
PWD = "passworD"
SRV = "192.168.1.1"
If Sheets("data").QueryTables.Count = 0 Then
Sheets("data").Cells.Select
Selection.ClearContents
Dim Str As String 'adds backround query
Str = ""
For Each cell In Range("A1:A10").Cells
Str = Str & Chr(10) & cell
Next
With Sheets("data").QueryTables.Add(Connection:="ODBC;UID=;PWD=;DRIVER=SQL
Server;SERVER=SRV", Destination:=Range("a2"))
.CommandText = "select 1"
'BackgroundQuery = True
'.Refresh BackgroundQuery = True
.FieldNames = False
.AdjustColumnWidth = False
End With
End If
With Sheets("data").QueryTables(1)
.Connection = "ODBC;DRIVER=SQL Server;SERVER=" & SRV &
";database=myDatabaseName;UID=" & UID & ";Pwd=" & PWD &
";Trusted_Connection=no;APP=Microsoft Office"
.CommandText = ("Get_dataset2 '" & Range("dateFrom") & "' ,'" &
Range("dateTo") & "' ")
BackgroundQuery = True
.Refresh BackgroundQuery:=False
End With
End Sub

runtime error 3704 on a opened object

I am struggling with this situation
I have a query that when i run in MSSQL server management studio it gives me 18 rows, it it stored in a cell. The database is connected to a live server and we would like to create Excel dashboards out of them so it get refreshed with live data and create graph etc....
***** EDIT *****
I tried a very simple query and it works i can get for example
select max(datetime)from table and i do have the latest sync.
The thing is: my query has
1) A Declared table for validation
2) A temporary table "with table as( ) ;" that sorts all data and rank them with some filtering "RowNumber" that is called later in with a where statement that take only some row numbers to avoid repeats
I think that in between the connection must close, can it be?
Normally this code works out but for this server i get:
"runtime error 3704 operation is not allowed when the object is closed"
I've searched the forum and the google with no luck
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Dim query As String
Set con = New ADODB.Connection
Set rs = New ADODB.Recordset
strCon = "Provider=SQLOLEDB.1;" _
& "Password=*******;" _
& "Persist Security Info=True;" _
& "User ID=********;" _
& "Initial Catalog=*******;" _
& "Data Source=***.**.**.**;" _
& "Use Procedure for Prepare=1;" _
& "Auto Translate=True;Packet Size=4096;" _
& "Use Encryption for Data=False;" _
& "Tag with column collation when possible=False"
con.Open (strCon)
rs.ActiveConnection = Con 'modified with suggestion below
strSQLQuery = Worksheets("Query").Range("B2").Value
rs.Open strSQLQuery
For i = 0 To rs.Fields.Count - 1
Sheet2.Cells(1, i + 1) = rs.Fields(i).Name
Next i
Worksheets("Result").Range("A2").CopyFromRecordset rs
rs.Close
Set rs = Nothing
con.Close
Set cn = Nothing
Can a magician help me out? because now im doing it with excel VBA as a demo but i would like to promote it to a VB tool and want to make sure it is not a server related issue.
Thank you in advance
con.Open (strCon)
rs.ActiveConnection = strCon
should be
con.Open strCon
rs.ActiveConnection = con
ie. you should set ActiveConnection to the Connection object you just opened, not to the connection string.

Execute SQL Server stored procedure in VBA with multiple outputs

I have a stored procedure in SQL Server that I am trying to execute from Excel via some VBA code. However, the stored procedure has two outputs (see below).
My record set is only pulling in the first table (added 0 error messages...) whereas I want to pull in the second table.
Image here: http://i.stack.imgur.com/LxyLi.png
Here is my code, compiled from other sources I found on here:
Sub RefreshBarcodes()
Dim Database As String
Dim con As ADODB.Connection
Dim strconn As String
Dim SQLServer As String
Dim Session As String
Dim strSQLCommandOne As String
Application.ScreenUpdating = False
Worksheets("Master").Activate
Database = Worksheets("Master").Cells(5, "H").Value
SQLServer = Worksheets("Master").Cells(4, "H").Value
Session = Worksheets("Master").Cells(6, "H").Value
'Connect to Database
Set con = New ADODB.Connection
strconn = "Provider=sqloledb; Data Source=" & SQLServer & ";Initial Catalog = " & _
Database & "; INTEGRATED SECURITY=SSPI; "
con.Open strconn
'Set SQL Commands
strSQLCommandOne = "set nocount on; exec spGetSessionSourceCounts 'HNW-CLU-001-024_01_0005'"
'Open Recordset
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
'Execute and copy to Excel
rs.Open strSQLCommandOne, strconn
rs.MoveFirst
Worksheets("Session").Activate
Cells(1, 1).Select
ActiveCell.CopyFromRecordset rs
rs.Close
Worksheets("Master").Activate
Cells(6, "H").Value = "Session updated"
con.Close
Application.ScreenUpdating = True
End Sub
Excel output: http://i.stack.imgur.com/b7i3B.png
I would love to be able to pull in the first (error message) and second results (session info), but mainly need only the second table. Thanks so much in advance!
To access the second recordset, you need to execute this line:-
'Activate the next available recordset
Set rs = rs.NextRecordset
If Not rs Is Nothing Then
'Add code in here
End If

Resources