This question already has answers here:
PHP - Using PDO with IN clause array
(9 answers)
Closed 7 years ago.
I have this SQL query:
$sql = "SELECT ac.id AS target_id FROM account AS ac JOIN
address_vod__c AS ad
ON (ad.account_vod__c = ac.id AND ad.primary_vod__c = 1)
WHERE ac.id IN (?)";
And I am trying to add values for IN clause from a array as follow:
// $values is a huge array containing values
$params = [implode("','", $values)];
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$result = $stmt->fetchAll();
Code is working but I am getting the wrong SQL:
SELECT
ac.id AS target_id
FROM
account AS ac
JOIN
address_vod__c AS ad ON (ad.account_vod__c = ac.id
AND ad.primary_vod__c = 1)
WHERE
ac.id IN ('00180000017rkSfAAI\',\'0018000001GgXTtAAN\',\'0018000001GgXTYAA3')
I expect and I am looking something like:
SELECT
ac.id AS target_id
FROM
account AS ac
JOIN
address_vod__c AS ad ON (ad.account_vod__c = ac.id
AND ad.primary_vod__c = 1)
WHERE
ac.id IN ('00180000017rkSfAAI','0018000001GgXTtAAN','0018000001GgXTYAA3')
How do I avoid PDO from escape the strings?
You are doing ac.id IN (?). This is telling the database that you want to bind one parameter to the query. If you have multiple elements, you need multiple ?s: ac.id IN (?,?,?).
What you can do is dynamically add the ?s and then bind each parameter that you need.
$params = implode(',', array_fill(0, count($values), '?'));
$sql = "SELECT ac.id AS target_id FROM account AS ac
JOIN address_vod__c AS ad ON (ad.account_vod__c = ac.id AND ad.primary_vod__c = 1)
WHERE ac.id IN ({$params})";
$stmt = $pdo->prepare($sql);
$stmt->execute($values);
$result = $stmt->fetchAll();
You should implode the placeholders and let pdo do the work
$inArray = array_fill(0, count($values), '?');
$inExpr = implode(',', $inArray);
$sql = "... WHERE id IN ($inExpr)";
And then just pass $values - pdo will do the rest for you
Related
This question already has answers here:
I have an array of integers, how do I use each one in a mysql query (in php)? [duplicate]
(5 answers)
mySQL bind_param with IN(?) [duplicate]
(5 answers)
Closed 3 years ago.
I have this mysql query in php:
$sql2 = "SELECT id, nazev, poradi FROM system WHERE id IN($idIs) ORDER BY poradi";
$result2 = mysqli_query($conn, $sql2);
The variable $idIs is a string '2,3' (two ids of system).
When I try to fill array $nazevSystemu, there are two values (beacause of the two ids from $idIs)
$i = 0;
$nazevSystemu = [];
while($row2 = mysqli_fetch_assoc($result2)) {
$nazevSystemu[$i] = $row2['nazev'];
echo $row2['nazev'];
$i++;
}
Result of echo $row2['nazev'];:
Value1Value2
I want to make it safe, avert SQl inj., so I use prepared statement like this (instead of the first two rows of code on this page):
$stmt2 = $conn->prepare("SELECT id, nazev, poradi FROM system WHERE id IN(?) ORDER BY poradi");
$stmt2->bind_param("s", $idIs);
$stmt2->execute();
$result2 = $stmt2->get_result();
But now I get only this as result of echo $row2['nazev']; - just one value:
Value1
What did I do wrong in prepared statement?
You have to provide all id's as individual parameters.
So instead of IN(?) you have to write IN(?,?,?) and parse each parameter individual.
Code example:
$ids = explode(',', $idIs);
$stmt2 = $conn->prepare("SELECT id, nazev, poradi FROM system WHERE id IN(".trim(str_repeat('?,', count($ids)), ',').") ORDER BY poradi");
foreach ($ids as $id) {
$stmt2->bind_param("i", $id);
}
$stmt2->execute();
$result2 = $stmt2->get_result();
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 3 years ago.
Is there any way to write this code using prepared statements?
$sql = "SELECT *
FROM exercises
WHERE exercise_id IN (
SELECT DISTINCT e.exercise_id
FROM users u,users_subjects us, exercises e
WHERE u.username='".$_SESSION['username']."' AND us.user_id_fk=u.id AND e.subjects=us.subject_id_fk
);";
$result = $conn->query($sql);
I'm trying this way, but with the sencente ‘IN’, I’m not sure how to do it:
$stmt = $mysqli->prepare("SELECT * FROM exercises where exercise_id in (select distinct e.exercise_id from users u,users_subjects us, exercises e where u.username='".$_SESSION['username']."' and us.user_id_fk=u.id and e.subjects=us.subject_id_fk");
$stmt->bind_param("" );
$stmt->execute();
$stmt->close();
$username = $_SESSION['username'];
// use ?'s in prepare
$stmt = $mysqli->prepare("SELECT * FROM exercises where exercise_id in (select distinct e.exercise_id from users u,users_subjects us, exercises e where u.username=? and us.user_id_fk=u.id and e.subjects=us.subject_id_fk");
// then pass $username to bind_param()
$stmt->bind_param("s", $username);
Then the rest of your code should work. I'd also recommend testing your stmt commands for error handling. They all return booleans.
// use ?'s in prepare
$stmt = $mysqli->prepare("SELECT * FROM exercises where exercise_id in (select distinct e.exercise_id from users u,users_subjects us, exercises e where u.username='?' and us.user_id_fk=u.id and e.subjects=us.subject_id_fk");
if(!$stmt) echo "prepare failed: " . mysqli_error($conn);
Same can be done for bind_param() and execute().
This question already has answers here:
Can I bind an array to an IN() condition in a PDO query?
(23 answers)
Closed 1 year ago.
I'm reworking some PHP code to use PDO for the database access, but I'm running into a problem with a "WHERE... IN" query.
I'm trying to delete some things from a database, based on which items on a form are checked. The length and content of the list will vary, but for this example, imagine that it's this:
$idlist = '260,201,221,216,217,169,210,212,213';
Then the query looks like this:
$query = "DELETE from `foo` WHERE `id` IN (:idlist)";
$st = $db->prepare($query);
$st->execute(array(':idlist' => $idlist));
When I do this, only the first ID is deleted. (I assume it throws out the comma and everything after it.)
I've also tried making $idlist an array, but then it doesn't delete anything.
What's the proper way to use a list of items in a PDO prepared statement?
Since you can't mix Values (the Numbers) with control flow logic (the commas) with prepared statements you need one placeholder per Value.
$idlist = array('260','201','221','216','217','169','210','212','213');
$questionmarks = str_repeat("?,", count($idlist)-1) . "?";
$stmt = $dbh->prepare("DELETE FROM `foo` WHERE `id` IN ($questionmarks)");
and loop to bind the parameters.
This may be helpful too:
https://phpdelusions.net/pdo#in
$arr = [1,2,3];
$in = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE column IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($arr);
$data = $stm->fetchAll();
I would make $idlist and array, then simply loop through the array using foreach to delete the specific item.
$idlist = array('260','201','221','216','217','169','210','212','213');
$stmt = $dbh->prepare("DELETE FROM `foo` WHERE `id` = ?");
$stmt->bindParam(1, $id);
foreach ($idlist as $item){
$id = $item;
$stmt->execute();
}
I have the following SQL statement which has been verified as working:
INSERT INTO community_players (community_id, player_id)
SELECT communities.id, users.id
FROM communities INNER JOIN users ON communities.admin = users.user_email
WHERE users.user_email = 'steve.downs#gmail.com'
AND communities.code = 'HX99f9'
I now want to replace the dummy email and community code data with the variables in the below php function, and submit it to the database.
This is my function:
public function insertNewAdminIntoCommunity($email, $code)
{
$sql = "insert into community_players (community_id, player_id) select communuities.id, users.id from communuities inner join users on communities.admin = users.user_email where users.user_email = '".$email."' and communities.code = '".$code."'";
$statement = $this->conn->prepare($sql);
if(!$statement) throw new Exception($statement->error);
$statement->bind_param("ss", $email, $code);
$returnValue = $statement->execute();
return $returnValue;
}
However it is throwing out errors back into Xcode - II thought maybe I have incorrect syntax when trying to use the variables in the function within the sql statement?
Any ideas?
Thanks
You should not concatenate the variables into the SQL string, as you do here:
users.user_email = '".$email."' and communities.code = '".$code."'";
as that defeats the whole purpose of prepared statements. Prepared statements help protect against SQL-injection, by allowing you to define placeholders that will be replaced with properly escaped values.
You should therefore use placeholders (question marks, without surrounding quotes):
users.user_email = ? and communities.code = ?";
What $statement->bind_param("ss", $email, $code); then does, is bind your variables to the two placeholders. Each s of the first argument signifies that the respective values should be treated as a string.1 MySQL takes care of properly escaping the values this way.
The error therefore most likely is telling you that you are trying to bind values to non-existent placeholders.
See the mysqli_stmt::bind_param() documentation for more available options.
You have a communuities in some field and communities in others
be sure you are using the proper table name in all case
$sql = "insert into community_players (community_id, player_id)
select communuities.id, users.id
from communuities
inner join users on communities.admin = users.user_email
where users.user_email = '".$email."' and communities.code = '".$code. "'";
and i suggest the use PDO with binding param instead string concat ..(and others connections)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
PHP/MYSQL using an array in WHERE clause
I have an array with ID values [1,5,2,6,7...] and I need to use that in a MySQL item_id IN (1,5,2,6,7...) statement to select only rows with an ID listed in the array. How can I go about converting the $arrIDs to something that I can insert into my SQL query?
EDIT- context of the call:
if(!IsNullOrEmptyString($_GET["view_playlist"])) {
session_destroy();
}
$id_list = implode(",", $_SESSION("playlist"));
$sql = 'SELECT t.track_id, t.track_title, t.track_num, al.album_title, g.genre_name, a.artist_name, t.length, t.track_rating '.
'FROM track t, genre g, artist a, album al '.
'WHERE t.track_id IN('.$id_list.' AND t.genre = g.genre_id AND t.artist = a.artist_id AND t.album = al.album_id';
Use implode();
$ids = implode(',', $your_array);
If you're using PDO or mysqli (which you should, as the mysql_ functions are antiquated and should be abandoned), then you'll want to construct a parameterized query using the number of elements in your array to match the number of ?'s in your SQL.
Here's an example in PDO:
$ids = array(1, 2, 3, 4);
try {
$dbh = new PDO("mysql:host=localhost;dbname=mydbname", 'username', 'password');
} catch(PDOException $e) {
die($e->getMessage());
}
$inClause = trim(str_repeat('?, ', count($ids)), ', ');
$stm = $dbh->prepare('SELECT * FROM mytable WHERE id IN ('.$inClause.')');
$stm->execute($ids);
// resulting SQL: SELECT * FROM mytable WHERE id IN (?, ?, ?, ?)