MySQL Error 1064 Using LIMIT Clause - php

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

Related

DWL with INNER JOIN doesn't work when LIMIT applied

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);

How to use a Select with OR in PHP - odbc_prepare Issue

I'm using Microsoft SQL Server for this
function novogetListagemClientes($conn, $User){
$stmt = odbc_prepare($conn, 'SELECT * FROM users WHERE id IN ( SELECT idCliente FROM ligacoes WHERE ligacoes.idGest = ? OR idSocioG = ? OR idFunc = ? OR idColab = ? OR idSub = ? )');
$success = odbc_execute($stmt, array($User));
while($myRow = odbc_fetch_array($stmt))
{
$rows = $myRow;
}
if(empty($rows))
{
return array();
}
return utf8_converter($rows);
}
That's my PHP Function and I want that all the '?' have the same number, how should I fill that array ?
Right now when I use this query in my page it returns nothing, but in Navicat using query builder, returns what I expect.
Error I get: Warning: odbc_execute(): SQL error: [Microsoft][ODBC SQL Server Driver]Syntax error or access violation, SQL state 37000 in SQLDescribeParameter
If switch the '?' by a number that exists, I get the true value.
Update:If I switch the ? by '.$User.' and take of the array part it works
This answer is a summary of interactions in comments on the original question.
Having checked that the ODBC connection was fine (data is returned when the relevant parameter was "hardcoded"), I surmised that the problem was that the ODBC connection wasn't coping with the "Prepare" statement. This will likely have been because the parameters to be passed were not in the outermost WHERE clause and so prior to executing the query the connection couldn't work out the overall shape of the resulting data.
To get around this, we refactored the SQL code to remove the subquery and so put the parameter in the outermost WHERE clause.
The SQL therefore changed from
SELECT *
FROM users
WHERE id IN ( SELECT idCliente
FROM ligacoes
WHERE ? in (ligacoes.idGest, idSocioG, idFunc, idColab, idSub))
to
SELECT DISTINCT u.*
FROM users u
JOIN ligacoes l ON
u.id = l.idCliente
WHERE ? in (l.idGest, l.idSocioG, l.idFunc, l.idColab, l.idSub)
And with that change the code ran without complaint.

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.

PDO syntax error for SELECT query

I have a basic query which gets all fields and exports the file but it keeps giving me an error. My code looks like this:
$array = ['users'];
foreach($array AS $i){
$file = $i.'.sql';
$stmt = $pdo->prepare("SELECT * FROM ? INTO OUTFILE ?");
try {
$stmt->execute(array($i,$file));
} catch (PDOException $e) {
$log .= $e -> getMessage().'........ \n ';
}
}
I keep getting this error how ever:
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 ''users' INTO OUTFILE 'users.sql'' at line 1.
What is the correct syntax for this ?
It(Syntax) should be the other way around
SELECT * INTO OUTFILE ? FROM ?;
See the documentation here
EDIT :
As JAL clarified, The table name cannot be passed as a parameter under a PreparedStatement. So your query should be like
SELECT * INTO OUTFILE ? FROM users;
You cannot prepare a statement where the table name is a parameter.
See Can PHP PDO Statements accept the table or column name as parameter?

Limit sql result on dbal

Im using dbal on Symfony2 to retrieve some info from my table:
$social = $conn->fetchAll('SELECT * FROM page WHERE brand_id = :brand LIMIT :start,:limit', array('brand'=>$brand, 'start'=>(int) $start, 'limit'=>(int) $limit));
Im getting an error only when I add the last part (LIMIT ....), this make me think that i cant limit the result inside the sql query but outside using some kind of command. How can i solve this?
Error:
An exception occurred while executing 'SELECT * FROM page WHERE brand_id = :brand LIMIT :start,:limit' with params {"brand":1,"start":0,"limit":4}:
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','4'' at line 1
$statement = $connection->prepare(
'SELECT ... LIMIT :limit'
);
$statement->bindValue('limit', $limit, \PDO::PARAM_INT);
$statement->execute();
$result = $statement->fetchAll();
Or you can simply use 3rd argument in the fetchAll($sql, array $params = array(), $types = array()) like that:
$social = $conn->fetchAll('SELECT * FROM page WHERE brand_id = :brand LIMIT :start,:limit', array('brand'=>$brand, 'start'=>(int) $start, 'limit'=>(int) $limit), array(\PDO::PARAM_STR, \PDO::PARAM_INT, \PDO::PARAM_INT));

Categories