VBS Script to Execute SQL statement? - sql

To open, I have never written a vbs script. I have written many SQL scripts, views, developed databases. I have written plenty of VBA in Access applications.
For this, I am just trying to set up a SQL script as a VBS script, so the users don't have to go into SSMS to run it. They can just double-click the VBS script, specify the server and database when prompted, and the quick script will run for them.
This is what I have gotten so far, but I keep getting Microsoft VBScript compilation errors. The latest one is line 3 char 17, which is on a Dim statement. Just wanted to see if anyone can tell if I am missing something fundamental to this script, that is preventing it from compiling or processing correctly.
This is the very short script:
Dim conn
Set conn = createobject("Adodb.Connection")
Dim sConnString As String
Dim SqlStatement As String
sSourceServer = InputBox ("Enter the name of the SQL Server","Enter SQL Server Name","")
If Len(sSourceServer) = 0 Then
MsgBox "No SQL Server was specified.", , "Unable to Continue"
Exit Sub
End if
sSourceDB = InputBox ("Enter the name of the Law SQL Database","Enter Law SQL DB Name","")
If Len(sSourceDB) = 0 Then
MsgBox "No SQL DB was specified.", , "Unable to Continue"
Exit Sub
End if
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=" & sSourceServer & "; Initial Catalog=" & sSourceDB & "; Integrated Security=SSPI;"
MsgBox sConnString
' Open the connection and execute.
conn.Open sConnString
conn.CommandTimeout = 900
SqlStatement = "UPDATE [tablename] " & _
"SET UUID = CASE WHEN CHARINDEX('.',[Filename]) > 1 THEN LEFT(CAST([Filename] AS VARCHAR),CHARINDEX('.',[Filename])-1) ELSE [Filename] END " & _
"WHERE [Filename] IS NOT NULL"
conn.Execute(SqlStatement)
conn.Close
Set rs = Nothing
SqlStatement = vbNullString
MsgBox "All Done! Go Check your results!"
If anyone can help, I'd greatly appreciate it.
Thank you

nevermind. I kept troubleshooting and finally got it to work. For those that this might help, unlike VBA, it's easier not to declare variables as a type. just Dim them and move on. see below:
Dim conn
Set conn = createobject("Adodb.Connection")
Dim sConnString
Dim SqlStatement
StartScript
Sub StartScript()
sSourceServer = InputBox ("Enter the name of the SQL Server","Enter SQL Server Name","")
If Len(sSourceServer) = 0 Then
MsgBox "No SQL Server was specified.", , "Unable to Continue"
Exit Sub
End if
sSourceDB = InputBox ("Enter the name of the Law SQL Database","Enter Law SQL DB Name","")
If Len(sSourceDB) = 0 Then
MsgBox "No SQL DB was specified.", , "Unable to Continue"
Exit Sub
End if
' Create the connection string.
sConnString = "Provider=SQLOLEDB;Data Source=" & sSourceServer & "; Initial Catalog=" & sSourceDB & "; Integrated Security=SSPI;"
' Open the connection and execute.
conn.Open sConnString
conn.CommandTimeout = 900
SqlStatement = "UPDATE [tablename] " & _
"SET UUID = CASE WHEN CHARINDEX('.',[Filename]) > 1 THEN LEFT(CAST([Filename] AS VARCHAR),CHARINDEX('.',[Filename])-1) ELSE [Filename] END " & _
"WHERE [Filename] IS NOT NULL"
conn.Execute(SqlStatement)
conn.Close
Set rs = Nothing
SqlStatement = vbNullString
End Sub
MsgBox "All Done! Go Check your results!"
Remember, for those looking to use this as a basis for a script - I'm not doing any checks, so if you don't know your data, this is a dangerous thing to run.
Know your data, backup your data, and if you can, add in some checks, to make sure anything that isn't a select statement, is checked and re-checked before it is run.

Related

Automation Error when Attempting to Query Access Database Using VBA

