Writing Dynamic SQL Statement - sql

I am very new to Microsoft Access.
I would like to select a column from a table based on the value of a parameter (i.e. my table has columns x, y and z and I have a chosencol parameter which is set by the user using a dropdown.
I can select one / all of the columns using a select command, however, I would like to do this using my parameter chosencol instead.
Having read around, I have found a number of references to using the SET and EXEC commands, however, entering them into the SQL command in Access just yields errors.
Please could someone advise me as to how I go about implementing a dynamic-sql query in Access (in fine detail as I think I am writing the commands in the wrong place at the moment...)

First I created an example table in Access.
Next, I created an example form to query your value. The dropdown is called 'chosencol'. Select a value from the Column Select dropdown and press the "Lookup Value" button.
Here is the code under the "Lookup Value" button's On Click event. A SQL statement is dynamically built with the column you chose. The column is renamed to [FieldName] to that it can by referenced.
Private Sub btnLookup_Click()
Dim rsLookup As New ADODB.Recordset
Dim strSQL As String
strSQL = "select " & chosencol.Value & " as [FieldName] from Table1 where ID=1"
rsLookup.Open strSQL, CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
If rsLookup.EOF = False Then
txtValue.SetFocus
txtValue.Text = rsLookup![FieldName]
End If
rsLookup.Close
End Sub
When the button is pushed, the value from whatever column you selected will be returned. For this simple example, I'm always returning row 1's data.

I'm pretty sure you can't do that in straight SQL. However, you can create the SQL string in VBA code and save it as a query.
CurrentDB.CreateQueryDef("MyQueryName", "SELECT " & chosencol & " FROM MyTable")
Now, MyQueryName will be a permanent query in your database and can be referenced wherever you want.
If chosencol is a multi-select dropdown, you'll have to read the selected values into an array and then write the array to one concatenated string and use that instead.

Related

Return Query Value Using VBA function in Access

I'm currently working on a project and I've been having trouble trying to get a function that is able to return the value of a query, which I do need in order to display it on a textbox.
The current code is like this:
Public Function rubrieknaamSQL() As String
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT T_Train.trainPlate, T_Category.categoryName FROM T_Category INNER JOIN T_Train ON T_Category.id = T_Train.category_id WHERE (((T_Train.trainPlate)=[Forms]![F_Comboio]![Combo_Search_Comboio]));"
Set rst = CurrentDb.OpenRecordset(strSQL)
rubrieknaamSQL = rst!categoryName
rst.Close
End Function
I should say that the code is copied from other publisher and I do not own its rights. However, it still won't work when I try to run it and the error displayed goes like this:
Run-Time Error 3061 : Too few parameters. Expected 1
and it happens in Set rst command.
For a SELECT query to set a recordset object, concatenate variable:
" ... WHERE T_Train.trainPlate=" & [Forms]![F_Comboio]![Combo_Search_Comboio]
If trainPlate is a text field, need apostrophe delimiters (date/time field needs # delimiter):
" ... WHERE T_Train.trainPlate='" & [Forms]![F_Comboio]![Combo_Search_Comboio] & "'"
For more info about parameters in Access SQL constructed in VBA, review How do I use parameters in VBA in the different contexts in Microsoft Access?
There are ways to pull this single value without VBA.
make combobox RowSource an SQL that joins tables and textbox simply references combobox column by its index - index is 0 based so if categoryName field is in third column, its index is 2: =[Combo_Search_Comboio].Column(2)
include T_Category in form RecordSource and bind textbox to categoryName - set as Locked Yes and TabStop No
build a query object that joins tables without filter criteria and use DLookup() expression in textbox
=DLookup("categoryName", "queryname", "trainPlate='" & [Combo_Search_Comboio] & "'")

Is it possible to make a dynamic sql statement based on combobox.value in access?

I made a form in access with 2 different comboboxes. The user of
This tool can choose in combobox1: the table (which has to be filtered) and the second combobox2 is the criteria to be filtered( for example Language= “EN”) and the output of this query has to be located in tablex.
The problen what I have is that i cant find a solution for passing the value of the combobox1 to the sql statement. The second one is just like: where [language] = forms!form!combo2.value, but the part where i cant find a solution for is: select * from (combobox1 value)? How can i pass the combobox value as table name to be filtered? Can anyone please help me?
You can't have the table name in the WHERE clause of your query (there might be a hacky way to do it, but it should be discouraged at any case).
If you want to select data from 1 of a number of tables, your best bet is to generate SQL dynamically using VBA. One way to do this (especially if you want/need your query to open in Datasheet View for the end user) is to have a "dummy" query whose SQL you can populate using the form selections.
For example, let's say we have 2 tables: tTable1 and tTable2. Both of these tables have a single column named Language. You want the user to select data from either the first or second table, with an optional filter.
Create a form with 2 combo boxes: One for the tables, and one with the criteria selections. It sounds like you've already done this step.
Have a button on this form that opens the query. The code for this button's press event should look something like this:
Private Sub cmdRunQuery_Click()
Dim sSQL As String
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
If Not IsNull(Me.cboTableName.Value) Then
sSQL = "SELECT * FROM " & Me.cboTableName.Value
If Not IsNull(Me.cboFilter.Value) Then
sSQL = sSQL & vbNewLine & _
"WHERE Language=""" & Me.cboFilter & """"
End If
Set db = CurrentDb
Set qdf = db.QueryDefs("qDummyQuery")
qdf.SQL = sSQL
DoCmd.OpenQuery qdf.Name
End If
End Sub
Note how the SQL is being generated. Of course, using this method, you need to protect yourself from SQL injection: You should only allow predefined values in the combo box. But this serves as a proof of concept.
If you don't need to show the query results, you don't need to use the dummy query: You could just open a recordset based on the SQL and process that.
If you run the code in the afterupdate event of the combobox you can set an SQL statement like this:
Private Sub combobox2_AfterUpdate()
someGlobalVar = "Select * FROM " & me.combobox1.value & " WHERE language = " & _
me.combobox2.value
End Sub
And then call the global with the SQL string wherever you need it.

Use an Access Forms Unbound text box as a Field filter in a table

Access 2013 - Reference an Unbound text box on a Form
I am currently trying to use an unbound text box [Text161] on a Form name [DCM_Gap_Servers] to sort information through a table. I want the query that I created to be able to take the users input from [DCM_Gap_Servers]![Text161] as the field that is being sorted from the table names 'Server'.
This is the SQL I am using right now in the query:
SELECT * FROM Servers WHERE "Forms![DCM_Gap_Servers]![Text161]" IS NULL
** I have already Tried:
"Forms![DCM_Gap_Servers]![Text161]" ; (Forms![DCM_Gap_Servers]![Text161]); Forms.[DCM_Gap_Servers]![Text161]
This will work at any time if I replace the Text Box reference with the actual Field name I am using, but since there are hundreds of combinations of fields, I need the reference to work.
I have looked all over, and I can't seem to find the correct answer. I am willing to do it in VBA if needed, whatever it takes to get the filtering done correctly.
Thank You.
It is:
SELECT * FROM Servers WHERE Forms.[DCM_Gap_Servers].[Text161] IS NULL
but that will just select all records whenever your textbox is Null.
So it rather is:
SELECT * FROM Servers WHERE SomeField = Forms.[DCM_Gap_Servers].[Text161]
To use the form value as a field name, you must use concatenated SQL:
strSQL = "SELECT * FROM Servers WHERE " & Forms![DCM_Gap_Servers]![Text161].Value & " IS NULL"
This you might pass to the SQL property of an existing query object:
MyQueryDef.SQL = strSQL
Or:
Constant SQL As String = "SELECT * FROM Servers WHERE {0} IS NULL"
FieldName = Forms![DCM_Gap_Servers]![Text161].Value
MyQueryDef.SQL = Replace(strSQL, "{0}", FieldName)
Of course, take care the the field name isn't a zero length string.

Run time error 3021- no current record

I want to link the result of a query to a Textbox but I get this error: here is my code:
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("SELECT XValue, YValue,Wert FROM tb_DCM_Daten WHERE (FzgID=" & Forms!frm_fahrzeug!ID & " AND Name='" & List2.Value & "')")
Text10.Text = rst!XValue //error in this line
It should be return c.a 20 record
Why do I get this error and how can I solve it?
One possible reason for the error is that Name is a reserved word in Access, so you should use
... & " AND [Name]='" & ...
You could also test for rst.EOF before trying to use rst!XValue. That is, to verify whether or not your query is returning at least one row you can add the code
If rst.EOF Then
MsgBox "The Recordset is empty."
End If
immediately after the .OpenRecordset call. If the Recordset is empty, then you'll need to verify your SQL statement as described by #GregHNZ in his comment above.
Usually, I would do this. Create a new query in Access , switch to SQL View , Paste my code there and go to Design >> Run.
SELECT XValue, YValue,Wert FROM [tb_DCM_Daten] WHERE [FzgID]=12 AND [Name]='ABC';
if your query syntax is correct you should see the result otherwise error mssg will tell where you are wrong. I used to debug a much more complicated query than yours and this is the way that I've done.
If there is still error, maybe you should try
Dim sql as String
sql = "SELECT...."
Set rst = CurrentDb.OpenRecordset(sql)
Another possible reason might be your table name. I just wonder what is your table name exactly ? if your table contains white space you should make it like this [DCM Daten].
One more thing I like to add that may cause this, is your returning a sets of resultset that has "Reserved word" fields, for example:
Your "Customers" table has field name like the following:
Custnum | Date | Custname
we know that Date field is a reserved word for most database
so when you get the records using
SELECT * FROM Customers
this will possible return "No Current Record", so instead selecting all fields for that table, just minimize your field selection like this:
SELECT custnum, custname FROM Customers
After trying the solutions above to no avail, I found another solution: Yes/No fields in Access tables cannot be Null (See allenbrowne.com/bug-14)
Although my situation was slightly different in that I only got the "No current record." error when running my query using GROUPBY, my query worked after temporary eliminating the Yes/No field.
However, my Yes/No field surprisingly did not contain any Nulls. But, troubleshooting led me to find an associated error that was indeed populating my query result with Null Yes/No values. Fixing that associated error eliminated the Null Yes/No values in my results, thus eliminating this error.
I got the same error in the following situation:
In my case the recordset returned one record including some fields with Null value.
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("SELECT * FROM tbl WHERE (criteria)", dbOpenDynaset)
Textbox1 = rst!field1 'error in this line - Non-Null value
Textbox2 = rst!field2 'Null value
Textbox3 = rst!field1 'Null value
Viewing Locals when rst is opened and before asignments, shows the recordset as I expect it to be. The error is thrown when trying to a asign a value from this recordset.
What fixed this, is ensuring that all fields contained non-Null values.
Just posting this for future seekers.

Using a VBA array in a SQL statement

I am trying to write some code that uses SQL to delete rows from several tables.
A user would type type numbers into a textbox that are separated by a comma which is used in the WHERE clause of a SQL DELETE statement.
I have managed to split the string into a variant array and now I want to insert it into my SQL statement.
How do I insert the variable into the SQL statement and have it run through every element of the array?
EDIT: A bit more digging has taught me about For Each Next statements. This is probably what im looking for.
I suggest you build your query in VBA, then your list of numbers can be an IN statement:
sSQL = "DELETE FROM table WHERE ID In (" & MyList & ")"
Where MyList = "1,2,3,4" or such like.
As you can see, you do not need an array and a textbox would be more suitable than a combobox. If you wish to allow your users to select by say, a name, then a listbox is useful. You can iterate through the selected items in the listbox and build a string from IDs to be used in the Delete statement. ( MS Access 2007 - Cycling through values in a list box to grab id's for a SQL statement )
You can then execute the sql against an instance of a database. For example:
Dim db As Database
Set db = CurrentDB
db.Execute sSQL, dbFailOnError
MsgBox "You deleted " & db.RecordsAffected & " records."
A generic approach
WHERE
','+Array+',' like '%,'+col+',%'
It will consider all the numbers available in your Array
You could make it simple and elaborate a string, something like
stringBuilder sb = StringBuilder("DELETE FROM YOURTABLE WHERE ");
foreach(string st in stringArray){
sb.append("YOURFIELD='" + st + "'");
//If it is not the last element, add an "OR"
if (st != stringArray[stringArray.length -1]) sb.append(" OR ");
}
//Now, you have a string like
//DELETE FROM YOURTABLE WHERE YOURFIELD='hello' OR YOURFIELD='YES'
//... do something with the command
This method will fail if you want to run SQL query on two (or multiple) columns using array values from two different arrays. .e.g
where col1=array1(i) and col2=array2(i)