VBA and SQL - some help for a novice

G

Guest

I am curently using a number of macros each of which runs a large number of
queries. I am told that this is not good practice, and that I should write
VBA code which executes the SQL code for each of the queries in turn. So,
the VBA would do the same job as the macro, but in a single piece of code. I
see myself designing the query in the Query Window, then pasting the
corresponding SQL code at the appropriate place in the VBA.

Can anyone suggest how a VBA novice like me could start experimenting with
SQL in VBA code. Perhaps, someone could show me how to write some VBA code
which does the same job as a very simple macro (say, one which calls two
queries).

I hope this makes sense

Jim Jones
Botswana
 
G

Guest

Its a bit of a large subject for one post, but you are on the right lines
with copying/pasting the SQL.

There are different methods depending on the type of queries you are
running. This example is for an 'Action' query:

The code needed for an action query would be: (Free-typed so may not work
at first)

Dim db as Database
dim strSql as String

Set db = Currentdb()

strSQL = "SELECT Name, Address INTO Details FROM tblCustomers;"

db.Execute strSQL


To use a query as a recordset:

Dim db as Database
Dim rs as Recordset
Dim strSQL As String

Set db = Currentdb()
Set rs = db.Openrecordset("SELECT Name, Address FROM tblCustomers;")

Do Until rs.EOF

' Loop through the recordset
Msgbox rs("Name") & " - " & rs("Address")

rs.MoveNext

Loop



That is the basics. It gets a bit more complex when the SQL is longer and
if you want to use Parameters or reference forms, etc....

Good Luck!

Steve.
 
A

Allen Browne

Jim, this is a big question. Hopefully you are willing to spend some time
learning this, because it *really* makes a monster difference to what you
can do with a database.

At the most basic level, the VBA is:
DoCmd.OpenQuery "Query1"
If Query1 is a SELECT query, this shows the query to the user. If it is an
Action query (Delete, Update, or Make Table), it executes the query.

For an Action query, it is probably better to use:
DoCmd.RunSQL "Query1"

These queries ask for user confirmation before the action. If you wish to
avoid that:
DoCmd.SetWarnings False
before the query, and:
DoCmd.SetWarnings True
afterwards.

To run 2 queries, without confirmation, the code would be:
DoCmd.SetWarnings False
DoCmd.RunSQL "Query1"
DoCmd.RunSQL "Query2"
DoCmd.SetWarnings True

These approaches are essentially the same as the macro. You are using VBA,
but you have not gained any benefit. A major problem with turning off
SetWarnings is that you get no message if the action query failed. For
example, if you were deleting records from a table so you could use it
again, you have no idea whether all records were actually deleted, or if
someone was using them and some were not deleted at all. And you have no
idea how many records were deleted.

A better approach in VBA is to Execute the query:
dbEngine(0)(0).Execute "Query1", dbFailOnError
With this approach, you do not need to turn SetWarnings off. But if the
query does not complete successfully, it triggers a trappable error. Your
VBA code can now handle the error and exit gracefully instead of ignorantly
continuing with the assumption that the data is ready to use. If the idea of
error handling is new, see:
http://allenbrowne.com/ser-23a.html

After an Execute, you can see how many records were deleted/appended/updated
via the RecordsAffected property:
dbEngine(0)(0).Execute "Query1", dbFailOnError
MsgBox dbEngine(0)(0).RecordsAffected & " record(s)."

But the Execute also has a limitation that RunSQL does not. If your query
has a parameter or refers to a text box on a form like this:
[Forms].[Form1]![Text0]
the Expression Service (ES) in Access will interpret the reference and the
query will run. The Execute cannot do that, so you need to build up the SQL
statement in your code, concatenating the value from the form into the SQL
string. Example:
Dim strSql As String
strSql = "DELETE FROM Table1 WHERE ClientID = " & _
Forms!Form1!Text0 & ";"
Debug.Print strSql
dbEngine(0)(0).Execute strSql, dbFailOnError

