DWL with INNER JOIN doesn't work when LIMIT applied - php

I'm trying to create a simple pagination using Bootpag.js in order to fetch my data I've created a PDO script with an INNER JOIN because I need to get and display the user team names from another table also I need to apply LIMIT to set the page selection.
This is the troublesome code,
session_start();
include_once("../iConnect/handShake.php");
include_once ("../Functions/userCheck.php");
if (isset($_REQUEST["page"])){
$page_number = filter_var($_POST["page"], FILTER_SANITIZE_NUMBER_INT, FILTER_FLAG_STRIP_HIGH);
if(!is_numeric($page_number)){die('Invalid page number!');} //incase of invalid page number
}else{
$page_number = 1;
}
$perpage = 3;
//get current starting point of records
$position = (($page_number-1) * $perpage);
//Data base join to get team names from teams data base
$getUsers = "SELECT userlogin.*, teams.TeamName FROM userlogin INNER JOIN teams ON teams.tId = userlogin.uTeam ORDER BY uId DESC LIMIT :place, :item_per_page";
$getUsersQuery = $dbConnect -> prepare($getUsers);
$getUsersQuery -> bindParam(':place', $position);
$getUsersQuery -> bindParam(':item_per_page', $perpage);
$getUsersQuery -> execute();
I tried the same SQL in phpMyAdmin it worked with out any errors I don't know why it throwing the below error when used with PHP + PDO.
Note: About the duplicate I've been searching the site using bindParam but I didn't see the duplicate and well it really didn't solve my issue the selected answer for this did any way if get marked what
Error:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '3'' at line 1' in ********\fetchUserList.php on line 27

When in emulation mode (which is on by default),PDO substitutes placeholders with actual data, instead of sending it separately.PDO treats every parameter as a string. As a result, the prepared LIMIT ?,? query becomes LIMIT '0', '3' which is invalid syntax that causes query to fail.
When you using bindParam each variables explicitly you need to set the proper param type.
you might need to turn off emulation by :
$dbConnect->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
Then
<?php
$getUsersQuery -> bindParam(':place', $position,PDO::PARAM_INT);
$getUsersQuery -> bindParam(':item_per_page', $perpage,PDO::PARAM_INT);
?>

When you are using limit / offset you need to type caste and pass as integer. Otherwise normally it take it as string
$getUsersQuery->bindParam(':place', (int) trim($position), PDO::PARAM_INT);
$getUsersQuery->bindParam(':item_per_page', (int) trim($perpage), PDO::PARAM_INT);

Related

PHP PDO error when using placeholders in the LIMIT clause of a MySQL query [duplicate]

