Selecting from database where id in given array - php

I'm trying to select elements from a table in a mysql database where the id of a row is in the given array.
This returns values:
<?php
$ids = '1,2,3,4';
$DBH = ....
$getID = $DBH->prepare("SELECT * FROM t1 WHERE id IN ($ids)");
$getID->execute();
?>
This returns nothing:
<?php
$ids = '1,2,3,4';
$DBH = ....
$getID = $DBH->prepare("SELECT * FROM t1 WHERE id IN (:ids)");
$getID->execute(array(':ids'=>$ids));
?>
I can't understand what is wrong with that code.

In the first one, you're using PHP to do string interpolation before talking to the database; in effect, using PHP variables to generate SQL code. This is where SQL injection comes from - the database doesn't know the difference between data and code, so it can't protect you from "data" leaking into the "code" space. In the second, you are using bound parameters, telling the database "Please deal with :ids as a SINGLE VALUE, whose contents I will tell you later." An easy way to solve the disconnect is something like:
$sql = 'SELECT * from t1 where id in (' . str_repeat('?', count($ids)) . ')';
$stmt = $pdo->prepare($sql);
$stmt->execute($ids);
Check out this tutorial for more on these points.

Assuming you are using PDO, try the following.
<?php
$ids = '1,2,3,4';
$DBH = ....
$getID = $DBH->prepare("SELECT * FROM t1 WHERE id IN (:ids)");
$getID->bindParam(":ids", $ids, PDO::PARAM_INT);
$getID->execute();
?>
When your original query is executed, PDO will escape your input so your query will look like
SELECT * FROM t1 WHERE id IN ("1,2,3,4")
When you tell PDO to bind as a integer, it will execute
SELECT * FROM t1 WHERE id IN (1,2,3,4)

Related

Using PHP variable in SQL query

I'm having some trouble using a variable declared in PHP with an SQL query. I have used the resources at How to include a PHP variable inside a MySQL insert statement but have had no luck with them. I realize this is prone to SQL injection and if someone wants to show me how to protect against that, I will gladly implement that. (I think by using mysql_real_escape_string but that may be deprecated?)
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'hospital_name' AND value = '$q'";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried switching '$q' with $q and that doesn't work. If I substitute the hospital name directly into the query, the SQL query and PHP output code works so I know that's not the problem unless for some reason it uses different logic with a variable when connecting to the database and executing the query.
Thank you in advance.
Edit: I'll go ahead and post more of my actual code instead of just the problem areas since unfortunately none of the answers provided have worked. I am trying to print out a "Case ID" that is the primary key tied to a patient. I am using a REDCap clinical database and their table structure is a little different than normal relational databases. My code is as follows:
<?php
$q = 'Hospital_Name';
$query = "SELECT * FROM database.table WHERE field_name = 'case_id' AND record in (SELECT distinct record FROM database.table WHERE field_name = 'hospital_name' AND value = '$q')";
$query_result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_assoc($query_result)) {
echo $row['value'];
}
?>
I have tried substituting $q with '$q' and '".$q."' and none of those print out the case_id that I need. I also tried using the mysqli_stmt_* functions but they printed nothing but blank as well. Our server uses PHP version 5.3.3 if that is helpful.
Thanks again.
Do it like so
<?php
$q = 'mercy_west';
$query = "SELECT col1,col2,col3,col4 FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
if($stmt = $db->query($query)){
$stmt->bind_param("s",$q); // s is for string, i for integer, number of these must match your ? marks in query. Then variable you're binding is the $q, Must match number of ? as well
$stmt->execute();
$stmt->bind_result($col1,$col2,$col3,$col4); // Can initialize these above with $col1 = "", but these bind what you're selecting. If you select 5 times, must have 5 variables, and they go in in order. select id,name, bind_result($id,name)
$stmt->store_result();
while($stmt->fetch()){ // fetch the results
echo $col1;
}
$stmt->close();
}
?>
Yes mysql_real_escape_string() is deprecated.
One solution, as hinted by answers like this one in that post you included a link to, is to use prepared statements. MySQLi and PDO both support binding parameters with prepared statements.
To continue using the mysqli_* functions, use:
mysqli_prepare() to get a prepared statement
mysqli_stmt_bind_param() to bind the parameter (e.g. for the WHERE condition value='$q')
mysqli_stmt_execute() to execute the statement
mysqli_stmt_bind_result() to send the output to a variable.
<?php
$q = 'Hospital_Name';
$query = "SELECT value FROM database.table WHERE field_name = 'hospital_name' AND value = ?";
$statement = mysqli_prepare($conn, $query);
//Bind parameter for $q; substituted for first ? in $query
//first parameter: 's' -> string
mysqli_stmt_bind_param($statement, 's', $q);
//execute the statement
mysqli_stmt_execute($statement);
//bind an output variable
mysqli_stmt_bind_result($stmt, $value);
while ( mysqli_stmt_fetch($stmt)) {
echo $value; //print the value from each returned row
}
If you consider using PDO, look at bindparam(). You will need to determine the parameters for the PDO constructor but then can use it to get prepared statements with the prepare() method.

