Mysqli query with a SET variable statment (ie multiple queries) - php

I want to set a variable to use in a mysqli query. This doesn't quite work. Prior to mysqli I used to set query calls. I played around with db->multi_query($sql) with no luck. Anyone out there have an idea how to make this work including a set statement?
$sql = 'SET #rownum := 0;';
$sql .= 'SELECT #rownum :=#rownum + 1 AS Rank, User_Id, COUNT(User_ID) AS Block_Count
FROM Block_Owners;
$stmt = $db->prepare($sql);
$stmt->bind_param('ii', $world, $userId);
// execute the query
$stmt->execute();

Do it in two separate queries:
$db->query('SET #rownum := 0');
$sql = 'SELECT #rownum :=#rownum + 1 AS Rank, User_Id, COUNT(User_ID) AS Block_Count FROM Block_Owners'
$stmt = $db->prepare($sql);
$stmt->bind_param('ii', $world, $userId);
$stmt->execute();
Note, however, that the query you want to run will always return a single row (with Rank = 1) since you are using an aggregate function without GROUP BY.

Related

mysqli prepared statement bind param array of ids

I have simple prepared statement, and i can't find solution to bind list of id's, so as you can see in first statement i get all ids that i need, and in next statement i need to put all those ids into IN clause, but i'm not able to do it, any suggestions how and what is best way to do it ?
$stmt = $mysqli->prepare("SELECT id FROM user WHERE groupId = ? ORDER BY id LIMIT ? OFFSET ?");
$stmt->bind_param("iii", $args['groupId'], $pageSize, $offset);
$stmt->execute();
$stmt->bind_result($id);
$userIds= array();
while ($stmt->fetch()) {
$userIds[] = $id;
}
$stmt= $mysqli->prepare("SELECT a.id as attendantId, a.firstName, a.lastName, c.id as caringId, c.startDate, c.endDate FROM attendant a LEFT JOIN caring c ON c.attendantId = a.id WHERE a.id IN (?)");
$stmt->bind_param('i', $userIds);
$stmt->bind_param('i', implode(',', $userIds));

cannot execute multiple queries

I'm trying to execute multiple queries, but something is wrong.
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
$sql = "
UPDATE tmatria SET par = " . $newpar . ", inde = " . $newinde . " WHERE id =" . $cutid . ";
SELECT * FROM tmatria ORDER BY inde ASC;
SET #i := 0;
UPDATE tmatria SET inde = #i := #i + 1;
";
try {
$db->exec($sql);
}
catch (PDOException $e) {
echo $e->getMessage();
die();
}
I want update some columns, then sort table by inde column and finally set inde values to 1 2 3...
I think lines UPDATE tmatria SET par... and SELECT * FROM tmatria ORDER BY inde ASC; are critical, but cannot see what's wrong.
Any help?
You have some fundamental misunderstanding about how to use SQL. You do a SELECT ... ORDER BY, and then you expect the following UPDATE to obey the same ordering. The UPDATE is ordering the table in its natural order, it doesn't pay attention to the SELECT query at all.
And as a matter of coding, there's no need or benefit to executing multiple SQL statements in one call. PDO permits it, but it's not a good habit. You should execute one SQL statement per call. As long as you use the same db connection, the session variable #i will retain its value.
Also use prepared queries when you want to combine PHP variables with a SQL statement; don't concatenate PHP variables into your SQL string.
try {
$sql = "UPDATE tmatria SET par = ?, inde = ? WHERE id = ?";
$stmt = $db->prepare($sql);
$stmt->execute([$newpar, $newinde, $cutid]);
$sql = "SET #i := 0";
$db->exec($sql);
$sql = "UPDATE tmatria SET inde = #i := #i + 1 ORDER BY inde ASC";
$db->exec($sql);
}
catch (PDOException $e) {
echo $e->getMessage();
die();
}
It also looks like you're trying to renumber inde after every update, to force that column to have consecutive values. This will get slower and slower the more rows you have in the table, right?
You should reconsider why you need that column to have consecutive values.
You need to pass your queries to PDO one at a time. You can still use variables like #i, because PDO will run your queries in order. But it won't run a mess of queries in one call.

Using OR operator in rowCount

