views:

186

answers:

3

I need an extra set of eyes on this one. Any help will be greatly appreciated. This is a very simple search query, but for whatever reason I cannot find the bug. Well, I know where the bug is. I just can't get past it. Anyway.....

I am taking a search value from a POST variable, setting that variable and then setting a column variable as follows...

$term = "'%".$_POST['searchTerm']."%'";
$field = "columnName";

When I echo these they come up perfectly. So if I type "a" in the form I would be echoing '%a%' and columnName.

I then prepare the query and bind the parameters as follows...

$suquery=$dbCon->prepare("select * from Table where ? LIKE ?");
$suquery->bind_param('ss', $field, $term);
$suquery->execute();

The result always returns 0 rows. What I am finding as I play with this is that neither bound parameter is working correctly even though it echoes as it should. For instance, when I change the query so that the column is hard coded and only bind the search term....

$suquery=$dbCon->prepare("select * from Table where columnName LIKE ?");
$suquery->bind_param('s', $term);
$suquery->execute();

I still get zero returned rows. This tells me that even though $field echoes as '%a%' something is still off. I really am at a loss on that one. Likewise, when I hard wire the search term and bind the column....

$suquery=$dbCon->prepare("select * from Table where ? LIKE '%a%'");
$suquery->bind_param('s', $field);
$suquery->execute();

I get far too many rows returned. It is actually pulling rows from the table where the value in any column contains the letter "a". So, neither column or term is binding correctly. Mayday!

A: 

EDIT: Original Answer was based on false assumption (assumed PDO instead of mysqli). Changed answer accordingly.

It looks like you are not allowed to use parameter substitution for column names. From the mysqli::prepare documentation:

Note: The markers are legal only in certain places in SQL statements. For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value. However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement, or ...

You might want to verify this by hardcoding the column/field name in the query and just replacing the comparison value via parameter...

Henrik Opel
Actually, no. I did, however, attempt to go down that road in an effort to get this working. I'm just baffled. I've been using bound parameters forever and I've never been this stuck for this long on something. It's frustrating me no end.
robert knobulous
Hi, I just realized my error - should have looked at the tags more closely. I changed my answer, as the problem might be related to parameter replacement not being allowed for identifiers (table and column names)
Henrik Opel
Hank, thanks very much for the time and energy you have spent to help me. You are absolutely correct about the column names not being allowed as identifiers. That solves half of my problem and now I wonder if I should re-post the question with just the other half. When I hard cord the column name the query still does not work properly If I type "a" in the search field I echo '%a%' (the single quotes are part of the echo, not something I am adding here ) as the value of $field. So my query is reading "select * from Table where columnName LIKE '%a%'". Still zero results.
robert knobulous
I should add that there is nothing wrong with the db or the query syntax itself as I typed it in my comment above. When I hard code the '%a%' into the query it works as intended. My issue, I think, is with the single quote but I am lost as to how to address it. If I fail to add the single quotes to the variable when I extract it from _POST then I get a mysql syntax error. And rightly so.
robert knobulous
But you are also adding single quotes in front and after the %: `$term = "'%".$_POST['searchTerm']."%'";` - there should be no need for those...
Henrik Opel
You, sir, are a stud.
robert knobulous
Hmm - I think I'd prefer if you'd upvoted and/or accepted the answer instead of me 'being a stud' ;)
Henrik Opel
+2  A: 
$suquery=$dbCon->prepare("select * from Table where ? LIKE ?");

Will not work as expected. It will get translated as:

SELECT * from table WHERE 'columnName' LIKE '%a%'

which returns all rows because 'columnName' contains an 'a'

Your second attempt is correct, except you have an extra quotes in the term. When using parameters, you don't need any quotes. The solution is:

$term = "%".$_POST['searchTerm']."%";
$suquery=$dbCon->prepare("select * from Table where columnName LIKE ?");
$suquery->bind_param('s', $term);
$suquery->execute();
John C
A: 

Just to clarify for anyone stumbling across this. The issue was fairly simple but it was odd enough that tracking it down was a bear. Henrik was partially correct. When parsing the variable $term to use in my LIKE statement I was doing the following:

$term = "'%".$_POST['searchterm']."%'";

Henrik pointed out that I should not need the single quotes bracketing my variable. This is true if one is simply preparing and executing the query as:

$query=$connection->prepare("select * from DATABASE where $field like '$term'");
$query->execute();

That works just fine. However, I was actually using $term as a bound parameter, which meant that I did indeed require the single quotes as the statement itself require the search term to look like this: '%term%'. It requires the single quotes. You will get a syntax error if you try to put the single quotes around the question mark place holder for the bound parameter, and if you do not put the single quotes inside the variable that you are using as the bound parameter the result will always be 0 rows found. So, in short, for anyone else encountering this.... if you are sending the query directly no need for single quotes as you can put them directly into the select statement. If you are using bound parameters you must have the single quotes as part of the variable in order for the query to work properly.

robert knobulous