Searching a database - code review needed

In my search window I have 5 text fields:

NumberTextField
TypeTextField
CombinedDateTextField
InvolvedTextField
DealingTextField

In my database I have the following accompanying columns:
Number
Type
Date
Involved
Dealing

I am trying to allow the user to enter as little or as much search criteria as desired, and then have the listbox in my main window update to show ONLY the results which match exactly to the search criteria.

Example:
If the user enters only 1 search criteria such as “Fire” in the TypeTextField, it will display all rows with the word “fire” in the type column of the database.
If however, the user enters “Fire” in the TypeTextField, AND “David” in the InvolvedTextField, it should display all database rows where Type = Fire AND Involved = David

I have the code below, but my concatenation code segment gets all jumbled up.
Could anyone please help?

[code]Dim Search As String
Dim TextFieldControlArray() as TextField

// CREATE AND POPULATE THE TextFieldControlArray TO MATCH THE WINDOW’S TEXTFIELDS
TextFieldControlArray.Append NumberTextField
TextFieldControlArray.Append TypeTextField
TextFieldControlArray.Append CombinedDateTextField
TextFieldControlArray.Append InvolvedTextField
TextFieldControlArray.Append DealingTextField

// CREATE AND POPULATE THE FieldNamesArray TO MATCH THE DATABASE COLUMN NAMES
Dim FieldNamesArray(5) as String

FieldNamesArray(0) = “Number”
FieldNamesArray(1) = “Type”
FieldNamesArray(2) = “Date”
FieldNamesArray(3) = “Involved”
FieldNamesArray(4) = “Dealing”

// SET SearchCriteria TO EMPTY
Dim SearchCriteria as String = “”

// LOOP THROUGH THE TextfieldControlArray LOOKING FOR ENTERED SearchCriteria
for i as Integer = 0 to UBound(TextfieldControlArray)
if TextfieldControlArray(i).text <> “” then

// ---------------------------------------- THIS BLOCK OF CODE SEEMS TO BE WRONG
// CONCATENATE MULTIPLE SearchCriteria ENTERED BY THE USER (IF NECESSARY)
SearchCriteria = TextfieldControlArray(i).text
SearchCriteria = “LIKE '%”+SearchCriteria+"%’ AND "
for p as integer = 0 to UBound(FieldNamesArray)
Search = Search+FieldNamesArray§+" "+SearchCriteria
next
end if
next

// REMOVE THE LAST “AND” FROM THE COMBINED SearchCriteria
If right(Search,4) = "AND " then
Search = left(Search,len(Search)-5)
end if

// RETRIEVE RECORDSET RESULTS FROM THE DATABASE
Dim ps As SQLitePreparedStatement = IncidentsDB.Prepare("SELECT * FROM Incidents WHERE " +Search + “ORDER BY IRef ASC”)
IncidentsRS = ps.SQLSelect

// NO MATCHING RECORDS FOUND, SO DISPLAY AN ERROR MSGBOX
if IncidentsRS = Nil or IncidentsRS.RecordCount <1 then
MsgBox(“No matching records found!”)
End if[/code]

Alternatively, is it possible to achieve this by using just an SQLSelect statement somehow???
The problem is that I do not know how many search criteria will be entered by the user?

Thank you all in advance.

The SQLite documentation says as long as the WHERE clause evaluates to a boolean value it will work.
I’ve just tested it on my own database and it works just fine using an AND clause in the query.

Check for

  1. Any database errors that may be returned
  2. The SQL statement formation, see if it’s being made the way you think it is.

I keep getting the No matching records found! Messagebox - probably due to my SQLSelect statement not being constructed properly?

what is your “search” variable prior to the Prepare ?

Don’t quite understand, Peter?

Really you should be doing
Dim s As String = "SELECT * FROM Incidents WHERE " +Search + “ORDER BY IRef ASC”

before the Prepare so you can see what it looks like. That said, I only glanced at it but it looks like the second one may not have a LIKE.