I've got a query and when I run it, I use rowCount to check if it returns a result. If it does, I echo some text. If not, I redirect the user - this worked fine until.... I tried to check if either rowCount returned a result in the same line of code, like this:
$id = '1';
$check1 = $stmt = $con->prepare("SELECT * FROM table1 WHERE ID=:id");
$stmt->bindParam(':id', $id);
$stmt->execute();
$check2 = $stmt = $con->prepare("SELECT * FROM table2 WHERE ID=:id");
$stmt->bindParam(':id', $id);
$stmt->execute();
if($check1->rowCount() > 0 || $check2->rowCount() > 0) {
echo 'Hello';
}else{
header('Location: index.php');
exit();
}
I've manually gone into table1 and table2 and there is a result there, however when I execute the script above, I'm re-directed to index.php because apparently, there is no result.
I'm wondering if this line of code has any syntax errors:
if($check1->rowCount() > 0 || $check2->rowCount() > 0)
A better approach for you is to use two scalar ,COUNT(*) subqueries and add together.
SELECT (SELECT COUNT(*)
FROM `table`
WHERE `ID` = 1
) +
(SELECT COUNT(*)
FROM `table1`
WHERE `ID` = 1
) AS Result
If either of the table shows result Result will > 1 so you can test for it.
With PDO regular, unnamed, placeholders with "lazy" binding when possible - passing data into execute are simpler to use & will dramatically shorten your code. NOTE the parameters passed in execute() must match those in query thus $id must be passed twice.
I have altered your code
$id = '1';
$stmt = $con->prepare("SELECT (SELECT COUNT(*)FROM `search`WHERE `ID` = ?)
+ (SELECT COUNT(*) FROM `search1`WHERE `ID` = ?) AS Result");
$stmt->execute(array($id,$id));
if($stmt->fetchColumn() > 0){
echo 'Hello';
}else{
header('Location: index.php');
exit();
}
PDOStatement::rowCount() does not return the number of rows returned from a SELECT query. It's for calculating number of rows affected by UPDATE or DELETE queries.
You shoud use SELECT COUNT(*) FROM table1 WHERE ID=? to get what you want, as the docs say (http://php.net/manual/en/pdostatement.rowcount.php)

Get Date Difference

I want to get the difference between two date in my query. I tried using multiple select statement but it's not working
Here's my code
$tbl_name = "myTable";
$setDay = "10";
$stmt = $pdo->query("SELECT * (
SELECT due_date,
date_paid,
DATEDIFF(due_date, date_paid) as date_interval)
FROM $tbl_name
WHERE DATEDIFF(due_date, date_paid) <= $setDay
ORDER BY trans_id DESC LIMIT $start, $limit");
$stmt->execute();
Thanks
It is important to develop you MySQL queries and perfect them outside the context of PHP code first, then integrate the query once you have it working the way you need it to in a MySQL client application like MySQL Workbench, PHPMyAdmin, etc.
In your query, the outer SELECT is not needed, and the inner query itself looks almost correct, but it is the way you attempt to execute it with PDO that is faulty.
SELECT
due_date,
date_paid,
DATEDIFF(due_date, date_paid) as date_interval
FROM $tbl_name
WHERE
DATEDIFF(due_date, date_paid) <= $setDay
ORDER BY trans_id DESC
LIMIT $start, $limit
Now to execute it in PDO, you should be using prepare()/bindParam()/execute() to create a prepared statement, bind in parameters, and execute it with those parameters (you cannot bind the table name though - that must remain a variable). In your current code, you have a mixup of the the PDO::query() method used for simple static queries and the PDOStatement::execute() method which is used to execute a prepared statement. You should be using the prepared statement method, rather than query().
// Setup the statement with named parameters like :setDay
$sql = "
SELECT
due_date,
date_paid,
DATEDIFF(due_date, date_paid) as date_interval
FROM $tbl_name
WHERE
DATEDIFF(due_date, date_paid) <= :setDay
ORDER BY trans_id DESC
LIMIT :start, :limit
";
// Make PDO throw useful errors on failure
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Prepare the statement
$stmt = $pdo->prepare($sql);
// Bind your 3 parameters and execute it
$stmt->bindParam(':setDay', $setDay, PDO::PARAM_INT);
$stmt->bindParam(':start', $start, PDO::PARAM_INT);
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
// Fetch your rows returned from the query
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Do something with them
print_r($rows);
I always recommend spending time with this PDO tutorial for MySQL developers which places PDO's usage in context of the old mysql_*() API you may already be familiar with.
Try this,
SELECT * , (select (DATEDIFF(due_date,date_paid)) AS date_interval) FROM $tbl_name
Use this to find the date defference,
$diff=date_diff($date1,$date2);

Using two queries at the same time. PDO

Okay so, I don't really know anything about PDO, my friend just asked me to post this here since he's not very good at English. Anyway, this is how he explained it to me:
The code provided is supposed to get a couple of values, save them, and it's supposed to get something out of another table with the help of the values gotten from earlier. The problem according to my friend is that it doesn't get the second value.
Code:
$user_email = $_SESSION['user_email'];
$query = $db->prepare("SELECT username,id,password FROM user WHERE email=:email");
$query->bindParam(':email', $user_email, PDO::PARAM_INT);
$query->execute();
$row = $query->fetch();
$user_username=$row['username'];
$user_group=$row['group'];
$query_group = $db->prepare("SELECT color,name FROM group WHERE id=:id");
$query_group->bindParam(':id', $user_group, PDO::PARAM_INT);
$query_group->execute();
$row = $query_group->fetch();
$group_color=$row['color'];
$group_name=$row['name'];
The word group used as a table name needs to be enclosed in backticks. group is a reserved key word (GROUP BY clause).
SELECT
color,
name
FROM `group`
WHERE id = :id
Using the above would work.
You can shorten the entire code by using a JOIN clause too. As commented above by Prix, the code shall be:
$user_email = $_SESSION['user_email'];
$query = $db->prepare("SELECT
u.username,
u.id,
u.password,
g.color,
g.name
FROM user u
JOIN `group` g
ON g.id = u.id
WHERE u.email = :email");
// I think emails are supposed to be `PDO::PARAM_STR`
$query->bindParam(':email', $user_email, PDO::PARAM_INT);
$query->execute();
$row = $query->fetch();
$user_username = $row['username'];
$group_color = $row['color'];
$group_name = $row['name'];
You don't have group in your select statement .
If you don't use * in your select you must have the field name in your query .
$query = $db->prepare("SELECT username,id,password FROM user WHERE email=:email");
This query gives you only username,id,password back NOT the field group .
so try to use $row['group'] is wrong .
$user_group=$row['group'];
So also put group in your select statement
Place also group in backticks it's a reserved word
$query = $db->prepare("SELECT id, username, password, `group` FROM user WHERE email=:email");
This is also a reason for important variables (e.g for next query) to consider their validity.
if (isset($row['group'])) {
database logic
} else {
error
}
With this simple test you would have found the error itself.

Categories