The Debug.Print line above is optional. It dumps the SQL string to the
Immediate Window. After running the code, you can open the Immediate Window
(Ctrl+G) to see the statement that executed. If there is a problem with the
SQL statement, the execute will fail, but you will be able to see what it
tried to execute, which empowers you to get it right.

When you concatenate values into a SQL string like that, you need delimiters
around the values. For dates, the delimiter is #, e.g.:
strSql = "DELETE FROM Table1 WHERE EntryDate = #" & _
Forms!Form1!Text0 & "#;"
For Text type fields, the delimiter is the double-quote. Trouble with that
is that VBA is already using quotes to delimit the string. The convention is
to double-them up when they are embedded in a string. So, if you want:
This string has a "word" in quotes
you code:
"This string has a ""word"" in quotes"

It looks a bit odd when the string ends with this word, since you get 3
quotes together:
"This string has a ""word"""
but that's the kind of thing you generally get:
strSql = "DELETE FROM Table1 WHERE City = """ & _
Forms!Form1!Text0 & """;"

So, you will certainly mock up a query using any sample critiera values,
switch it to SQL View, and copy the statement to use in your code. But you
still need to concatenate your variables into the string.

These SQL statements can be quite long, so you probably want to break them
into multiple lines like the Query window does as well. Effectively this is:
strSql = "SELECT * FROM Table1 " & "WHERE ID = 99;"
Use the underscore as the line continuation charcacter:
strSql = "SELECT * FROM Table1 " & _
"WHERE ID = 99;"

There's more power beyond that as well, such as wrapping multiple statements
in a transaction so you roll the whole thing back unless it all completes
successfully. There's more info on that here:
http://allenbrowne.com/ser-37.html

But I fear we have already given you indigestion.
 
G

Guest

Dear FBxiii - It's good to know that I am on the right lines!

The code you provided is just the kind of start I needed - many thanks indeed!

Jim Jones
 
G

Guest

Dear Allen

Many thanks for providing such a detailed answer, and thanks for confirming
that the approach is worth persuing - it's obviously something which is worth
spending time on.

So, here goes ........

Thanks again

Jim Jones


Allen Browne said:
Jim, this is a big question. Hopefully you are willing to spend some time
learning this, because it *really* makes a monster difference to what you
can do with a database.

At the most basic level, the VBA is:
DoCmd.OpenQuery "Query1"
If Query1 is a SELECT query, this shows the query to the user. If it is an
Action query (Delete, Update, or Make Table), it executes the query.

For an Action query, it is probably better to use:
DoCmd.RunSQL "Query1"

These queries ask for user confirmation before the action. If you wish to
avoid that:
DoCmd.SetWarnings False
before the query, and:
DoCmd.SetWarnings True
afterwards.

To run 2 queries, without confirmation, the code would be:
DoCmd.SetWarnings False
DoCmd.RunSQL "Query1"
DoCmd.RunSQL "Query2"
DoCmd.SetWarnings True

These approaches are essentially the same as the macro. You are using VBA,
but you have not gained any benefit. A major problem with turning off
SetWarnings is that you get no message if the action query failed. For
example, if you were deleting records from a table so you could use it
again, you have no idea whether all records were actually deleted, or if
someone was using them and some were not deleted at all. And you have no
idea how many records were deleted.

A better approach in VBA is to Execute the query:
dbEngine(0)(0).Execute "Query1", dbFailOnError
With this approach, you do not need to turn SetWarnings off. But if the
query does not complete successfully, it triggers a trappable error. Your
VBA code can now handle the error and exit gracefully instead of ignorantly
continuing with the assumption that the data is ready to use. If the idea of
error handling is new, see:
http://allenbrowne.com/ser-23a.html

After an Execute, you can see how many records were deleted/appended/updated
via the RecordsAffected property:
dbEngine(0)(0).Execute "Query1", dbFailOnError
MsgBox dbEngine(0)(0).RecordsAffected & " record(s)."

But the Execute also has a limitation that RunSQL does not. If your query
has a parameter or refers to a text box on a form like this:
[Forms].[Form1]![Text0]
the Expression Service (ES) in Access will interpret the reference and the
query will run. The Execute cannot do that, so you need to build up the SQL
statement in your code, concatenating the value from the form into the SQL
string. Example:
Dim strSql As String
strSql = "DELETE FROM Table1 WHERE ClientID = " & _
Forms!Form1!Text0 & ";"
Debug.Print strSql
dbEngine(0)(0).Execute strSql, dbFailOnError

The Debug.Print line above is optional. It dumps the SQL string to the
Immediate Window. After running the code, you can open the Immediate Window
(Ctrl+G) to see the statement that executed. If there is a problem with the
SQL statement, the execute will fail, but you will be able to see what it
tried to execute, which empowers you to get it right.

When you concatenate values into a SQL string like that, you need delimiters
around the values. For dates, the delimiter is #, e.g.:
strSql = "DELETE FROM Table1 WHERE EntryDate = #" & _
Forms!Form1!Text0 & "#;"
For Text type fields, the delimiter is the double-quote. Trouble with that
is that VBA is already using quotes to delimit the string. The convention is
to double-them up when they are embedded in a string. So, if you want:
This string has a "word" in quotes
you code:
"This string has a ""word"" in quotes"

It looks a bit odd when the string ends with this word, since you get 3
quotes together:
"This string has a ""word"""
but that's the kind of thing you generally get:
strSql = "DELETE FROM Table1 WHERE City = """ & _
Forms!Form1!Text0 & """;"

So, you will certainly mock up a query using any sample critiera values,
switch it to SQL View, and copy the statement to use in your code. But you
still need to concatenate your variables into the string.

These SQL statements can be quite long, so you probably want to break them
into multiple lines like the Query window does as well. Effectively this is:
strSql = "SELECT * FROM Table1 " & "WHERE ID = 99;"
Use the underscore as the line continuation charcacter:
strSql = "SELECT * FROM Table1 " & _
"WHERE ID = 99;"

There's more power beyond that as well, such as wrapping multiple statements
in a transaction so you roll the whole thing back unless it all completes
successfully. There's more info on that here:
http://allenbrowne.com/ser-37.html

But I fear we have already given you indigestion.

--
Allen Browne - Microsoft MVP. Perth, Western Australia.

Reply to group, rather than allenbrowne at mvps dot org.

Jim Jones said:
I am curently using a number of macros each of which runs a large number of
queries. I am told that this is not good practice, and that I should
write
VBA code which executes the SQL code for each of the queries in turn. So,
the VBA would do the same job as the macro, but in a single piece of code.
I
see myself designing the query in the Query Window, then pasting the
corresponding SQL code at the appropriate place in the VBA.

Can anyone suggest how a VBA novice like me could start experimenting with
SQL in VBA code. Perhaps, someone could show me how to write some VBA
code
which does the same job as a very simple macro (say, one which calls two
queries).

I hope this makes sense

Jim Jones
Botswana
 
R

RD

On Mon, 22 May 2006 06:34:01 -0700, Jim Jones <Jim
I am curently using a number of macros each of which runs a large number of
queries. I am told that this is not good practice, and that I should write
VBA code which executes the SQL code for each of the queries in turn. So,
the VBA would do the same job as the macro, but in a single piece of code. I
see myself designing the query in the Query Window, then pasting the
corresponding SQL code at the appropriate place in the VBA.

Can anyone suggest how a VBA novice like me could start experimenting with
SQL in VBA code. Perhaps, someone could show me how to write some VBA code
which does the same job as a very simple macro (say, one which calls two
queries).

I hope this makes sense

Jim Jones
Botswana

Take a look at this:
http://www.mvps.org/access/queries/qry0014.htm

HTH,
RD
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top