473,399 Members | 3,401 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

Access asking for a query parameter unnecessarily? (Access VBA and SQL)

patjones
931 Expert 512MB
Hi -

I have a bound form with a bunch of text boxes connected to various fields. When someone types a search value into txtSearch and either tabs out or hits Enter, the following code runs (variable declarations, error handling and clean up omitted):
Expand|Select|Wrap|Line Numbers
  1. strGetPersonSQL = "PARAMETERS [LastName] CHAR; " & _
  2.                   "SELECT tblBasicInfo.*," & _
  3.                          "tblReferral.*," & _
  4.                          "tblCountryNames.fldCountry " & _
  5.                   "FROM   tblCountryNames INNER JOIN " & _
  6.                          "(tblBasicInfo LEFT JOIN " & _
  7.                          "tblReferral " & _
  8.                     "ON   tblBasicInfo.fldCaseID=tblReferral.fldCaseID) " & _
  9.                     "ON   tblBasicInfo.fldCountryID=tblCountryNames.fldCountryID " & _
  10.                   "WHERE  tblBasicInfo.fldNameLast=[LastName]"
  11.  
  12. Set qdf = CurrentDb.CreateQueryDef("qryGetPersonFromSearch", strGetPersonSQL)
  13. qdf("LastName") = Me.txtSearch.Value
  14.  
  15. Set rst = qdf.OpenRecordset(dbOpenSnapshot)
  16.  
  17. If rst.EOF Then
  18.     MsgBox "Nothing found. Try again...", vbExclamation + vbOKOnly, "Last Name Lookup"
  19.     rst.Close
  20.     Set rst=Nothing
  21.     Exit Sub
  22. Else
  23.     Me.RecordSource = "qryGetPersonFromSearch"
  24. End If
Things are fine up to where I assign the form's recordsource, at which point Access raises one of those annoying boxes asking for the value of LastName...but I already passed it in via the PARAMETER clause. What is going on here?

As a side note, I recognized that I could assign a SQL string to the recordsource directly, but then I don't know how I would use a parameter. I'm trying to avoid using the text box name directly in the WHERE clause. Thanks.

Pat
Nov 17 '09 #1

✓ answered by ADezii

@zepphead80
I've made some substantial Revisions to your Code, while at the same time making the Revised DB available as an Attachment to this Post. I intentionally left Comments outs, so should you have any questions, feel free to ask. A couple of the Major Revisions were:
  1. Removed the Code from the context of the Sub-Routine and placed in directly into the Click() Event of cmdLookup.
  2. Removed the Call to the Sub-Routine from the AfterUpdate() Event of txtSearch where I thought it was inappropriate.
  3. Rather than dealing with the more complex PARAMETERS Collection, I incorporated the Criteria into the WHERE Clause of the SQL Statement. If you remember correctly, this was NeoPa's suggestion.
  4. I'll post the Code for reference purposes, but download the Revised Attachment to really see what is going on:
    Expand|Select|Wrap|Line Numbers
    1. Private Sub cmdLookup_Click()
    2. On Error Resume Next
    3. Dim strGetPersonSQL As String
    4. Dim qdf As DAO.QueryDef
    5. Dim rst As DAO.Recordset
    6.  
    7. strGetPersonSQL = "SELECT tblBasicInfo.*, tblReferral.*, tblCountryNames.fldCountry " & _
    8.                   "FROM tblCountryNames INNER JOIN (tblBasicInfo LEFT JOIN tblReferral ON tblBasicInfo.fldCaseID = " & _
    9.                   "tblReferral.fldCaseID) ON tblBasicInfo.fldCountryID = tblCountryNames.fldCountryID WHERE " & _
    10.                   "tblBasicInfo.fldNameLast = '" & Forms!frmMain![txtSearch] & "';"
    11.  
    12. If IsNull(Me![txtSearch]) Then
    13.   MsgBox "No Last Name to search on!", vbExclamation, "Criteria Missing"
    14.     Exit Sub
    15. End If
    16.  
    17. CurrentDb.QueryDefs.Delete ("qryGetPersonFromSearch")
    18.  
    19. On Error GoTo Err_cmdLookup_Click
    20.  
    21. Set qdf = CurrentDb.CreateQueryDef("qryGetPersonFromSearch", strGetPersonSQL)
    22.  
    23. Set rst = qdf.OpenRecordset(dbOpenSnapshot)
    24.  
    25. If rst.EOF Then
    26.   MsgBox "No Record(s) found for Last Name of [" & Me![txtSearch] & "]." & _
    27.           vbCrLf & vbCrLf & "Try again...", vbExclamation + vbOKOnly, "Last Name Lookup"
    28. Else
    29.   Me.RecordSource = "qryGetPersonFromSearch"
    30. End If
    31.  
    32. Exit_cmdLookup_Click:
    33.   If Not qdf Is Nothing Then
    34.     qdf.Close
    35.     Set qdf = Nothing
    36.   End If
    37.   If Not rst Is Nothing Then
    38.     rst.Close
    39.     Set rst = Nothing
    40.   End If
    41.     Exit Sub
    42.  
    43. Err_cmdLookup_Click:
    44.   MsgBox Err.Description, vbExclamation, "Error in cmdLookup_Click()"
    45.   Resume Exit_cmdLookup_Click
    46. End Sub