I've made the following ADODB object declarations in code.
Dim OConn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim fld As ADODB.Field
Set OConn = New ADODB.Connection
Set rs = New ADODB.Recordset
I would like to use the following code to read from a table on a MS Access database file and generate a recordset, rs.
'Get the table name from the search results.
tableName = ThisWorkbook.Sheets("PLC Module Data").Cells(2, 9).Value
'Set the SQL string.
strSql = "SELECT Code, Points, Type, Description, Rating " & _
"FROM " & tableName
'Set the connection string and open the connection to the Access DB.
OConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=Q:\AutoCAD Improvements\PLC IO Utility Docs\PLC IO Spreadsheet
App\PLC IO App\ace_plc.mdb"
OConn.Open
'Open the recordset and error out if nothing is returned
Set rs = OConn.Execute(strSql)
If rs.EOF Then
MsgBox "No matching records found."
rs.Close
OConn.Close
Exit Sub
End If
I've checked the query statement within the Access file itself and it works fine. I always get the error
Run-time error'-2147217900 (80040e14)': Automation Error
on the line,
Set rs = OConn.Execute(strSql)
If anyone could take a look over my code and determine why this is happening it would be much appreciated. I've looked at similar examples online and it seems like this should be correct.
I added the brackets around the tableName string and it works now. Thanks for all the feedback.
'Set the SQL string.
strSql = "SELECT Code, Points, Type, Description, Rating " & _
"FROM [" & tableName & "]"

Performing SQL queries on basic Excel 2013 worksheet as table using ADO with VBA triggers Errors

I'm developping modules on a client XLSm with 32-bits 2013 Excel.
I'd like to use datas on worksheet as if it is an Access table.
With a lot of difficulties, I think connection is now OK.
Still, I have error : 3001 Arguments are of wrong type, are out of acceptable range. Error that I cannot understand.
Here excerpts of VBA lines :
In addition, I added 20 lines in data Worksheet below the header line to permit to Excel to interpret for the type of each columns.
varCnxStr = "Data Source=" & G_sWBookREINVOICingFilePath & ";" & "Extended Properties='Excel 12.0 Xml;HDR=YES;IMEX=15';"
With conXLdb
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Mode = adModeShareExclusive
.Open varCnxStr
End With
strSQL = "SELECT * "
strSQL = strSQL & " FROM [ReInvoiceDB$B2B5072] inum "
strSQL = strSQL & " WHERE inum.InvoiceNum LIKE '1712*' "
strSQL = strSQL & ";"
'>> TRIGGERs ERROR with the current Where Clause !!'
adoXLrst.Open strSQL, conXLdb, dbOpenDynamic, adLockReadOnly, adCmdText
If adoXLrst.BOF And adoXLrst.EOF Then
'no records returned'
GoTo Veloma
End If
adoXLrst.MoveFirst
Do While Not adoXLrst.EOF
'Doing stuff with row'
adoXLrst.MoveNext
Loop
sHighestSoFar = adoXLrst(1).Value '> just to try for RecordSet : Codes are not completed...
sPrefixeCURR = Mid(sHighestSoFar, 1, 4)
Highest = CInt(Mid(sHighestSoFar, 5))
'> Increment >'
Highest = Highest + 1
HighestStr = sPrefixeCURR & Format(Highest, "00")
strGSFNumber = HighestStr
adoXLrst.Close
conXLdb.Close
Veloma:
On Error Resume Next
Set adoXLrst = Nothing
Set conXLdb = Nothing
Exit Sub
Etc.
Any idea about what seems be wrong ?
Thank you
Below is an old example I have been using successfully. Note that the sheet name in the book are Sheet1 and Sheet2, but in the query I had to use sheet1$ and sheet2$. I noticed you had $ signs in the middle of your sheet names. perhaps that's the issue ?
Sub SQLUpdateExample()
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset
Set con = New ADODB.Connection
con.Open "Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=" & ThisWorkbook.FullName & ";" & _
"DefaultDir=" & ThisWorkbook.FullName & ";ReadOnly=False;"
Set rs = New ADODB.Recordset
Set rs = con.Execute("UPDATE [Sheet1$] inner join [Sheet2$] on [Sheet1$].test1 = [Sheet2$].test1 SET [Sheet1$].test3 = [Sheet2$].test2 ")
Set rs = Nothing
Set con = Nothing
End Sub
To give more details about the whole module to be implemented : it is to perform a Transaction unit.
This transaction will comprise 3 operations : get a max value from a column (Invoice number) to increment it, record the new number inside an Access table (by DAO), the same Excel file (by ADO) and generating document on HDD.
So it is aimed to use the Excel file as a table not as a file manipulated with Windows script or Excel VBA. My end user is disturbed by the pop-uping of an Excel opening file operation. As a developer, I'm feeling more comfortable with using SQL statements as much as possible inside Transaction session. Is that your opinion too ?