WHERE Columnx LIKE ‘%text%’ "AND Columny LIKE ‘%text2%’

Ok,
please bear in mind that I am still learning Xojo :slight_smile:

Prior to the prepare. Search looks like the screenshot below:

As you can hopefully see - it is messed up?
I searched for Type = Fire (full evacuation) and Involved = Me, but it seems to be making a statement which is searching ALL fields for Fire (full evacuation) ???

You are looping through your text fields then looping again through your field names.

One loop, one index.

I don’t get it to be honest. First is this what you are attempting?

NumberTextField searches only in Number
TypeTextField searches only in Type
CombinedDateTextField searches only in Date
InvolvedTextField searches only in Involved
DealingTextField searches only in Dealing

?

You already pinpointed the problem code.

// CONCATENATE MULTIPLE SearchCriteria ENTERED BY THE USER (IF NECESSARY) SearchCriteria = TextfieldControlArray(i).text SearchCriteria = "LIKE '%"+SearchCriteria+"%' AND " for p as integer = 0 to UBound(FieldNamesArray) Search = Search+FieldNamesArray(p)+" "+SearchCriteria next end if next

This assembles something that checks every field for what you entered.
So you might enter SMITH and the search will look for SMITH in every field.
I would have expected that to be OR not AND

…generating a search that effectively says give me rows where
Surname like ‘%Smith%’ OR
Forename like '%Smith" OR
JobType like ‘%Smith%’

If it uses AND, then it will only return rows that have Smith in EVERY field. Cant be what you intended?

Something like this might be easier

[code]// LOOP THROUGH THE TextfieldControlArray LOOKING FOR ENTERED SearchCriteria

Dim whereClause() As String