22 6718
ChipR
1,287 Expert 1GB
Sorry, I'm not too familiar with querydefs and parameters. The table at http://support.microsoft.com/kb/142938 has Text, but doesn't list CHAR as a variable type, nor does the example use [ ]. Maybe that could be part of the problem?
Nov 17 '09 #2
NeoPa
32,556 Expert Mod 16PB
Having reformatted your code to be legible, I wonder what you mean by saying you have already specified the value of [lastName] in your PARAMETER(S) statement. Certainly the type has been specified, but no value is passed.

What are you actually trying to do?

Do you have the value of [LastName] (that you want to use) available to the code at the time the SQL is created?
Nov 17 '09 #3
patjones
931 Expert 512MB
Hi Chip -

Thanks for responding. I did change the parameter type to TEXT, but it doesn't seem to matter. I figured CHAR was fine because it does actually open the recordset okay with it written out like that.

The brackets don't matter either, apparently. But thanks for the suggestions!

Pat
Nov 17 '09 #4
patjones
931 Expert 512MB
Hi NeoPa -

Doesn't the line
Expand|Select|Wrap|Line Numbers
  1. qdf("LastName") = Me.txtSearch.Value
assign whatever I type into the text box to the parameter? At least this is how I've done it in the past. And, when I test this out with a last name that does not exist in the database the rst.EOF test catches it. So I'm pretty sure the query is getting the value from txtSearch. Thanks for responding.

Pat
Nov 17 '09 #5
NeoPa
32,556 Expert Mod 16PB
Very possibly Pat (I overlooked that).

I would consider shoving that value into the SQL directly though :
Expand|Select|Wrap|Line Numbers
  1.      "WHERE  tblBasicInfo.fldNameLast='" & Me.txtSearch & "'"
I cannot say why your code is not working, but I expect this version would avoid the problem.
Nov 17 '09 #6
patjones
931 Expert 512MB
It definitely will avoid the problem, and I must say simplify the code - for then I can eliminate all the parameter stuff. But my concern in doing it the way you're suggesting is SQL injection. So I wanted to use the parameter method because of that.

Is there some way to avoid SQL injection even when inserting the text box value directly into the string like that?
Nov 17 '09 #7
ADezii
8,834 Expert 8TB
May be a simple oversight/syntax error on your part, replace Line # 12 with:
Expand|Select|Wrap|Line Numbers
  1. qdf.Parameters("LastName").Value = Me.txtSearch.Value 
Nov 17 '09 #8
patjones
931 Expert 512MB
Hi ADezii -

I have seen that notation before and tried it here, but to no avail. If there is a way that I can prevent SQL injection while embedding Me.txtSearch.Value into the WHERE clause directly, perhaps that is the route I should take. But I will still be bothered as to why the parameter formalism isn't working. Thanks for responding.

