I have a mysql query that targets a single column in a single row
"SELECT some_col_name FROM table_name WHERE user=:user"
After I execute the statement $stmt->execute(); how do I get this single cell directly placed into a variable with no loops? In other words how to get
from $stmt->execute();
to $col_value = 100;
I tried the 2 below, but neither worked.. The column is number 4 in the original table, but I'm assuming since in my select statement I'm selecting it only, it should be 1 when I specify the parameter for fetchColumn.
$col_value = $stmt->fetchColumn();
$col_value = $stmt->fetchColumn(0);
As you can see, I'm trying to do it in as few lines as possible.
Are you sure it's returning any rows?
$stmt->fetchColumn()
is correct way to fetch a single value, so either you probably didn't bind the :user parameter or it simply returned no rows.
$sql='SELECT some_col_name FROM table_name WHERE user=?';
$sth=$pdo_dbh->prepare($sql);
$data=array($user);
$sth->execute($data);
$result=$sth->fetchColumn();
I'm not sure why so many people mess this up:
$stmt = $dbh->prepare("SELECT `column` FROM `table` WHERE `where`=:where");
$stmt->bindValue(':where', $MyWhere);
$stmt->execute();
$SingleVar = $stmt->fetchColumn();
Make sure that you are selecting a specific column in the query and not * or you will need to specify the column order number in fetchColumn(), example: $stmt->fetchColumn(2); That usually isn't a good idea because the columns in the database may be reorganized by, someone...
This will only work properly with unique 'wheres'; fetchColumn() will not return an array.
When you want to get the last insert you add the DESC Limit 1 to the sql statement.
$sql = "SELECT `some_col_name` FROM table_name\n"
. "ORDER BY `some_col_name` DESC\n"
. "LIMIT 1";
$stmt = $conn->prepare($sql);
$result = $stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
//convert the array content to string and store in variable
$col = implode(" ", $row);
echo $col;
Have you prepared the statement first? (Before $stmt->execute())
$stmt = $db->prepare("SELECT some_col_name FROM table_name WHERE user=:user");
You could use this:
$stmt->fetch(PDO::FETCH_COLUMN, $number_of_column);
Related
This question already has an answer here:
PDO pagination with LIKE
(1 answer)
Closed 2 years ago.
I have one doubt about PDO.
I have a method in the class that returns data from the database for sent filters.
I want to get a number of rows for that query, but there are LIMIT and STAR in the query.
So because of that, I am using two queries to get a number of rows and data but to work, I need to bind the same value two times. Is there any more elegant way to achieve not have repeated code?
The method that I use is below.
$db = $this->openConnection();
$sql = " SELECT * FROM contacts";
// Filter data by main search input
if(!empty($search_query)){
$sql .= " WHERE ( location LIKE :search_query_location OR address LIKE :search_query_address ) ";
}
$sql .=" ORDER BY ".$order;
$stmt = $db->prepare($sql);
if(!empty($search_query)){
$stmt->bindValue(':search_query_location', (string) $search_query.'%');
$stmt->bindValue(':search_query_address', (string) $search_query.'%');
}
// Get number of rows after filter
$stmt->execute();
$total = $stmt->rowCount();
$sql .=" LIMIT :start, :limit_num";
$stmt = $db->prepare($sql);
if(!empty($search_query)){
$stmt->bindValue(':search_query_location', (string) $search_query.'%');
$stmt->bindValue(':search_query_address', (string) $search_query.'%');
}
// Bind start and limit value
$stmt->bindValue(':start', (int) $start, PDO::PARAM_INT);
$stmt->bindValue(':limit_num', (int) $limit, PDO::PARAM_INT);
// Get filtered data
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
return array($total,$data);
WHY I NEED TO REPEAT BINDING FOR TWO SAME QUERIES ONE WITHOUT LIMITS TO WORK IS THERE ANY ELEGANT SOLUTION
Problem
The reason that you have to bind twice is that $pdo->prepare($sql) returns a PDOStatement which isn't editable after it's been set. So when you update it you have to overwrite it and start again... Obviously the new statement doesn't retain the old bound parameters.
If you think of it as an array that you add some data to and then overwrite with a new, blank, array... You then can't read the information from the original array because it doesn't exist in the new one:
$array = [];
$array[] = 1;
$array[] = 2;
$array[] = 3;
var_dump($array);
/*
Output...
Array
(
[0] => 1
[1] => 2
[2] => 3
)
*/
$array = [];
print_r($array);
/*
Output...
Array
(
)
*/
The difference is that PDOStatement is an object not an array. But it's functionally the same thing!
N.B.
While $pdo->rowCount() may return the number of results from a SELECT query it isn't guaranteed so usually it's best practice not to use it.
I wouldn't overwrite the variable with a new query anyway... Better to use a different variable name e.g. $countQuery and $dataQuery
Solutions
So, if the only reason is that you're trying to reduce the amount of code then there are a bunch of solutions that you could use. However, this doesn't appear to be code golf, so why does it matter?
Solution 1
Assuming you don't have an unreasonable amount of unneeded results returned by the query then you could just return the array from the first query and use array_slice to take the place of the second query...
$pdo = $this->openConnection();
$sql = "SELECT * FROM contacts";
if($search_query){
$sql .= " WHERE ( location LIKE :search_query_location OR address LIKE :search_query_address ) ";
}
$sql .= " ORDER BY :order";
$query = $pdo->prepare($sql);
if($search_query){
$query->bindValue(':search_query_location', $search_query.'%');
$query->bindValue(':search_query_address', $search_query.'%');
}
$query->bindValue(':order', $order);
$query->execute();
$result = $query->fetchAll(PDO::FETCH_ASSOC);
$count = count($result);
return [$count, array_slice($result, $start, $limit)];
Solution 2
If you're worried about readability and code maintenance then you should remember that: it's usual for a method/function to have a reasonably specific function, for example...
Return the number of rows which match a query
Return the data which matches a query
Implementing this would mean you have each of your queries in separate functions:
function countContacts(...)
{
$sql = 'SELECT count(*) FROM contacts WHERE ...';
$query = $pdo->prepare($sql);
$query->bindValue(...);
$query->execute();
return $query->fetchColumn();
}
function getContacts(...)
{
$sql = 'SELECT * FROM contacts WHERE ... ORDER BY ... LIMIT ...';
$query = $pdo->prepare($sql);
$query->bindValue(...);
$query->execute();
return $result->fetchAll(PDO::FETCH_ASSOC);
}
Solution 3
I wouldn't use this, but it technically solves the issue
You could use a union and run two queries in one, then you could use emulated prepared statements (as per #Straberry's answer) to bind once...
Although, again, emulated prepared statements are not something that anyone on here is likely to suggest you should use without good reason. Of course you could use normal prepares and use different bind parameter names.
Either way, this isn't a great solution. I wouldn't use it.
$sql = "
SELECT COUNT(*) as col1, null as col2, null as col3, null as col4, null as col5 FROM contacts WHERE ...
UNTION
SELECT col1, col2, col3, col4, col5 FROM contacts WHERE ... ORDER BY ... LIMIT ...
";
$query = $pdo->prepare($sql);
$query->bindValue(...);
$query->execute();
$result = $query->fetchAll(PDO::FETCH_ASSOC);
return [$result[0]["col1"], array_slice($result, 1)];
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.
Hello I have a prepared statement and I need to count the number of results I get. In order to do this I use store_result and num_rows
$query = 'SELECT userId, promo, email FROM users WHERE active = ?';
$rsActivation = $db->prepare($query);
$rsActivation->bind_param('s', $actv);
$rsActivation->execute();
$rsActivation->store_result();
$totalRows = $rsActivation->num_rows;
This code manages to get me the number of rows. The problem is that if I do this I cannot use fetch() on $rsActivation. If I use fetch and not use store_result I cannot get the number of rows.
How can I accomplish both things?
Thanks
SOLVED:
Turns out my problem was I was trying to fetch the results as an associative array. Instead I used bind_result to assign values to variables. Then I was able to use store_result and num_rows to get the count and after that I used fetch() together with the variables I assigned in bind_result.
$query = 'SELECT userId, promo, email FROM users WHERE active = ?';
$rsActivation = $db->prepare($query);
$rsActivation->bind_param('s', $actv);
$rsActivation->execute();
$rsActivation->bind_result($userId, $promo, $email);
$rsActivation->store_result();
$totalRows = $rsActivation->num_rows;
while($rsActivation->fetch()){
echo "<p>". $userId ."</p>";
...
}
You can try using
...
$rsActivation->execute();
$results = $rsActivation->get_results();
$totalRows = $results->num_rows;
and you should be able to fetch using something like
$results->fetch_assoc(), $results->fetch_row(), etc.
Here's the doc for it: http://php.net/manual/en/class.mysqli-result.php
Possibly stupid question, but can not find answer.
I need to get values from two columns of the same row.
And then set variables with each value.
Here I get one value from column Number and then define variable $NumberPostRegister1
$stmt = $db->prepare("SELECT Number FROM 2_1_journal WHERE Number = :Number1");
$stmt->bindParam(':Number1', $row_id1);
$stmt->execute();
$NumberPostRegister1 = $stmt->fetchColumn();
echo $NumberPostRegister1 .' NumberPostRegister1<br>';
Here I get second value from column IfDraft and then define variable $IfDraft1
$stmt = $db->prepare("SELECT IfDraft FROM 2_1_journal WHERE Number = :Number1");
$stmt->bindParam(':Number1', $row_id1);
$stmt->execute();
$IfDraft1 = $stmt->fetchColumn();
echo $IfDraft1 .' NumberPostRegister1<br>';
Two queries and rather long code.
How to do the same using one query and shorter/simpler code?
$stmt = $db->prepare("SELECT IfDraft, Number FROM 2_1_journal WHERE Number = ?");
$stmt->execute(array($row_id1));
list($IfDraft, $Numer) = $stmt->fetch();
I have a mysql query that targets a single column in a single row
"SELECT some_col_name FROM table_name WHERE user=:user"
After I execute the statement $stmt->execute(); how do I get this single cell directly placed into a variable with no loops? In other words how to get
from $stmt->execute();
to $col_value = 100;
I tried the 2 below, but neither worked.. The column is number 4 in the original table, but I'm assuming since in my select statement I'm selecting it only, it should be 1 when I specify the parameter for fetchColumn.
$col_value = $stmt->fetchColumn();
$col_value = $stmt->fetchColumn(0);
As you can see, I'm trying to do it in as few lines as possible.
Are you sure it's returning any rows?
$stmt->fetchColumn()
is correct way to fetch a single value, so either you probably didn't bind the :user parameter or it simply returned no rows.
$sql='SELECT some_col_name FROM table_name WHERE user=?';
$sth=$pdo_dbh->prepare($sql);
$data=array($user);
$sth->execute($data);
$result=$sth->fetchColumn();
I'm not sure why so many people mess this up:
$stmt = $dbh->prepare("SELECT `column` FROM `table` WHERE `where`=:where");
$stmt->bindValue(':where', $MyWhere);
$stmt->execute();
$SingleVar = $stmt->fetchColumn();
Make sure that you are selecting a specific column in the query and not * or you will need to specify the column order number in fetchColumn(), example: $stmt->fetchColumn(2); That usually isn't a good idea because the columns in the database may be reorganized by, someone...
This will only work properly with unique 'wheres'; fetchColumn() will not return an array.
When you want to get the last insert you add the DESC Limit 1 to the sql statement.
$sql = "SELECT `some_col_name` FROM table_name\n"
. "ORDER BY `some_col_name` DESC\n"
. "LIMIT 1";
$stmt = $conn->prepare($sql);
$result = $stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
//convert the array content to string and store in variable
$col = implode(" ", $row);
echo $col;
Have you prepared the statement first? (Before $stmt->execute())
$stmt = $db->prepare("SELECT some_col_name FROM table_name WHERE user=:user");
You could use this:
$stmt->fetch(PDO::FETCH_COLUMN, $number_of_column);