Checking for an empty result (PHP, PDO, and MySQL) [duplicate] - php

This question already has an answer here:
How to check fetched result set is empty or not?
(1 answer)
Closed 11 months ago.
What am I doing wrong here? I'm simply retrieving results from a table and then adding them to an array. Everything works as expected until I check for an empty result...
This gets the match, adds it to my array and echoes the result as expected:
$today = date('Y-m-d', strtotime('now'));
$sth = $db->prepare("SELECT id_email FROM db WHERE hardcopy = '1' AND hardcopy_date <= :today AND hardcopy_sent = '0' ORDER BY id_email ASC");
$sth->bindParam(':today', $today, PDO::PARAM_STR);
if(!$sth->execute()) {
$db = null;
exit();
}
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$this->id_email[] = $row['id_email'];
echo $row['id_email'];
}
$db = null;
return true;
When I try to check for an empty result, my code returns 'empty', but no longer yields the matching result:
$today = date('Y-m-d', strtotime('now'));
$sth = $db->prepare("SELECT id_email FROM db WHERE hardcopy = '1' AND hardcopy_date <= :today AND hardcopy_sent = '0' ORDER BY id_email ASC");
$sth->bindParam(':today',$today, PDO::PARAM_STR);
if(!$sth->execute()) {
$db = null;
exit();
}
if ($sth->fetchColumn()) {
echo 'not empty';
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$this->id_email[] = $row['id_email'];
echo $row['id_email'];
}
$db = null;
return true;
}
echo 'empty';
$db = null;
return false;

You're throwing away a result row when you do $sth->fetchColumn(). That's not how you check if there are any results. You do
if ($sth->rowCount() > 0) {
... got results ...
} else {
echo 'nothing';
}
Relevant documentation is here: PDOStatement::rowCount

If you have the option of using fetchAll() then, if there are no rows returned, it will just be an empty array.
count($sql->fetchAll(PDO::FETCH_ASSOC))
will return the number of rows returned.

You should not use rowCount for SELECT statements as it is not portable. I use the isset function to test if a select statement worked:
$today = date('Y-m-d', strtotime('now'));
$sth = $db->prepare("SELECT id_email FROM db WHERE hardcopy = '1' AND hardcopy_date <= :today AND hardcopy_sent = '0' ORDER BY id_email ASC");
// I would usually put this all in a try/catch block, but I kept it the same for continuity
if(!$sth->execute(array(':today'=>$today)))
{
$db = null;
exit();
}
$result = $sth->fetch(PDO::FETCH_OBJ)
if(!isset($result->id_email))
{
echo "empty";
}
else
{
echo "not empty, value is $result->id_email";
}
$db = null;
Of course this is only for a single result, as you might have when looping over a dataset.
I thought I would weigh in as I had to deal with this lately.

$sql = $dbh->prepare("SELECT * from member WHERE member_email = '$username' AND member_password = '$password'");
$sql->execute();
$fetch = $sql->fetch(PDO::FETCH_ASSOC);
// if not empty result
if (is_array($fetch)) {
$_SESSION["userMember"] = $fetch["username"];
$_SESSION["password"] = $fetch["password"];
echo 'yes this member is registered';
}else {
echo 'empty result!';
}

what I'm doing wrong here?
Almost everything.
$today = date('Y-m-d'); // no need for strtotime
$sth = $db->prepare("SELECT id_email FROM db WHERE hardcopy = '1' AND hardcopy_date <= :today AND hardcopy_sent = '0' ORDER BY id_email ASC");
$sth->bindParam(':today',$today); // no need for PDO::PARAM_STR
$sth->execute(); // no need for if
$this->id_email = $sth->fetchAll(PDO::FETCH_COLUMN); // no need for while
return count($this->id_email); // no need for the everything else
Effectively, you always have your fetched data (in this case in $this->id_email variable) to tell whether your query returned anything or not. Read more in my article on PDO.