This question already has answers here:
How can I pass an array of PDO parameters yet still specify their types?
(3 answers)
How to apply bindValue method in LIMIT clause?
(11 answers)
Closed 7 years ago.
$sql = "SELECT sql_calc_found_rows * FROM members".
" ORDER BY username LIMIT :startRow, :numRows";
try {
$st = $conn->prepare($sql);
$st->bindParam(":startRow", $startRow, PDO::PARAM_INT);
$st->bindParam(":numRows", $numRows, PDO::PARAM_INT);
$st->execute();
} catch (PDOException $e) {
die("Query failed: " . $e->getMessage());
}
Here I get error:
Query failed: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''5'' at line 1.
The LIMIT :startRow, :numRows has problem in :numRows.
I have tried both $st->bindParam and $st->bindValue, both didn't work.
I think the problem is with TBL_MEMBERS
I suppose this is a view(subselect).
So, if you have product table for example and you want to execute following statement:
select sql_calc_found_rows * from select id, code, name, slug, info from products order by code
you will receive following error:
SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select id, code, name, slug, info from products order by code' at line 1
But if you change query to:
select sql_calc_found_rows * from (select id, code, name, slug, info from products) v order by code
this will work.
To summarize,
TBL_MEMBERS is a view which should be put in parenthesis and given alias(i my example alias is 'v')
I recommend to look at the SQL query text what PDO actually produces. You can do this with help of MySQL's general query log.
Most probably, the formal types of $startRow and/or $numRows are strings, not integers, and resulting query is therefore something like LIMIT '0', '5' (syntax error) instead of LIMIT 0, 5 (correct).
The thing is, even with PDO::PARAM_INT, when the parameter's formal type is not integer (is_int returns false), PDO wraps it in quotes. So, you have to cast parameters to integers before binding them (e.g. using intval):
$st->bindParam(":startRow", intval(trim($startRow)), PDO::PARAM_INT);
$st->bindParam(":numRows", intval(trim($numRows)), PDO::PARAM_INT);
I solved it.I Type casted the :numRows placeholder.
$numRows=(int)$numRows;
$sql = 'SELECT sql_calc_found_rows * FROM ' .
TBL_MEMBERS .'ORDER BY'. $order .'LIMIT :startRow,:numRows';
try {
$st = $conn->prepare($sql);
$st->bindValue(":startRow", $startRow, PDO::PARAM_INT);
$st->bindValue(":numRows", $numRows, PDO::PARAM_INT);
$st->execute();
...
And it worked. I also noticed the ' should be use instead of ".

PDO fails to excute after first attempt, args will not be added to prepared statement in a routine?

Enviro: MySQL, PHP 5.5
I have a situation where I need to return a random result from the Database. I have tried two methods of doing this. One which returns an array of results and I randomly pick one using the array_rand($results) and the other is adding order by rand() limit1;
When I returned a list of results the execution time was recorded reported from the MySQL console like so:
602 rows in set (0.05 sec)
Query OK, 0 rows affected (49.37 sec)
This is not good. So I choose the other method which reported:
1 row in set (0.05 sec)
Query OK, 0 rows affected (0.36 sec)
The issue became when run this query for a second time, I am passing in the arg that records the previous record retrieved so I avoid duplicates
Here is my routine:
CREATE PROCEDURE `getRandomRecord`(
IN _args varchar(100)
)
BEGIN
SET #query = CONCAT('SELECT C.*, B.*
FROM C
LEFT JOIN B
ON B.id = c.Bid
where (C.Type=27 || C.Type=28 || C.Type=29)
and C.EndDate>CURRENT_TIMESTAMP() ',_args,' order by rand() limit 1;');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END//
This executes the first time without an issue, but on the PHP side when I run this a second time the call fails.
The args are being recorded like so:
$args= !empty($args) ? $args : '';
//args is empty first time
$dbHandler = new RandomRecordDatabase();
$results = $dbHandler->getRandomRecord($args);
//Do Stuff HERE
$args .= ' AND C.id!='.$results['C.id'];
$dealer_results = $dbHandler->getRandomRecord($args);
The function is like this:
public function getRandomRecord($args){
try
{
$procedure = "Call getRandomRecord(?)";
$statement = $this -> _dbh -> prepare($procedure);
$statement -> bindParam(1, $args);
$statement -> execute();
$results = $statement -> fetchAll(PDO::FETCH_ASSOC);
return $results[0];
}
catch(PDOException $e)
{
echo $e -> getMessage();
}
}
On the second call to this method, I get the following PDOException:
Warning: PDOStatement::execute(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"387 order by rand() limit 1'
Which references the line $statement -> execute();
How can I fix this error? Thank you!
UPDATE(SOLUTION):
I should of reviewed the Output of args more closely and I would of seen the error: echo $args;
In one instance I noted a mix case: " AND C.id=123 AND AND C.id=456 and C.id="111" AND C.id=789.
I modified the one case which I never noted located in a different script. This now fixes the issue.
You are missing the second quote after your variable, that is what the error message is saying. Quotes around integers are not required, nor advised, in sql.
I can not see where you are introducing that erroneous quote since you have not posted all the relevent code.

PHP MYSQL Error when not hardcoding values for Limit Clause [duplicate]

This question already has answers here:
How to apply bindValue method in LIMIT clause?
(11 answers)
Closed 7 years ago.
I get and error when trying to use values I retrieve through $_GET[], in particular the $start and $end, which I use to limit the number of results. Whenever I hardcode the values in the bottom most chuck of code, the server fetches the results no problem. Why can't I pass a parameter to Limit using PHP PDO prepared statements for MySQL?
THIS IS THE ERROR I GET
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]:
Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '20'
ORDER by orders.order_placed' at line 10' in /base/data/home/apps/s~beta/1.383539951926438776/admin/get/getorderitems.php:35
Stack trace:
#0 /base/data/home/apps/s~beta/1.383539951926438776/admin/get/getorderitems.php(35): PDOStatement->execute()
#1 {main}
thrown in /base/data/home/apps/s~beta/1.383539951926438776/admin/get/getorderitems.php on line 35
<?php
error_reporting(E_ALL); ini_set('display_errors', 1);
require('../../dbconnect.php');
$stadiums_id = $_GET['stadiums_id'];
$time = $_GET['time'];
$time_12ago = $time - 43200000; // last 12 hours
$start = 0 + $_GET['start']; // used for limit clause
$end = $start + 20;
$page = $_GET['page'];
$json;
// incoming order
if($page === "incoming"){
$statement=$con->prepare('SELECT orders.*,orders_has_items.*,
customers.id,customers.fname,customers.lname,items.*
FROM orders_has_items,items,orders,customers
WHERE orders.stadiums_id = :stadiums_id
AND orders_has_items.items_id = items.id
AND orders.id = orders_has_items.orders_id
AND customers.id = orders.customers_id
AND (orders.order_prepared IS NULL)
AND orders.create_time BETWEEN :time_12ago AND :time
ORDER by orders.order_placed
limit :start, :end');
$statement->bindParam(':stadiums_id',$stadiums_id); // bind param to variable
$statement->bindParam(':time_12ago',$time_12ago); // bind param to variable
$statement->bindParam(':time',$time); // bind param to variable
$statement->bindParam(':start',$start); // bind param to variable
$statement->bindParam(':end',$end); // bind param to variable
$statement->execute();
$results=$statement->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($results);
}
However, the code below works just fine when hard coding the Limit as seen below
$statement = $con->prepare('SELECT orders.*,orders_has_items.*,
customers.id,customers.fname,customers.lname,
items.*
from orders_has_items,items,orders,customers
where orders.stadiums_id = 1
and orders_has_items.items_id = items.id
and orders.id = orders_has_items.orders_id
and customers.id = orders.customers_id
and (orders.order_prepared IS NULL)
and orders.create_time between (1428735225152-43200000) and 1428735225152
order by orders.order_placed
limit 0,10');
$statement->execute();
$results=$statement->fetchALL(PDO::FETCH_ASSOC);
$json = json_encode($results);
By default, bindParam() binds the parameter as a string. Cast the value to an integer before passing it to the bind function, and set the datatype to PDO::PARAM_INT
$statement->bindParam(':start',(int)$start, PDO::PARAM_INT)); // bind param to variable
$statement->bindParam(':end',(int)$end, PDO::PARAM_INT)); // bind param to variable

PHP PDO Prepared Statement parameter causing error

I'm having an issue with a prepared statement with a parameter, please see below.
I apologise in advance if this turns out to be some dumb mistake.
The error:
Failed to run query (Project List) - SQLSTATE[42000]: Syntax error or access violation: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0,8'' at line 1
The code:
$limit = ($pagenum - 1) * $page_rows . "," . $page_rows;
print_r($limit); // Prints 0,8 as expected
$query = "SELECT * FROM projects INNER JOIN users ON projects.companyid = users.companyid ORDER BY projects.projectid DESC LIMIT :limit";
$query_params = array (
':limit' => $limit
);
try {
$stmt = $db->prepare($query);
$stmt->execute($query_params);
}
catch (PDOException $ex) {
die("Failed to run query (Project List)" . " - " . $ex->getMessage());
}
What I've tried so far:
Added the SQL Limit as part of the $limit string
Renamed the limit parameter/variables just in case (reserved keyword etc)
Tested the SQL query manually in SQLyog with the LIMIT 0,8 - works fine
Tested the prepared statement by directly passing the limit variable - works fine
Read all similar questions suggested, no similar issues found at least within my level of understanding.
Your $limit parameter is being escaped as one parameter, where it should be escaped as two. Your sql will currently look something like "limit '0, 8';" where it should look like "limit 0, 8";
To solve this, you should split your limit parameter into two. Edit the end of your SQL to look like:
LIMIT :offset, :limit
And your parameter list to look like:
$query_params = array (
':offset' => ($pagenum - 1) * $page_rows,
':limit' => $page_rows
);
As Mr Smith mentioned, you'll also have to add the line:
$db->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
To ensure the limit parameters are correctly handled as integers rather than strings.

MySQL Error 1064 Using LIMIT Clause

I'm having a strange issue running a query via PDO prepared statements that I just can't spot the issue. When running the query manually it works just fine. Here is the code (simplified for conciseness):
// Query Parameters
$params = array( 1, 5 );
// Get Products
$query = "SELECT * FROM mydb.Product
WHERE ProductId >= ?
AND IsApproved = 1
AND IsPublic = 1
LIMIT ?";
// Get Database Instance
$dbh = App\App::getDatabase()->getInstance();
// Prepare Query
if( $stmt = $dbh->prepare($query) )
{
if( $stmt->execute($params) )
{
// Return Records
}
}
Removing the LIMIT ? portion from the query returns all results as expected. Instead, when attempting to use the LIMIT and it passes 5 as the value, I get this error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''5'' at line 5
A dump of the PDOStatement object after preparation shows:
object(PDOStatement)[59]
public 'queryString' => string 'SELECT * FROM mydb.Product
WHERE ProductId >= ?
AND IsApproved = 1
AND IsPublic = 1
LIMIT ?'
I've tried putting a semicolon at the end of the query but that gives same error. Am I having cerebral flatulence and missing something obvious?
TL;DR; Why does my prepared statement fail when using the LIMIT clause with a 1064 error?
I think this could be a duplication of
PDO Mysql Syntax error 1064
The solution is to bind limit parameter forcing it to be an int instead of a string with a simple (int) cast.
just put (int) before your limit value

Categories