How to fetch the record when Query string with the single quotes string in Php

I am fetching data from the MySQL Database and database has a table name
wp_evr_event. I am fetching records using event_name from wp_evr_event.
wp_evr_event table has a fiels name event_name that use name of event.
now event name is Women\'s Reading Group into database.
when I used the Query
$sql = "SELECT * FROM `wp_evr_event` WHERE `event_name` LIKE '%".$_REQUEST['events_name']."%' ";
echo $sql;
Query become like
SELECT * FROM `wp_evr_event` WHERE `event_name` LIKE '%Women \'s Reading Group%'
But this is not fetching any record.
For the wordpress wpdb class you should use 2 functions. esc_like & prepare
A small example:
global $wpdb;
// First, escape the link for use in a LIKE statement.
$link = $wpdb->esc_like( $_REQUEST['events_name'] );
// Add wildcards
$link = '%' . $link . '%';
// Create a SQL statement with placeholders for the string input.
$sql = "SELECT * FROM `wp_evr_event` WHERE `event_name` LIKE '%s'";
// Prepare the SQL statement so the string input gets escaped for security.
$sql = $wpdb->prepare( $sql, $link);
If you prepare your query like this you should get the expected result.

PHP variable in SQLite query

I'm a beginner with web-related coding and I'm trying to make a web-interface from where I can read and write to the sqlite database. My current problem is implementing a PHP-variable ($inNodeID) to sqlite query:
SELECT * FROM data WHERE NodeID = "$inNodeID"
If I replace the variable in query to the value of the variable ("ID007") everything seems to work. So what is wrong with my syntax in this manner?
$inNodeID = "ID007";
echo "Requested node: $inNodeID \n";
print "<table border=1>";
print "<tr><td>NodeID</td><td>MemoryIndex</td><td>DataIndex</td><td>TimeStamp</td></tr>";
$result = $db->query('SELECT * FROM data WHERE NodeID = "$inNodeID"');
//$result->bindParam(':inNodeID', $inNodeID, PDO::PARAM_STR);
foreach($result as $row)
{
print "<td>".$row['NodeID']."</td>";
print "<td>".$row['MemoryIndex']."</td>";
print "<td>".$row['DataIndex']."</td>";
print "<td>".$row['TimeStamp']."</td></tr>";
}
print "</table>";
It seems you were about to use the right way but for some reason gave up
Here you go:
$result = $db->prepare('SELECT * FROM data WHERE NodeID = ?');
$result->execute(array($inNodeID));
$data = $result->fetchAll();
foreach($data as $row)
...
With SQLite3, you can do it like this:
$query = $db->prepare('SELECT * FROM data WHERE NodeID = ? OR NodeID = ?');
$query->bindParam(1, $yourFirstNodeID, SQLITE3_INTEGER);
$query->bindParam(2, $yourSecondNodeID, SQLITE3_INTEGER);
$result = $query->execute();
var_dump($result->fetchArray());
You can find the documentation about bindParam here.
Problem is because of you have enclosed variable $inNodeID. If a variable is enclosed in Quotes PHP behave in different ways based on the Quote thats used. PHP evaluates a variable only when its enclosed in Double quotes, if its used with Single Quote then PHP treats it as a STRING.
please change your code to any one of the below option, your issue will be solved
Option 1
$result = $db->query("SELECT * FROM data WHERE NodeID = $inNodeID");
Option 2
$result = $db->query('SELECT * FROM data WHERE NodeID = '.$inNodeID);
For more info Check Out PHP Manual
you should do Three steps:
prepare your sql code with imaginary word and ":" instead of your variable like this:
$statement = $db -> prepare("SELECT * FROM table WHERE col_test = :imaginary_word");
bind your php variable with the previous step "imaginary word" like this:
$statement -> bindValue(':imaginary_word', $php_variable);
your statement which is a combination of your SQL code and PHP variables is ready and it's the time to execute it like this:
$your_result = $statement -> execute();
♦ now you can use this "$your_result" for fetch_array() , fetch_all Or anything you want...
You don't need to put " around the variable. So try:
$result = $db->query('SELECT * FROM data WHERE NodeID = ' . $inNodeID );