One more approach to consider:
When I build an HTML table or other database-dependent content (usually via an AJAX call), I like to check if the SELECT query returned any data before working on any markup. If there is no data, I simply return "No data found..." or something to that effect. If there is data, then go forward, build the headers and loop through the content, etc. Even though I will likely limit my database to MySQL, I prefer to write portable code, so rowCount() is out. Instead, check the the column count. A query that returns no rows also returns no columns.
$stmt->execute();
$cols = $stmt->columnCount(); // no columns == no result set
if ($cols > 0) {
// non-repetitive markup code here
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {

I only found one way that worked...
$quote = $pdomodel->executeQuery("SELECT * FROM MyTable");
//if (!is_array($quote)) { didn't work
//if (!isset($quote)) { didn't work
if (count($quote) == 0) { //yep the count worked.
echo 'Record does not exist.';
die;
}

Thanks to Marc B's help, here's what worked for me (note: Marc's rowCount() suggestion could work too, but I wasn't comfortable with the possibility of it not working on a different database or if something changed in mine... also, his select count(*) suggestion would work too, but, I figured because I'd end up getting the data if it existed anyway, so I went this way).
$today = date('Y-m-d', strtotime('now'));
$sth = $db->prepare("SELECT id_email FROM db WHERE hardcopy = '1' AND hardcopy_date <= :today AND hardcopy_sent = '0' ORDER BY id_email ASC");
$sth->bindParam(':today', $today, PDO::PARAM_STR);
if(!$sth->execute()) {
$db = null;
exit();
}
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$this->id_email[] = $row['id_email'];
echo $row['id_email'];
}
$db = null;
if (count($this->id_email) > 0) {
echo 'not empty';
return true;
}
echo 'empty';
return false;

Related

NULL MAX(col) value even though DB has a valid record

So I am trying to extract the maximum invoiceNo for current year and this is how I implemented it with PDO:
$sql = 'SELECT MAX(invoiceNo) AS invoiceId FROM invoices WHERE invoiceDate BETWEEN :yearStart AND :yearEnd HAVING invoiceId IS NOT NULL';
if($stmt = $pdo1->prepare($sql)){
$year = date("Y")."-01-01";
$stmt->bindParam(":yearStart", $year);
$year = date("Y")."-12-31";
$stmt->bindParam(":yearEnd", $year);
if($stmt->execute()){
if($stmt->rowCount() == 1){
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$invoiceNo = $row['invoiceId'];
$response = date("Y").strval(++$invoiceNo);
}
else{
$response = date("Y")."-0";
}
}
}
However, $response keeps getting assigned to the else clause : .
This is how my DB looks like:
Hence I was expecting the $response to be 2022-2.
I think there is something wrong with my SQL query and I apologize for that, still learning the ropes!
$sql = "SELECT MAX(arbitInvoiceNo) AS invoiceId FROM invoices WHERE invoiceDate BETWEEN :dateStart AND :dateEnd HAVING invoiceId IS NOT NULL";
if($stmt = $pdo1->prepare($sql)){
$dateStart = date("Y")."-01-01";
$stmt->bindParam(":dateStart", $dateStart);
$dateEnd = date("Y")."-12-31";
$stmt->bindParam(":dateEnd", $dateEnd);
if($stmt->execute()){
if($stmt->rowCount() == 1){
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$invoiceNo = $row['invoiceId'];
$response = date("Y")."-".strval(++$invoiceNo);
}
else{
$response = date("Y")."-0";
}
}
}
Changed the way I named the variables in PHP and the placeholders in the SQL query. Thank you ADyson for all the help!

odbc_num_rows is not work

$stmt is execute and give Result in Print_r($stmt). Result is this "Resource id #4" but when Print_r($stmt) is put in if (odbc_num_rows($stmt) > 0) {Print_r($stmt);}. it's not give Result. and gone else conditon give message else condition.so How to Put odbc function instead of odbc_num_rows($stmt).if right Parameter pass query execute and gone if condition.
which Odbc function used in if condtion.
<?php
include 'Connection.php';
if(isset($_REQUEST["insert"]))
{
$user = $_GET['user'];
$pwd = $_GET['pass'];
$yid = $_GET['yid'];
$sql = "select RegNo, UserName, Pasword from Std_Reg where UserName= '$user' and Pasword = '$pwd' and YearID = $yid and IsActive = True";
$stmt = odbc_exec($conn, $sql);
$result = array();
if (!empty($stmt)) {
// check for empty result
if (odbc_num_rows($stmt) > 0)
{
print_r($stmt);
$stmt1 = odbc_fetch_array($stmt);
$product = array();
$product['RegNo'] = $stmt1['RegNo'];
$product['UserName'] = $stmt1['UserName'];
$product['Pasword'] = $stmt1['Pasword'];
// success
$result["success"] = 1;
// user node
$result["product"] = array();
array_push($result["product"], $product);
// echoing JSON response
echo json_encode($result);
} else {
// no product found
$result["succes"] = 0;
$result["message"] = "No product found";
// echo no users JSON
echo json_encode($result);
}
//sqlsrv_free_stmt($stmt);
odbc_close($conn); //Close the connnection first
}
}
?>
For INSERT, UPDATE and DELETE statements odbc_num_rows() returns the number of rows affected. The manual says-
Using odbc_num_rows() to determine the number of rows available after a SELECT will return -1 with many drivers.
one way around this behaviour is to do a COUNT(*) in SQL instead. See here for an example.

my function that checks if something is already in the database isn't working

I'm working on this project and I need help with something. I am trying to check if someone is already in the database upon logging in and if they are not, they will be added. However, my code always adds them to the database...
Login code:
<?php
if(isset($_POST["emaillogin"]) and isset($_POST["passwordlogin"])){
$sql = "SELECT `accnr`
FROM `Account`
WHERE '$emaillogin' = `emailadress`
AND '$passwordlogin' = `password` LIMIT 1";
$result = mysql_query($sql);
if ($result == false){
echo "E-mail or password incorrect! <br>";
}else{
$accnr = mysql_fetch_array($result);
setcookie("accnr", $accnr[0] , time() + (1800), "/");
$accnmr = $accnr[0];
if(check_firstest($accnmr) == false){
$query = "INSERT INTO `VRIENDEN`
(`accnr`,`vriendnr`)
VALUES ('$accnmr','$accnmr')";
$result = mysql_query($query);
}
header("location:home.php");
die();
}
}
?>
The function in functions.php:
function check_firstest($accnr){
$query = mysql_query("SELECT count(*) AS 'num' FROM `VRIENDEN` WHERE `accnr` = '$accnr' AND `vriendnr` = '$accnr'");
if($result > 0){
return true;
}
else{
return false;
}
}
The login on its own works just fine, so thats no problem.
Thank you!
Your first query is somewhat odd and you do not capture the values from $_POST into the variables that you are using in the query either
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
if(isset($_POST["emaillogin"]) and isset($_POST["passwordlogin"])){
$sql = "SELECT `accnr`
FROM `Account`
WHERE `emailadress` = '{$_POST['emaillogin']}'
AND `password` = '{$_POST['passwordlogin']}'
LIMIT 1";
$result = mysql_query($sql);
if ($result == false){
// something went REALLY WRONG, report it
echo mysql_error();
exit;
}
if ( mysql_num_rows($result) == 1 ) {
// found user and password matches
header("location:home.php");
exit;
}else{
// new user, create the account
$accnr = mysql_fetch_array($result);
setcookie("accnr", $accnr[0] , time() + (1800), "/");
$accnmr = $accnr[0];
if(check_firstest($accnmr) == false){
$query = "INSERT INTO `VRIENDEN`
(`accnr`,`vriendnr`)
VALUES ('$accnmr','$accnmr')";
$result = mysql_query($query);
}
// and go to home page
header("location:home.php");
die();
}
}
?>
And of course the fix for the check_firstest() is also required
function check_firstest($accnr){
$result = mysql_query("SELECT count(*) AS 'num'
FROM `VRIENDEN`
WHERE `accnr` = '$accnr'
AND `vriendnr` = '$accnr'");
if(mysql_fetch_field($result, 0) > 0){
return true;
} else{
return false;
}
}
But I have to add
Your script is at risk of SQL Injection Attack
Have a look at what happened to Little Bobby Tables Even
if you are escaping inputs, its not safe!
Use prepared parameterized statements
And
You should not be using the mysql_ database extension, it is deprecated and has been for years and is gone for ever in PHP7.
If you are just learning PHP, spend your energies learning the PDO or mysqli database extensions and prepared statements.
Start here
You have to count the resulting rows:
function check_firstest($accnr){
$result = mysql_query("SELECT count(*) AS 'num'
FROM `VRIENDEN`
WHERE `accnr` = '$accnr'
AND `vriendnr` = '$accnr'");
if(mysql_fetch_field($result, 0) > 0){
return true;
} else{
return false;
}
}
Here the mysql_num_rows() function gives the number of rows in the result set. If it is greater than 0 then it means that there is some data.

Pdo Sqlite and php

I have a question related to php / pdo and sqlite. I have ported some code from a mysql backend to a sqlite backend. I have used rowCount() alot in this project.
In my original Mysql application i did this:
$stmt = $db->query("SELECT id FROM table where id = $id ");
$rc = $stmt->rowCount();
if ($rc == 1) {
// do something
}
The documentation says this method is only for returning affected rows from UPDATE, INSERT, DELETE queries, with the PDO_MYSQL driver (and this driver only) you can get the row count for SELECT queries.
So, how to achive the same thing with a sqlite backend?
This is how I have ended up doing it:
$stmt = $db->query("SELECT count(id) as cnt FROM table where id = $id ");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row['cnt'] == "1") {
// do something
} else {
return false;
}
}
}
I am looking for a more elegant solution, while achieving the same thing as rowCount().
This is the way to do that in pdo:
$stmt = $db->query('SELECT * FROM table');
if ($stmt->rowCount() == 1) {
//...
} else {
//...
}
echo $row_count.' rows selected';
(The same way XD)
BTW, I wouldn't recommend doing something like
$stmt = $db->query("SELECT count(id) as cnt FROM table where id = $id ");
It's not good to have variables in statements like that. use something like:
$stmt = $db->query('SELECT id FROM table where id = ?');
$stmt->execute(array($id));
if ($stmt->rowCount() == 1)
{
$arr = $stmt->fetch(PDO::FETCH_ASSOC);
foreach($arr as $element)
{
echo '<pre>'.print_r($element).'</pre>';
}
}
else
{
//...
}
This is part of some code I'm using:
$stmt = $db->prepare('SELECT * FROM users WHERE id=?');
$stmt->execute(array($id));
if ($stmt->rowCount() == 1) {
$currentUser = $stmt->fetchAll(PDO::FETCH_ASSOC)[0];
} else {
return false;
}
Edit: (for compatibility issues)
$stmt = $db->query('SELECT * FROM table');
$arr = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (($arr === false) || (sizeof($arr) == 0)) {
return false;
} else {
//... do ....
echo sizeof($arr);
}

Nested While Loops php

I've been trying to get a series of nested loops working to select the database name from one table then query the selected table in that database, and add up the results and display the number of them and the database name.
I have gotten the code to work but it keeps displaying:
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in
I have tried every way possible I have found online to help, but none work.
$resulta = mysql_query("SELECT dbname AF012 FROM Customer");
while($data = mysql_fetch_array($resulta))
{
$db = $data[' dbname '];
$result = null;
$result2 = mysql_query("SELECT changemade FROM $db.orders");
//looping through the results
while($row = mysql_fetch_array($result2))
{
//checking if any record is 1,2 or 3
if( ($row[‘changemade’]== 1) || ($row[‘changemade’]== 2) || ($row[‘changemade’]== 3) ) {
//if any match the if adding 1 to the counter
$counter ++;
}
}
unset($result2);
echo $db." ".$counter;
echo "<br>";
$counter = 0;
$result = null;
$result2 = null;
}
All the database connections are made and work fine, so it has nothing to do with that. Any help would be great.
You need to introduce error handling, also you can streamline your code. The current point of failure is querying the database and fetching from it, so you can encapsulate it into a function of it's own which will also reduce your code:
function mysql_query_array($query)
{
if (!$result = mysql_query($query)) {
throw new Exception(sprintf('Invalid query "%s", error: %s.', $query, mysql_error()));
}
return function () use ($result) {
return mysql_fetch_array($result);
};
}
With that little helper function, your code is now more compact and it has actual error handling:
$queryA = mysql_query_array("SELECT dbname AF012 FROM Customer");
while ($data = $queryA())
{
$counter = 0;
$queryB = mysql_query_array("SELECT changemade FROM {$data['dbname']}.orders");
while ($row = $queryB())
{
if (in_array($row['changemade'], range(1, 3))) {
$counter++;
}
}
printf("%s %s<br>\n", $db, $counter);
}
This is caused by the fact that mysql_query return false if the query fails, so one of your query fails and mysql_fetch_array() gets a boolean. Try changing $db = $data[' dbname ']; to $db = $data['dbname'];

Categories