This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 8 years ago.
I'm having trouble figuring out what I'm doing wrong. If i use this set of code I get the result I intend:
$x = $db->prepare('SELECT * FROM table LIMIT 2');
$x->execute();
print_r($x->fetchALL());
When I use this set of code I don't get anything in return:
$a = "table";
$b = "2";
$x = $db->prepare('SELECT * FROM ? LIMIT ?');
$x->execute(array($a,$b));
print_r($x->fetchALL());
Is there something I'm missing? Thanks in advance.
Parameter placeholders can only be used to replace column values; not table names, column names, or other syntax elements (including LIMIT values).
In order to make your query dynamic with respect to things that can't be parameterized, you have to build it yourself, without PDO's help. However, you should still build it so that the values that can be parameterized, are paramerized.
Related
This question already has answers here:
Use an array in a mysqli prepared statement: `WHERE .. IN(..)` query [duplicate]
(8 answers)
Build SELECT query with dynamic number of LIKE conditions as a mysqli prepared statement
(2 answers)
Closed 11 months ago.
I'm currently facing a difficulty where putting a comma-separated values to a MySQL NOT IN doesn't give me the result I was hoping for. There must be something I'm missing as I'm unsure what to search for this particular problem. Running only the MySQL code works, but passing the parameter from another PHP function didn't.
Here's the code that's giving me a problem:
$uid = 1;
$selected_uids = '1,2';
$result = $db->retrieveFollowingWithCondition($uid, $selected_uids);
...then somewhere along the code...
public function retrieveFollowingWithCondition($uid, $selected_uids) {
$stmt = $this->conn->prepare("SELECT *
FROM `friendlist`
WHERE `uid` = ? AND `buddy_uid` NOT IN (?)
GROUP BY `buddy_uid`;");
$stmt->bind_param("is", $uid, $selected_uids);
...}
I've tested just putting '2' in $selected_uids and it actually works. But once there's comma involved, the code runs but the $selected_uids are still in the result. Not sure this is a bad practice or just needing a minor adjustment to the code. Anyway, I'm really looking forward to understand why it's not working for me.
By using s in bind_param you are telling PHP to treat the entire contents of $selected_uids as a string. Therefore, "1,2" is treated as ('1,2') instead of (1,2). Your problem is that bind_param doesn't support arrays, so support of IN queries is limited. There are a number of alternatives to get around this limitation, but since you are dealing with a list of ints, I would probably do a raw string concat.
// using is_numeric because is_int("1") === false
$filtered = array_filter('is_numeric', $selected_uids);
// You could also just call array_map('intval', $selected_uids);
// Depending on your needs.
if(!$filtered) {
return; // No valid values
}
$filteredStr = implode(',', $filtered);
$stmt = $this->conn->prepare("SELECT *
FROM `friendlist`
WHERE `uid` = ? AND `buddy_uid` NOT IN ($filteredStr)
GROUP BY `buddy_uid`;");
Should also be noted: if I were trying to use strings for an IN query, I would likely do the following:
$filtered = array_map([$this->conn, 'escape_string'], $queried);
$inQuery = '\'' . implode('\',\'', $filtered) . '\'';
I find that notation cleaner and easier than a dynamically generated bind_param format string.
You should bind every parameter in IN(...) separately, but method bind_param doesn't support multiple calls. There is a nice class that can do this and you can find it on PHP documentation pages:
Custom class for multiple bind_param
This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Using LIKE in bindParam for a MySQL PDO Query [duplicate]
(2 answers)
Closed 7 years ago.
I'm trying to get PDO to return the results of a wildcard search. My code is:
$search = "%Notes%";
$result = $db->prepare("SELECT * FROM books WHERE 'name' LIKE :search");
$result->bindParam(':search', $search);
$result->execute();
while($arr = $result->fetch(PDO::FETCH_ASSOC)){
echo $arr['name'];
}
At the moment, I get a blank screen. If I run the sequel through PHPMyAdmin:
SELECT * FROM books WHERE name LIKE '%Notes%'
I get the appropriate result.
I assume it's something to do with the way I am formatting my PDO statement, I know you can't have a dynamic column name but I don't see what is going wrong?
in your query you have 'name' change that to just backticks instead of quotes
aka
$result = $db->prepare("SELECT * FROM `books` WHERE `name` LIKE :search");
you can also just remove the backticks
This question already has answers here:
Can I parameterize the table name in a prepared statement? [duplicate]
(2 answers)
Closed 8 years ago.
I'm trying to prepare the following code:
foreach((array)$problem as $word) { //cycles through each word in the problem, grabs tag name like word, looking through each separate tag table
foreach((array)$tables as $table) { //cycles through list of keyword tables, checks keywords against tables
$query = $mysqli->prepare("SELECT ?.name FROM ? WHERE ?.words LIKE '?'"); //grabs table name where keyword exists
$query->bind_param('ssss',$table,$table,$table,$word);
$query1 = $query->execute();
$resultThree::fetch_assoc($query1);
if(!is_null($resultThree)) { //if keyword exists
array_push($pretag, $resultThree['name']); //push to pretags
}
}
}
It returns saying "Call to a member function bind_param() on a non-object in /home/whatpzcp/public_html/test/search.php on line 25" (the prepared statement line). Apparently this means the MySQL didn't return anything, but this same code worked fine before I was using prepared statements and doesn't anymore, which is what is confusing me.
Go easy on me as this is my first program! Also, do I need to prepare ALL MySQL statements or just ones that deal with user input?
According to the PHP docs, you may not use ? binding variables "for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement, or to specify both operands of a binary operator such as the = equal sign."
This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 8 years ago.
So I am having this strange issue with PDO, in that queries with bound variables are not executing properly for some reason. Let me show some code:
$conn = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pwd);
$sth=$conn->prepare("select count(*) from article");
$sth->execute();
var_dump($sth->fetchColumn());
This will print out the correct number of entries in the table "article".
However, if we change it slightly, by making the table a named parameter instead of a constant:
$conn = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pwd);
$sth=$conn->prepare("select count(*) from :article");
$sth->execute(array(":article"=>"article"));
var_dump($sth->fetchColumn());
This will print a boolean false. Both statements should return the same result, but I have no idea why the second one is not working. I suspect I have a typo somewhere, but I checked several times, and I don't see any issue. Anyone have any idea?
Not possible. You're trying to use a placeholder for a tablename. This is not permitted. placeholders can only replace values.
SELECT count(*) FROM :table WHERE field=:article
^^^^^^--illegal ^^^^^^^^--legal
For this, you'll have to use old-fashion string building:
$table = "article";
$sth=$conn->prepare("select count(*) from $table");
which then re-opens the SQL injection attack vulnerability, because you're now directly inserting external data into an SQL string.
This question already has answers here:
How can I bind an array of strings with a mysqli prepared statement?
(7 answers)
Closed 3 years ago.
I’m moving some old code over to the new msqli interface using prepared statements, I’m having trouble with SQL statements containing the IN clause. I would just normally do this:
$ids = '123,535,345,567,878'
$sql = "SELECT * FROM table WHERE id IN ($ids)";
$res = mysql_query($sql);
Converting this to mysqli and prepared statements I have tried a number of solutions:
$ids = '123,535,345,567,878'
$ids = implode($ids,',');
$result = $msqli->prepare("SELECT foo,blar FROM table WHERE id IN (?));
$result->bind_param("i", $ids);
$result->execute();
The above fails and calculating the number of elements in the array and altering number of question marks in the SQL string and calling bind_parm for each element in the array also fails. Just using the comma separated string also fails.
I can find no good documentation in Google on this, so how have you solved the problem?
It's not possible to bind a list of variable length to a single bound variable.
Similarly, if you were to bind the string $ids you'll actually end up with:
SELECT foo,blar FROM table WHERE id IN ('123,535,345,567,878')
(Note the quotes around the list of IDs).
Creating your own query with the right number of question marks and bound parameters should have actually worked - you may need to try that again and report on the actual error.
Alternatively, this may be one of those occasions where it's unfortunately necessary to hand-craft your own SQL and not use bound parameters.
Look at the answer to a similar question that has been asked here before (second code sample):
I have an array of integers, how do I use each one in a mysql query (in php)?
It boils down to:
create the SQL string with the right amount of question marks
use call_user_func_array() to bind your array to the query string
I thought the point of prepared statements was so in this situation you could just do:
$stmt = $this->mysqli->prepare("UPDATE radcheck SET attribute = ?, value = ? WHERE username = ? AND attribute LIKE 'CS-Total-Octets%'");
foreach ($usernames as $username)
{
$stmt->bind_param('sss', $bandwidth_types[$bandwidth_type], $bandwidth_bytes, $username);
$stmt->execute();
}
$stmt->close();