using mysql variable in where clause with PDO - php

I'm still struggling to find out the best possible solution for binding one date as variable in SQL with PDO. So far I programmed a function in PHP which approximates times in a specific date. I only have one date but the dirtiest solution which I found would be to bind it twice which I wouldn't risk to keep my code clean. So I was thinking to set a variable which will be used then in Where Clause. That's my code so far:
<?php
function approximateAppo($date){
$link = OpenDB();
try {
$query = "SET #v1 = :date;
SELECT from, till
FROM termin
WHERE from >= CONVERT('#v1 08:00:00', DATETIME)
AND till <= CONVERT('#v1 20:00:00', DATETIME)
AND comp_id=:comp";
$statement = $link->prepare($query);
$statement->bindValue(':comp', $_SESSION['comp'],PDO::PARAM_INT);
$statement->bindValue(':date', $date, PDO::PARAM_STR);
$statement->execute();
$row = $statement->fetchAll();
} catch (PDOException $e){
p($e);
}
CloseDB($link);
return $row;
}
But it doesn't really work, what might be the issue in there? Or what is the best possible solution for solving the issue? I still haven't found anything similar for solving my case.

You can't execute multiple queries in a single call.
You can initialize a variable in a subquery.
Also, variables aren't replaced inside strings, you need to use CONCAT().
$query = "SELECT from, till
FROM termin
CROSS JOIN (SELECT #v1 := :date) AS x
WHERE from >= CONVERT(CONCAT(#v1, ' 08:00:00'), DATETIME)
AND till <= CONVERT(CONCAT(#v1, ' 20:00:00'), DATETIME)
AND comp_id=:comp";
But there isn't really a need for the variable, you can use the :date placeholder twice.
$query = "SELECT from, till
FROM termin
WHERE from >= CONVERT(CONCAT(:date, ' 08:00:00'), DATETIME)
AND till <= CONVERT(CONCAT(:date, ' 20:00:00'), DATETIME)
AND comp_id=:comp";

Related

PDO statement select where date less than error

I've spent 2 days trying to fix this - my date comparisons in MySQL aren't working when
trying to bind values with the <= less than or equals operator.
I've narrowed it down to the second date field (from a much more complicated script that changes the prepared statement joins/groups/fields/conditions depending on the request..hence why I am referring to table.column and selecting from only one table below - it works either way) but I can't make sense of it. The exact code used to work on php 5.x but I have just upgraded to php7.2.27.
Take the below SQL statement:
$sth = $this->prepare("SELECT
transaction.transactionid,
transaction.accountid,
transaction.userid,
transaction.billdate,
transaction.amount,
transaction.description,
transaction.confirmed
FROM transaction
WHERE
DATE(`billdate`) BETWEEN :startdate AND :enddate #date('2020-03-12')
ORDER BY billdate desc");
Trying to bind the following to it:
$terms = array(':startdate' => "2000-01-01",':enddate' => "2020-03-12");
foreach ($terms as $key => $value) {
if($value == (int)$value)
$sth->bindValue("$key", $value, PDO::PARAM_INT);
else
$sth->bindValue("$key", $value);
}
var_dump($sth);
var_dump($terms);
$sth->execute();
$this->rowCount = $sth->rowCount();
var_dump( $sth->fetchAll(PDO::FETCH_ASSOC));
This returns an empty array.
The table contains a handful of test rows. The below returns correctly:
...
DATE(`billdate`) BETWEEN :startdate AND '2020-03-12'
ORDER BY billdate desc
Wrapping the dates in date('date') seems to make no difference.
I've also tried this...
DATE(`billdate`) >= :startdate AND
DATE(`billdate`) <= '2020-03-12'
ORDER BY billdate desc
");
(Of course, changing the bound terms so that they mirror whatever I am using)
I need to be able to bind both variables.
Grateful for any pointers as I would love to avoid wasting another day debugging this!
Thanks
Just CAST to DATE:
WHERE billdate
BETWEEN CAST(:startdate AS DATE) AND CAST(:enddate AS DATE)"
And bind as PDO::PARAM_STR:
$sth->bindValue("startdate", "2000-01-01", PDO::PARAM_STR);
$sth->bindValue("enddate", "2020-03-12", PDO::PARAM_STR);

PDO UNION with ? not working

I am new to SQL and PDO and PHP so I know I am asking a lot of myself. Still nothing ventured...
I want to combine the results of two queries and am using aliases to make the column names the same for the UNION query.
I have tried all sorts of reducing till there is nothing left to reduce, there are many more in the actual result I need for my app. I have the following code by can't think why it is not working.
Both queries work on their own but I get nothing when I combine them with a UNION. Any suggestions would be most helpful.
include ("conn/dbCon_1.php");
$sql= "(SELECT First_Name AS myResult FROM tbl_User WHERE First_Name LIKE ?)";
$sql.=" UNION ALL ";
$sql.= "(SELECT Course_Title AS myResult FROM tbl_Course WHERE Course_Title LIKE ? )";
$c1 = "%le%";
try {
$qResults = $dbConn->prepare($sql);
$qResults->execute([$c1]);
$qResults->fetch(PDO::FETCH_ASSOC);
return $qResults;
//Close connection
$dbConn = null;
} catch(PDOExcepetion $e) {
echo $e->getMessage();
}
Many thanks in anticipation and thank you for your kind attention.
Bri
As you have two placeholders - you should bind values twice:
$qResults->execute([$c1, $c1]);
You invoke the query with two parameters (like in the first Query and like in the second) even if they have the same value .. so you have to pass two parameters
$qResults->execute([$c1, $c1]);

PHP PDO rowCount returns -1 on SELECT statement

I am having a strange problem that has been kicking my backside all day long.
I have the following code:
$today = date("m/d/Y");
$sql = "SELECT * FROM msgs WHERE is_errata = 0 AND kill_date >= '$today' AND msg_date <= '$today' ORDER BY msg_date";
$ps = $pdo->prepare($sql);
if (!$ps) {
echo "PDO::errorInfo():";
print_r($pdo->errorInfo());
}else{
$ps->execute();
$number_of_rows = $ps->rowCount();
When I display the value of $number_of_rows, it ALWAYS displays -1, even when I get results.
Anyone else have this problem?
Oh, and the database I am using is NOT MySQL, but the lovely MS Access. I suspect this might be the problem.
rowCount() method does NOT return number of rows from SELECT statement. It's common mistake.
PDOStatement::rowCount() returns the number of rows affected by the
last DELETE, INSERT, or UPDATE statement executed by the corresponding
PDOStatement object.
If the last SQL statement executed by the associated PDOStatement was
a SELECT statement, some databases may return the number of rows
returned by that statement. However, this behaviour is not guaranteed
for all databases and should not be relied on for portable
applications.
More details you can find in the documentation.
So to get number of rows you have to write SELECT statement with sql COUNT(*) function. In your case:
$sql = "SELECT COUNT(*) AS `count` FROM msgs WHERE is_errata = 0 AND kill_date >= '$today' AND msg_date <= '$today' ORDER BY msg_date";
or using PHP:
$number_of_rows = count($ps->fetchAll());
You should also learn to prepare the query the right way
You should use iterator_count to count rows, i.e.
$number_of_rows = iterator_count($ps);

How do I count how many times a value appears in a MySQL column?

I have a MySQL table called Reports, and in it is a column called Status. This is set to either Open, Pending, or Closed. I need to be able to count how many reports are set to Open, Closed, and Pending respectively. I also need to put these numbers into individual variables for use in a graph.
I use PDO on the site and am easily able to add, edit, and retrieve data but I can't for the life of me get this to work. I find PDO very confusing and difficult to learn since everyone seems to use completely different formatting, syntax, and variable names in all the examples I can find online. I have no idea if I'm even on the right track with this. Here's what I've come up with so far;
try {
$DBH = new PDO("mysql:host=localhost;dbname=$dbname",$dbuser,$dbpass);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$STH = $DBH->prepare("SELECT status, COUNT(*) FROM reports GROUP BY status");
$result = $STH->fetch();
}
catch(PDOException $e) {
echo $e->getMessage();
}
I don't get any errors or anything. How can I even troubleshoot this?
As a bit of an extra feature, I'd like to be able to only count the values of entries submitted between certain dates. I have a date column already in the database.
Am I on the right track? Completely off? I can make this work no problem with straight MySQL queries but not with PDO.
I think you've missed the execute() command? You may also want to use fetchAll instead of fetch to get everything.
try {
$DBH = new PDO("mysql:host=localhost;dbname=$dbname",$dbuser,$dbpass);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$STH = $DBH->prepare("SELECT status, COUNT(*) AS count FROM reports WHERE date_field BETWEEN :start_date AND :end_date GROUP BY status");
$STH->execute(array(':start_date' => $start_date_variable, ':end_date' => $end_date_variable));
$rows = $STH->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
echo $row['status'] . " = " . $row['count'];
}
}catch(PDOException $e) {
echo $e->getMessage();
}
Think you're not actually running the query currently? Haven't used PDO for a while so may be wrong but give it a try..
You'll need something to this effect:
SELECT sum(
IF (
COALESCE (status, '') = 'Open',
1,
0
)
) AS total_open,
sum(
IF (
COALESCE (status, '') = 'Closed',
1,
0
)
) AS total_closed,
sum(
IF (
COALESCE(status, '') = 'Pending ',
1,
0
)
) AS total_pending
FROM reports
This should give you the total number of each in 3 different columns that you can use for your graph.

How to check for existence of specific date in MySQL 'date' column?

Using the code below, I'm having trouble checking whether a specified date exists in a MySQL 'date' column.
$data = array(1367971200);
$s=$dbh->prepare("
SELECT DISTINCT
`date`
FROM
`report_coa_bal_hist`
WHERE
UNIX_TIMESTAMP(`date`) = ?
");
if ($s->execute($data)) {
if ($s['date'] == null) {
return false;
}
return true;
}
It's returning false, despite the fact that I can see the date '2013-05-08' displayed in phpMyAdmin.
The table itself contains 70+ entries for that date. It always will do, if it contains any at all, but I just want to know whether it exists or not at this stage.
The date field is a MySQL 'date' type. I'm suspecting that the bug is in my structuring of the PDO calling of the query.
UPDATE
Updated $r['date'] to `$s['date']. I suspect that I still have an issue with the structure of that, but probably need to fix the query so that it gives us results before focusing on this.
Also tried running the query against the database directly and got an empty resultset, despite being able to see that the target date exists. Still baffled!
Try this
$data = array(1367971200);
$s=$dbh->prepare("
SELECT COUNT(`date`) as c_date
FROM
`report_coa_bal_hist`
WHERE
UNIX_TIMESTAMP(`date`) = ?");
if ($s->execute($data)) {
$result = $s->fetch(PDO::FETCH_ASSOC);
if ($result['c_date'] > 0) {
return false;
}
return true;
}
You can't select a whole day with UNIX timestamps because of their more accurate nature (i.e. seconds), you would need the textual version:
$data = array(date('Y-m-d', 1367971200));
$stmt = $dbh->prepare("SELECT COUNT(*)
FROM `report_coa_bal_hist`
WHERE `date` = ?
");
$stmt->execute($data);
$count = current($stmt->fetchAll(PDO::FETCH_COLUMN, 0));
return $count > 0;
Take note of any timezone differences between the server that runs your script and the database server itself.
there are many flaws with your code, not one:
format of the value you are checking
way you are checking in SQL
the way you are getting result
So, the code have to be
$data = array('2013-05-07');
$sql = "SELECT 1 FROM report_coa_bal_hist WHERE `date` = ? LIMIT 1";
$stm = $dbh->prepare($sql);
$stm->execute($data);
return $stm->fetchColumn();

Categories