how to rewrite code from DAO to ADO?

We got some old legacy application which was developed during 2000 and we have moved from access 2003 to 2007. When I am trying to run a module of an application, it is giving me an error:
"Run-time error 3847. ODBCDirect is no longer supported. Rewrite the code to use ADO instead of DAO".
And it highlights to the line Set WS = CreateWorkspace("NewWS", "", "", dbUseODBC). As I am really new to Access, I did research before posting this issue here but no luck. I am trying to rewrite the code to use ADO instead of DAO.
Following is my old vba code:
Public Function GetID (ByRef SegmentItem As clsSegmentDefinitions) As Long
Dim qdf As QueryDef
Dim qdfNewID As QueryDef
Dim rs As Recordset
Dim rsNewID As Recordset
Dim NaturalDescription As String
Dim WS As Workspace
Dim con As Connection
Set WS = CreateWorkspace("NewWS", "", "", dbUseODBC)
WS.DefaultCursorDriver = dbUseODBCCursor
Set con = WS.OpenConnection("", , , SQLConnectString)
DoCmd.Hourglass False
DoCmd.OpenForm " frmQuickAdd_AddNatural ", , , , , acDialog, SegmentItem.AddValue
DoCmd.Hourglass True
If Form_frmQuickAdd_AddNatural.Tag Then
Set qdf = con.CreateQueryDef("", "{ ? = call sp_Insert(?, ?, ?) }")
qdf.Parameters.Refresh
qdf![#prmDescription] = Left(Form_frmQuickAdd_AddNatural.txtSegmentDescription, 34)
qdf![#prmCreateUser] = CurrentUser
qdf![#prmProjectID] = 0
qdf.Execute
Set qdfNewID = CodeDb.CreateQueryDef("")
qdfNewID.Connect = SQLConnectString
qdfNewID.ReturnsRecords = True
qdfNewID.SQL = "sp_GetNewSegmentID"
Set rsNewID = qdfNewID.OpenRecordset
If Not IsNull(rsNewID!MaxOfSegmentID) Then
GetID = rsNewID!MaxOfSegmentID
Else
GetID = 0
End If
Else
GetID = 0
End If
DoCmd.Close acForm, "frmQuickAdd_AddNatural"
End Function
I had started to rewrite code but I have no clue if it is suppose to be like this at all.
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
cnn.Open "Provider=mssql;Data Source=" & dbq & ";User Id=" & uid & ";Password=" & pwd
With rst
.Open "SELECT COUNT(*) FROM " & tbl, cnn, adOpenKeyset, adLockOptimistic
num = .Fields(0)
.Close
End With
cnn.Close
Set rst = Nothing
Set cnn = Nothing
First, you really don’t want to introduce ADO into an application built and designed around DAO. Worse, is ADO has been on its way out for about 15 years now. In fact SQL server is dropping support for oleDB which ADO works on. (so don’t go there).
See this link about SQL server dropping oleDB support:
http://blogs.msdn.com/b/sqlnativeclient/archive/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access.aspx
The industry has moved away from ADO and all major vendors are suggesting to use Open Database Connectivity as the industry standard. (that means ODBC).
I would create and save a pass-though query in Access. You code can then be re-written as:
Public Function GetID(ByRef SegmentItem As String) As Long
Dim strSQL As String
strSQL = "sp_Insert('" & _
Left(Form_frmQuickAdd_AddNatural.txtSegmentDescription, 34) & "'," & _
"'" & CurrentUser & "', 0)"
With CurrentDb.QueryDefs("qryPass")
.SQL = strSQL
.ReturnsRecords = False
.Execute
End If
With CurrentDb.QueryDefs("qryPass")
.SQL = "sp_GetNewSegmentID"
.ReturnsRecords = True
GetID = Nz(.OpenRecordset()("MaxOfSegmentID"),0)
End With
End Function
So create one pass-though query. And you can use it quite much in all places where you were using JET-DIRECT. In access 2007, jet-direct support was dropped, but use of a simple pass-though query will more than suffice and also as the above shows save buckets of coding and developer time. If the “left” expression you have can return a null, then you likely need to wrap that expression in a nz() to return a “” (null string) or the appropriate value.

T-SQL query with variable declarations in Excel VBA Code fail

I got a problem with running SQL query with "declare" and "set" functions in VBA.
Sheets("Arkusz1").Select
connstring = _
"ODBC;DRIVER=SQL Server;SERVER=my_database_server;UID=user;PWD=password;APP=Microsoft Office 2010;WSID=some_id;DATABASE=mydatabase"
With ActiveSheet.QueryTables.Add(Connection:=connstring, Destination:=Worksheets("Arkusz1").Range("A1"), Sql:=Array( _
"declare #dzisiaj date" & Chr(13), _
"set #dzisiaj = getdate()" & Chr(13), _
"select #dzisiaj as dzisiaj"))
.BackgroundQuery = False
.Refresh
End With
In SQL Server 2012 that code works fine, but... when I embed it into it gives me a run-time error '1004'. Also VBA code works on other queries works well.
My full SQL query has about 90 lines with 2 variable declarations (one declaration is a value from another 30 line SQL query), so it's mandatory to include variable declarations :)
How to solve that problem?
I figured it out. The key is to use ADODB connection to import data via SQL Query. Also necessary is to check Microsoft Active X Data Objects 2.0 library in Tools->References in Visual Basic Editor (Shortcut: Alt+F11 in Excel).
So, there is an example of my VBA code:
Sub sql_query_import()
' Declarations
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 connection settings
Server_Name = "192.168.1.106\my_database" ' IP of server name
Database_Name = "mydatabase" ' Database name
User_ID = "myusername" ' User name
Password = "mypassword" ' User password
' SQL Query
SQLStr = "SET NOCOUNT ON " & Chr(13) ' it's mandatory if you don't want to get error 3704
SQLStr = SQLStr & "declare #dzisiaj date " & Chr(13)
SQLStr = SQLStr & "set #dzisiaj = getdate() " & Chr(13)
SQLStr = SQLStr & "select #dzisiaj as 'today'
' Connect to database
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
' Start connection
rs.Open SQLStr, Cn, adOpenStatic
' Load data
With rs
For i = 1 To .Fields.Count
Worksheets(1).Cells(1, i) = .Fields(i - 1).Name ' Include column name if not - delete it
Next i
End With
Worksheets(1).Cells(2, 1).CopyFromRecordset rs ' Start loading data to Cell A2
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
Using in SQL Query "SET NOCOUNT ON" is necessary if you don't want to get error 3704.
Also, using
SQLStr = "SET NOCOUNT ON " & Chr(13) ' it's mandatory if you don't want to get error 3704
SQLStr = SQLStr & "declare #dzisiaj date " & Chr(13)
is more efficient way to include multi-line SQL Queries :)
I'm still new to vb and vba and learning myself, but I know you can declare and write to variables in VB.net which can then feed into an embedded SQL script. I would think you can do the same thing in vba. Here's what I suggest.
Declare a vb string like SQL_Var_1
Insert the 30-line SQL query as a separate query before the main query.
Write the result of the 30-line query to the vb string SQL_Var_1.
Remove the declarations from the Main SQL query but leaving the references to those variables.
Reference SQL_Var_1 as an input parameter in the embedded main query using the exact same name you used in the main query (i.e., #dzisiaj), like here.
If you follow these steps for both SQL variables, you should be able to achieve the same result as if you were using the declared SQL variables.

Error in connecting to Access database from Excel macro

I have to create excel macro which fetches from access database and update appropriate columns in excel worksheet.
I have never done VBA programming before, i am just able to write a code to connect to the database which is giving me error saying "Error in From clause".
Sub Button2_Click()
Dim conn As New Connection
Dim rs As New Recordset
strcon = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\Users\Xprts8\Documents\shipping.accdb;" & _
"User Id=admin;Password="
conn.Open (strcon)
qry = "SELECT * FROM shipping-table"
rs.Open qry, conn, adOpenKeyset
rs.Close
conn.Close
End Sub
can anybody help me with the following problem
shipping-table is not a valid table name in an SQL statement (because of the hyphen) unless its escaped thusly:
SELECT * FROM [shipping-table]