for i as Integer = 0 to UBound(TextfieldControlArray)
if TextfieldControlArray(i).text <> “” then
whereClause.append(fieldNamesArray(i).text + " “LIKE '%”+ tetfieldControlArray(i).Text +"%’ "
end if
Next

// RETRIEVE RECORDSET RESULTS FROM THE DATABASE
Dim rs As RecordSet = IncidentsDB.SQLSelect("SELECT * FROM Incidents WHERE " + Join(whereClause, " And ") + “ORDER BY IRef ASC”)[/code] <-- Note space on either side of “And”

If you are going to use prepared statements you have to do your bindings. In this case where it is user entered data prepared statements are the way to go. My example above is a regular Select.

Yes Jym, that is exactly what I am trying to do. The I need to display only those results in the listbox.

Ok,
I am now getting confused with all the answers :slight_smile:

NumberTextField searches only in Number
TypeTextField searches only in Type
CombinedDateTextField searches only in Date
InvolvedTextField searches only in Involved
DealingTextField searches only in Dealing

If the user enters FIRE in the TYPE field, RICHARD in the INVOLVED field, and DAVID in the DEALING field, - then I need the listbox to only show rows where ALL 3 of those are true for the same row.

Hope that made more sense :slight_smile:

So why not just do it with 5 IF statements?

Dim s As String = “Select …”
if TRIM(NumberTextField.Text) <> “” then s = s + " Number LIKE ‘%" + numbertextfield.text + "%’ AND "
if TRIM( same as above for all of the text fields …

Remove the final AND from s
then add the rest of the statement. done

Do you mean like this?
Been trying to solve this for more than a day and I have now become brain drained :frowning:

[code]Dim Search As String = “SELECT * FROM Incidents WHERE”

if TRIM(NumberTextField.Text) <> “” then Search = Search + " Number LIKE ‘%" + NumberTextField.text + "%’ AND "

if TRIM(CombinedDateTextField.Text) <> “” then Search = Search + " Date LIKE ‘%" + DateTextField.text + "%’ AND "

if TRIM(TypeTextField.Text) <> “” then Search = Search + " Type LIKE ‘%" + TypeTextField.text + "%’ AND "

if TRIM(InvolvedTextField.Text) <> “” then Search = Search + " Involved LIKE ‘%" + InvolvedTextField.text + "%’ AND "

if TRIM(DealingTextField.Text) <> “” then Search = Search + " Dealing LIKE ‘%" + DealingTextField.text + "%’ AND "

// REMOVE THE LAST “AND” FROM THE COMBINED SearchCriteria
If right(Search,4) = "AND " then
Search = left(Search,len(Search)-5)
end if

end if
end if
end if
end if
end if[/code]

There are no end if’s when it’s on one line

If i = b then i = 20

is the same as

If i = be then
i = 20
end if

Everything I look at now seems to look like gibberish :slight_smile:

[code]// INITIALIZE THE SELECT STATEMENT
Dim Search As String = “SELECT * FROM Incidents WHERE”

if TRIM(NumberTextField.Text) <> “” then Search = Search + " Number LIKE ‘%" + NumberTextField.text + "%’ AND "

if TRIM(CombinedDateTextField.Text) <> “” then Search = Search + " Date LIKE ‘%" + DateTextField.text + "%’ AND "

if TRIM(TypeTextField.Text) <> “” then Search = Search + " Type LIKE ‘%" + TypeTextField.text + "%’ AND "

if TRIM(InvolvedTextField.Text) <> “” then Search = Search + " Involved LIKE ‘%" + InvolvedTextField.text + "%’ AND "

if TRIM(DealingTextField.Text) <> “” then Search = Search + " Dealing LIKE ‘%" + DealingTextField.text + "%’ AND "

// REMOVE THE LAST “AND” FROM THE COMBINED SearchCriteria
If right(Search,4) = "AND " then
Search = left(Search,len(Search)-5)
end if

// RETRIEVE THE RECORDSET RESULTS FROM THE DATABASE
IncidentsRS = IncidentsDB.SQLSelect(Search)

// NO MATCHING RECORDS FOUND, SO DISPLAY AN ERROR MSGBOX
if IncidentsRS = Nil or IncidentsRS.RecordCount <1 then
MsgBox(“No matching records found!”)
End if[/code]

Yes, but you don’t need the final if statement because as you see it will = AND

Then add your ORDER BY. You want to leave a space so remove only the last 4 chrs.

Run it with different combos and post Search string

Ok,
I have added ORDER BY to the Search string, but I am not sure what you mean by removing the last if statement?
Do you mean remove the No Matching Records Found message box if statement?

[code]// INITIALIZE THE SELECT STATEMENT
Dim Search As String = “SELECT * FROM Incidents WHERE”

if TRIM(NumberTextField.Text) <> “” then Search = Search + " Number LIKE ‘%" + NumberTextField.text + "%’ AND "

if TRIM(CombinedDateTextField.Text) <> “” then Search = Search + " Date LIKE ‘%" + DateTextField.text + "%’ AND "

if TRIM(TypeTextField.Text) <> “” then Search = Search + " Type LIKE ‘%" + TypeTextField.text + "%’ AND "

if TRIM(InvolvedTextField.Text) <> “” then Search = Search + " Involved LIKE ‘%" + InvolvedTextField.text + "%’ AND "

if TRIM(DealingTextField.Text) <> “” then Search = Search + " Dealing LIKE ‘%" + DealingTextField.text + "%’ AND "

// REMOVE THE LAST “AND” FROM THE COMBINED SearchCriteria
If right(Search,4) = "AND " then
Search = left(Search,len(Search)-5)
end if

// APPEND ORDER BY TO THE SEARCH STRING
Search = Search + “ORDER BY Number”

// RETRIEVE THE RECORDSET RESULTS FROM THE DATABASE
IncidentsRS = IncidentsDB.SQLSelect(Search)

// NO MATCHING RECORDS FOUND, SO DISPLAY AN ERROR MSGBOX
if IncidentsRS = Nil or IncidentsRS.RecordCount <1 then
MsgBox(“No matching records found!”)
End if[/code]