why is PDO returning only one row here?

when binding a comma separated list of id's to my prepared statement i only get one row returned, whereas I expected 3.
<?php
$dbh = new PDO("mysql:host=127.0.0.1;dbname=database", "user", "password");
$stmt = $dbh->prepare('SELECT * FROM Person WHERE PersonID IN (:p)');
$stmt->bindValue(":p", "3,4,5");
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<pre>
<?php print_r($result); ?>
</pre>
if I change the stmt to
SELECT * FROM Person WHERE PersonID IN (3,4,5)
i get back 3 rows as expected, I'm confused !
Because bind will essentially wrap that in quotes and treat it as a single value. Then MySQL is converting it back to an integer so it still finds a match for the first item.
You need to do IN (:p1, :p2, :p3) and bind value each separately
This should work, it dynamically builds the place holders that you should use in the statement:
$idList = array(3, 4, 5);
$argList = join(',', array_fill(0, count($idList), '?'));
$stmt = $dbh->prepare("SELECT * FROM Person WHERE PersonID IN ($argList)");
$stmt->execute($idList);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

PDO - passing a field name as a variable

I'm just migrating my code from mysql_query style commands to PDO style and I ran into a problem. THe old code looked like this :
$query_list_menu = "SELECT ".$_GET['section_name']." from myl_menu_hide_show WHERE id='".$_GET['id']."'";
And the updated code looks like below. Apparently it's not working. I store in $_GET['section_name'] a string that represents a field name from the database. But I think there is a problem when I pass it as a variable. Is the below code valid ? Thanks.
$query_list_menu = "SELECT :section_name from myl_menu_hide_show WHERE id=:id";
$result_list_menu = $db->prepare($query_list_menu);
$result_list_menu->bindValue(':section_name', $_GET['section_name'] , PDO::PARAM_STR);
$result_list_menu->bindValue(':id', $_GET['id'] , PDO::PARAM_INT);
$result_list_menu->execute();
If $_GET['section_name'] contains a column name, your query should be:
$query_list_menu = "SELECT " . $_GET['section_name'] . " from myl_menu_hide_show WHERE id=:id";
Giving:
$query_list_menu = "SELECT :section_name from myl_menu_hide_show WHERE id=:id";
$result_list_menu = $db->prepare($query_list_menu);
$result_list_menu->bindValue(':id', $_GET['id'] , PDO::PARAM_INT);
$result_list_menu->execute();
The reason is that you want the actual name of the column to be in the query - you'd changed it to be a parameter, which doesn't really make much sense.
I'll also add that using $_GET['section_name'] directly like this is a massive security risk as it allows for SQL injection. I suggest that you validate the value of $_GET['section_name'] by checking it against a list of columns before building and executing the query.
There is no good and safe way to select just one field from the record based on the user's choice. The most sensible solution would be to select the whole row and then return the only field requested
$sql = "SELECT * from myl_menu_hide_show WHERE id=?";
$stmt = $db->prepare($query_list_menu);
$stmt->execute([$_GET['id']]);
$row = $stmt->fetch();
return $row[$_GET['section_name']] ?? false;

Categories