Pat
Nov 17 '09 #9
ADezii
8,834 Expert 8TB
@zepphead80
  1. I have duplicated your functionality and have had no problem with it. If you would like to Upload the Database with some sample data, I pretty sure that I can get the situation resolved one way or another.

  2. If there is a way that I can prevent SQL injection while embedding Me.txtSearch.Value into the WHERE clause directly
    I think that NeoPa has already suggested this (Post #6), and I feel as though this is an excellent idea.
  3. It's you call.
Nov 17 '09 #10
patjones
931 Expert 512MB
Hi ADezii -

I have attached the file. This is a small, sort of 'test' database for a project. Provided that it gets approval at this point, it will grow considerably - both in number of tables and records. Right now there are just two bogus records in it.

Thanks for your help.

Pat
Attached Files
File Type: zip dbTrackingTest.zip (29.7 KB, 127 views)
Nov 17 '09 #11
ADezii
8,834 Expert 8TB
@zepphead80
I'll try to look at it this evening. OOPs sorry, I don't have Access 2007. Can you convert it to an earlier Version, say 2002?
Nov 17 '09 #12
patjones
931 Expert 512MB
Here is 2002-2003. Thanks.
Attached Files
File Type: zip dbTrackingTest.zip (44.1 KB, 126 views)
Nov 17 '09 #13
NeoPa
32,556 Expert Mod 16PB
@zepphead80
Good thinking.

You can control this on your form with various techniques to ensure there is no quote character in the value. Further info can be found at SQL Injection Attack
Nov 17 '09 #14
ADezii
8,834 Expert 8TB
@zepphead80
I've made some substantial Revisions to your Code, while at the same time making the Revised DB available as an Attachment to this Post. I intentionally left Comments outs, so should you have any questions, feel free to ask. A couple of the Major Revisions were:
  1. Removed the Code from the context of the Sub-Routine and placed in directly into the Click() Event of cmdLookup.
  2. Removed the Call to the Sub-Routine from the AfterUpdate() Event of txtSearch where I thought it was inappropriate.
  3. Rather than dealing with the more complex PARAMETERS Collection, I incorporated the Criteria into the WHERE Clause of the SQL Statement. If you remember correctly, this was NeoPa's suggestion.
  4. I'll post the Code for reference purposes, but download the Revised Attachment to really see what is going on:
    Expand|Select|Wrap|Line Numbers
    1. Private Sub cmdLookup_Click()
    2. On Error Resume Next
    3. Dim strGetPersonSQL As String
    4. Dim qdf As DAO.QueryDef
    5. Dim rst As DAO.Recordset
    6.  
    7. strGetPersonSQL = "SELECT tblBasicInfo.*, tblReferral.*, tblCountryNames.fldCountry " & _
    8.                   "FROM tblCountryNames INNER JOIN (tblBasicInfo LEFT JOIN tblReferral ON tblBasicInfo.fldCaseID = " & _
    9.                   "tblReferral.fldCaseID) ON tblBasicInfo.fldCountryID = tblCountryNames.fldCountryID WHERE " & _
    10.                   "tblBasicInfo.fldNameLast = '" & Forms!frmMain![txtSearch] & "';"
    11.  
    12. If IsNull(Me![txtSearch]) Then
    13.   MsgBox "No Last Name to search on!", vbExclamation, "Criteria Missing"
    14.     Exit Sub
    15. End If
    16.  
    17. CurrentDb.QueryDefs.Delete ("qryGetPersonFromSearch")
    18.  
    19. On Error GoTo Err_cmdLookup_Click
    20.  
    21. Set qdf = CurrentDb.CreateQueryDef("qryGetPersonFromSearch", strGetPersonSQL)
    22.  
    23. Set rst = qdf.OpenRecordset(dbOpenSnapshot)
    24.  
    25. If rst.EOF Then
    26.   MsgBox "No Record(s) found for Last Name of [" & Me![txtSearch] & "]." & _
    27.           vbCrLf & vbCrLf & "Try again...", vbExclamation + vbOKOnly, "Last Name Lookup"
    28. Else
    29.   Me.RecordSource = "qryGetPersonFromSearch"
    30. End If
    31.  
    32. Exit_cmdLookup_Click:
    33.   If Not qdf Is Nothing Then
    34.     qdf.Close
    35.     Set qdf = Nothing
    36.   End If
    37.   If Not rst Is Nothing Then
    38.     rst.Close
    39.     Set rst = Nothing
    40.   End If
    41.     Exit Sub
    42.  
    43. Err_cmdLookup_Click:
    44.   MsgBox Err.Description, vbExclamation, "Error in cmdLookup_Click()"
    45.   Resume Exit_cmdLookup_Click
    46. End Sub
Nov 17 '09 #15
NeoPa
32,556 Expert Mod 16PB
To make this Injection-proof, simply add the following code after line #5 :
Expand|Select|Wrap|Line Numbers
  1. Dim strCheck As String
  2.  
  3. If Replace(Replace(Forms!frmMain![txtSearch], _
  4.                    """", _
  5.                    ""), _
  6.            "'", _
  7.            "") <> Forms!frmMain![txtSearch] Then
  8.     'Handle SQL Injection here
  9. End If
PS. Alternatively, you may decide simply to strip out any quote characters and pass that string along, instead of advertising that your code is on to them ;)
Nov 18 '09 #16
patjones
931 Expert 512MB
Thanks to the both of you for addressing my issue. I will absorb this overnight, and let you know how it works out!

Pat
Nov 18 '09 #17
ChipR
1,287 Expert 1GB
An alternative is the Instr function.
Expand|Select|Wrap|Line Numbers
  1. If Instr(Forms!frmMain![txtSearch], """") > 0 Or _
  2.    Instr(Forms!frmMain![txtSearch], "'") > 0 Then
Nov 18 '09 #18
patjones
931 Expert 512MB
Thank you all. Things work quite well.

ADezii -

I put all the code in the Click event for the command button as you suggested, and removed the parameter formalism. I also really like the tests for existence of qdf and rst at the end of the sub and have added those as well.

NeoPa -

I like the Replace method, but am simply assigning those nested Replace statements to a string variable and then putting that into the SQL string rather than doing the test.

I appreciate the time and effort. Thanks so much.
Nov 18 '09 #19
NeoPa
32,556 Expert Mod 16PB
It's always a pleasure working with someone who's prepared to get involved Pat. Responding so fully, as you do, keeps everyone in the picture and everyone feeling valued.

BTW I hope you agree with me that ADezii's post #15 is the most apposite for the question (as I've selected it).
Nov 18 '09 #20
patjones
931 Expert 512MB
ADezii's code is basically what I implemented and consider the best solution.

I'm still not sure why the parameter didn't work though. I usually use unbound forms, pulling the data from the tables with ADO and then assigning text box values item by item referencing the recordset. I've found that ADO makes use of parameters straightfoward.

Thanks!
Nov 18 '09 #21
ChipR
1,287 Expert 1GB
I recommend you try using bound forms the next chance you get. Being a programmer before a database administrator, I started with unbound forms and lots of code, but have learned enough to use bound forms. Funny how the "easy" way was not as easy as just writing code. Anyway, the result is much cleaner and faster, and I have redone most of my forms.
Nov 18 '09 #22
patjones
931 Expert 512MB
Indeed, I am using a bound form for this project...really my first time using one. It does seem to cut down on the code quite a bit. It also makes edits really easy.

Thanks for your insight Chip.
Nov 18 '09 #23

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: Jack | last post by:
Hi, I am working on a asp page where I am opening a recordset object using an Access stored query named "GMISExpenseCombo". I have to use this resultset with various fields in the page. Howeve,r...
2
by: The Plankmeister | last post by:
Hi... I have a query which I'm accessing through PHP as a stored procedure. However, I need to be able not to pass a couple of parameters in certain situations. When I do this, I get an error: ...
3
by: cassandra.flowers | last post by:
Hi, I was wondering if it is possible (Using access) to have a query parameter as a drop down box rather than a text box? e.g. typing as criteria for a query produces a box with a text box...
1
by: ED | last post by:
I currently have an ODBC query that hits an Oracle database. I want to bring back records for a given month based on a job completion date in the Oracle database. I would like to have the user...
0
by: totierne | last post by:
comp.databases.ms-access, I want to know how to use Oracle views with session variables in Access. The parameterised views in access, are migrated to views with per session variables. The...
3
by: eagleofjade | last post by:
I am trying to help a friend who is learning VB.net in school. I have done VB programming for a number of years using VB 6. He needs to open a query in an Access database that has parameters so he...
2
by: SF | last post by:
Hi, I am new to ASP.NET. I started my first testing ASP.NET by having a ASP page consist of a drop-down control and 1 datagrid bound to Access database. The dropdown control works very well...
2
by: gumby | last post by:
I would like to call this stored procedure, but I am unable to pass parameters to the @Start and @End. Is thier a way to pass parameters to a pass through query from MS Access? SELECT ...
13
by: EVH316 | last post by:
Hi eveyone, Its my first time to use MS Access 2003 and I need to modify the existing program I have a MS Access query and I want to fetch the record 1 by 1 and write the result in a text file....
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.