The proper use of MSSQL "go" in VBA - sql-server

I am about to run a batch what I programmed using MSSQL, like this:
create function xy (
.....
end
go
create function2 xy (
...
end
go
Then, I saved it in a file, what my macro reads it into a string and with ADO trying to run. Unfortunately, all the time I get the following error message: Incorrect syntax near 'go'. I have been reading about it, and only found the solution to split the batch, but I don't really want since I have it in one string variable. My connection string in vba is the following (first the public declared variables):
Public conn As ADODB.Connection
Public rs As ADODB.Recordset
Public cmd As ADODB.Command
Public sConnString As String
On Local Error GoTo err
sConnString = "Provider=SQLOLEDB.1;Data Source=localhost;" & _
"Initial Catalog=" & database & ";" & _
"Integrated Security=SSPI;"
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
Set cmd = New ADODB.Command
conn.Open sConnString
conn.CursorLocation = adUseClient
cmd.ActiveConnection = conn
set rs = conn.Execute(mysqlstring)
I have also checked the file what I read in with vba and no problem with it, if I copy it then paste to microsoft sql, it works. It does not, if I use ADO.
Every help is much appreciated!
Marta

GO is default batch terminator, it is not correct TSQL.
"Signals the end of a batch of Transact-SQL statements to the SQL Server utilities."
GO is not a Transact-SQL statement; it is a command recognized by the sqlcmd and osql utilities and SQL Server Management Studio Code editor.
For your example make 2 calls to database or create these functions via SSMS.

Related

Is there some fast way to dump an ADO recordset into a new MS ACCESS table?

We have a SQL Server Backend with MS ACCESS 2016 Front. We have a general purpose ADO connection object that we use to send SQL commands off to our DB. When we have SQL that returns something, we were using code to build a passthru query object, which was a handly way to get SQL output into the frontend.
We are now in a situation where we have some really complex SQL that returns an output, but consists of several statements, including the construction of several temp tables on the server. We can't use the "build a passthru query object" method because passthrus can't handle multiple SQL Statements, and we can't send the SQL statements one at a time because the temp tables get destroyed after the query finishes.
At present, we are now using our ADO objects to get the output into an ADO recordset, then saving the recordset down as an .XML and then finally importing the .XML file into the DB. But this is a lot of I/O and it goes slow for large outputs.
Is there any better (faster) way to get the output of our complex SQL into a local table in the MS Access Frontend?
Heres a snippit of our vba class object:
Private Const DB_CONNECTION_STRING As String = "<our connection string>"
Private conn As ADODB.Connection
Private cmd As ADODB.Command
Private recAff As Long
______________________________________________________________
Private Sub Class_Initialize()
Set conn = New ADODB.Connection
Set cmd = New ADODB.Command
conn.Open DB_CONNECTION_STRING
With cmd
.ActiveConnection = conn
.CommandTimeout = 0
End With
End Sub
...
<more properties/methods>
...
Public Sub LocalizeOutput(fetchSQL As String, InputTableName As String)
'If the InputTableName does not exist, a new table will be created. All fields will be datatyped as Text
'Otherwise, if the InputTableName does exist, data will be appended. Caller is responsible for handling errors
Dim rs As ADODB.Recordset
Dim XMLFilePath As String
Dim domIn As Object
Dim domOut As Object
Dim domStylesheet As Object
XMLFilePath = Environ("TEMP") & "\TableImport.xml"
fetchSQL = "SET NOCOUNT ON; " & vbNewLine & fetchSQL
Set domIn = CreateObject("Microsoft.XMLDOM")
domIn.async = False
'Execute the query
With cmd
.CommandType = adCmdText
.CommandText = fetchSQL
Set rs = .Execute(recAff)
End With
Dim tbl As TableDef
'Save off the output as xml file
If FileExists(XMLFilePath) Then
Call FileDelete(XMLFilePath)
End If
rs.Save XMLFilePath, adPersistXML
'Write the XML Transformation File
Call WriteXSLTransform(InputTableName)
'Convert the ado_xml file into an Access readable xml file
domIn.Load XMLFilePath
Set domStylesheet = CreateObject("Microsoft.XMLDOM")
domStylesheet.Load Environ("TEMP") & "\ADOXMLToAccess.xsl"
Set domOut = CreateObject("Microsoft.XMLDOM")
domIn.transformNodeToObject domStylesheet, domOut
'Set domIn = Nothing
Call FileDelete(XMLFilePath)
'Save the output
domOut.Save XMLFilePath
'Import the saved document into Access
Application.ImportXML XMLFilePath, acAppendData
'clean up
Call FileDelete(XMLFilePath)
Call FileDelete(Environ("TEMP") & "\ADOXMLToAccess.xsl")
Set rs = Nothing
Set domIn = Nothing
Set domOut = Nothing
Set domStylesheet = Nothing
End Sub

Using excel to query sql server automatically when sheet is opened

I need an excel sheet along with a batch file such that that: when the batch file runs, the excel sheet opens, runs a query on an SQL database, and saves the contents to a differently named excel file.
I know this is asking a lot, so I apologize for the long request. I know exactly the query that I need to perform and I know how the batch file is supposed to work.
What I am having trouble with is the VBA code inside of excel that runs when the file is opened and performs the query. So, while I know how to run sql queries in SAS and in Micorsoft SQL, I am having a hard time figuring out how to make excel perform these queries automatically in the VBA code. Here's what I have, but it *when I run the code, I get the error "Compile error: user-defined type not defined"
Steps to help
Create a WorkBook Open Event and place your code there.
Learn how to open other works books using VBA. The documentation section here on SO has examples
Learn to write results using Offset property and xlUp command (just in case you need to write results to a log which tends to be the next row/columns
I use like this
Sub getDAtaFromServer()
Dim con As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim rst As New ADODB.Recordset
Dim strOldUDT As String
Dim strNewUDT As String
Dim aryTempUDT() As String
Dim strTempID As String
Dim i As Integer
con.ConnectionString = "Provider=SQLOLEDB.1;" _
& "Server=(local);" _
& "Database=TEST;" _
& "Integrated Security=SSPI;" _
& "DataTypeCompatibility=80;"
con.Open
Set cmd.ActiveConnection = con
cmd.CommandText = "SELECT * FROM [table] "
Set rst = cmd.Execute
Range("A1").CopyFromRecordset rst
con.Close
Set con = Nothing
End Sub

Executing stored procedure in sql-server from vb6?

Iam running a legacy VB6 application. I'm trying to execute a stored procedure that would go through a bunch of tables in SQL-SERVER, grab Data and put it into a table in SQL - SERVER. Do I need to declare and set a new recordset?
dim strSQL as string
strSQL = "Exec FillEmptyTable #blah = "& blah
It would seem that I don't need a recordset, but this doesn't execute
Now when i SET a new recordset, then it works
dim rs as adodb.recordset
set rs = new adodb.recordset
dim strSQL as string
strSQL = "Exec FillEmptyTable #blah = "&blah
rs.open strSQL, Connection
Is this right? I don't know why I need a recordset if I'm only creating one on SQL-SERVER side?
If you don't need a recordset because the SP returns no rows or you don't care about any rows it does return you can simply pass the SQL string to the connection object:
Connection.Execute strSQL, 0, adCmdText
See here for a more formal way using a Command object that removes potential the SQL injection vulnerabilities implicit in manually building SQL in a string.

Catching error message from SQL Server in VBA in Excel

I am doing an excel macro in order to automate some query what eventually I run in SQL Server. My problem is that I don't know how the server could alert excel if a query did not succeed.
For example, I am importing a file, and there is no syntax error, but it might result in error if bulk insert statement is not set properly. For the SQL connection I use the following:
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=localhost;" & _
"Initial Catalog=" & MyDatabase & ";" & _
"Integrated Security=SSPI;"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
conn.Open sConnString
Set rs = conn.Execute(Myquery)
If I have a syntax error while compiling the code it stops which is good. But if I have another problem, e. g. the database name is not good, the table already exists, then the program runs with no error, I only can detect when I check it in SQL Server. I really want to know somehow whether the query run has resulted in error and then code some alerting message then into my macro. How can I do that?
Every help is much appreciated!
The ADO connection object has an Errors collection, which you can check after running your SQL:
conn.Errors.Clear
Set rs = conn.Execute(Myquery)
If conn.Errors.Count &GT; 0 Then
For i = 0 To conn.Errors.Count
Debug.Print conn.Error(i).Number
Debug.Print conn.Error(i).Source
Debug.Print conn.Error(i).Description
next i
End If
That should get you started. You may find that you're seeing an 'error zero' that's actually a status message; if so, you'll have some additional coding to to do.
I found this helpful but needed to use:
Debug.Print conn.Errors.Item(i).Description
Debug.Print conn.Errors.Item(i).Source
Debug.Print conn.Errors.Item(i).NativeError
I might be using a different connection type

Calling Stored Procedure from MSAccess fails, but running the exact same command from Sql Server Manager works

I have an Access DB that has a bunch of linked tables from a SQL Server database. The Access DB calls a stored procedure on the SQL Server database that updates data on a form.
Dim sql As String
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
cnn.ConnectionString = "DSN=Records"
cnn.CommandTimeout = 90
cnn.Open
sql = "exec myStoredProcedure #param1=" & Me.txtParam1Field & ", #param2=" & Me.txtParam2Field
cnn.Execute sql
Set cnn = Nothing
frmMyForm.Requery
When I run this it either times out, if the CommandTimeout value isn't long enough, or it executes, but doesn't actually execute myStoredProcedure for some reason. If I take the string sql and past it into Sql Server Manager, myStoredProcedure executes in less than a second and everything works great.
I've tried debugging over this code in Access, but I'm not getting any useful results when I step over cnn.Execute sql.
Depending on the values of txtParam1Field and txtParam2Field you probably want to enclose the values with single quote like so:
sql = "exec myStoredProcedure #param1='" & Me.txtParam1Field & "', #param2='" & Me.txtParam2Field & "'"
If we take your original code and assume that txtParam1Field is equal to 1 and txtParam2Field is equal to John then your generated sql will not execute because it will look like this:
exec myStoredProcedure #param1=1, #param2=John
Your best bet is to output the value of "sql" variable in debug window and run that exact statement in sql query manager. That will tell you exactly where the problem is if it's malformed SQL.
You could try setting the Prepared property to false on the command object. This causes a recompile of the procedure before execution, but could result in a better plan depending on the parameters that are sent.
Dim sql As String
Dim cnn As ADODB.Connection
Dim Cmd As ADODB.Command
Set cnn = New ADODB.Connection
cnn.ConnectionString = "DSN=Records"
cnn.CommandTimeout = 90
cnn.Open
sql = "exec myStoredProcedure #param1=" & Me.txtParam1Field & ", #param2=" & Me.txtParam2Field
Set Cmd = New ADODB.Command
Set Cmd.ActiveConnection = cnn
Cmd.CommandType = adCmdText
Cmd.CommandText = sql
Cmd.Prepared = False
Cmd.CommandTimeout = 300
Cmd.Execute

Resources