PDO order by throws error - php

I am confused.
This is working:
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD DESC';
$stmt = $conn->prepare($sql);
$stmt->execute();
This is not:
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD :orderbydateofupload';
$stmt = $conn->prepare($sql);
$stmt->bindValue(':orderbydateofupload', $orderbydateofupload, PDO::PARAM_STR);
$stmt->execute();
I have checked and set $orderbydateofupload by $orderbydateofupload='DESC', so it's definitely not null.
I get an error to the last line ($stmt->execute()):
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 ''DESC'' at line 1' in /home/gh6534/public_html/query.php:77 Stack trace: #0 /home/gh6534/public_html/query.php(77): PDOStatement->execute() #1 {main} thrown in /home/gh6534/public_html/query.php on line 77
I also tried to use the column as parameter:
$sort = 'DATEOFUPLOAD';
$sql = 'SELECT * FROM TABLE ORDER BY :sort :orderbydateofupload';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':sort', $sort);
$stmt->bindParam(':orderbydateofupload', $orderbydateofupload);
$stmt->execute();
This does not throw an exception, but all items are queried without any sorting. What's wrong?

Try this
$orderbydateofupload = 'ASC'; //Or DESC
if($orderbydateofupload == 'DESC')
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD DESC';
else
$sql = 'SELECT * FROM TABLE'

You can't bind identifiers with PDO because prepared statements can be used only with data, but not with identifiers or syntax keywords.
So, you have to use whitelisting, as shown in the example I posted before
That's why in my own class I use identifier placeholder, which makes whole code into one line (when you need to set the order by field only):
$data = $db->getAll('SELECT * FROM TABLE ORDER BY ?n',$sort);
but with keywords whitelisting is the only choice:
$order = $db->whiteList($_GET['order'],array('ASC','DESC'),'ASC');
$data = $db->getAll("SELECT * FROM table ORDER BY ?n ?p", $sort, $order);

Related

Syntax error while executing a sql request with parameters in symfony?

I have a just simple problem I guess, I followed Symfony 4.3 documentation, and tried to do do exactly what they have done to execute a SQL request, but I get an error when passing parameters in the execute method, but I get no error while executing the same code but without passing parameters to the request.
I tried this and it worked:
$conn = $this->getDoctrine()->getManager()->getConnection();
$sql = '
SELECT * FROM question_comment WHERE question=2 LIMIT 0, 3';
$stmt = $conn->prepare($sql);
$stmt->execute();
var_dump($stmt->fetchAll());
But this does not work, I get a syntax error:
$question = $request->query->get('question');
$row = $request->query->get('row');
$question = intval($question);
$beggining = intval($row*3);
$conn = $this->getDoctrine()->getManager()->getConnection();
$sql = '
SELECT * FROM question_comment WHERE question=:question LIMIT :beggining , 3';
$stmt = $conn->prepare($sql);
$stmt->execute(['question' => $question, 'beggining' => $beggining]);
var_dump($stmt->fetchAll());
This is the error:
An exception occurred while executing ' SELECT * FROM question_comment
WHERE question= :question LIMIT :beggining , 3' with params [2, 0]:
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
Here is what I have followed, I did exactly what was there, but its not working.
I tried this solution to bind my parameters but it did not work too :
$sql = '
SELECT * FROM question_comment WHERE question=:question LIMIT :beggining , 3';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':question', $question, \PDO::PARAM_INT);
$stmt->bindParam(':beginning', $beginning, \PDO::PARAM_INT);
$stmt->execute();
And I got this :
An exception occurred while executing ' SELECT * FROM question_comment
WHERE question=:question LIMIT :beggining , 3' with params [2, null]:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
alternative way to bind parameters is using this.
$stmt->bindParam(':question', $question, PDO::PARAM_STR);
$stmt->bindParam(':beginning', $beginning, PDO::PARAM_INT);
or to make it sure you binded the $beginning parameter, cast it to int.
$stmt->bindValue(':beginning', (int)trim($beginning), PDO::PARAM_INT);
or if you want to stick on your existing code.
$stmt->execute(['question' => $question, 'beggining' => (int)trim($beggining)]);

SELECT from and DELETE the same row in one query

At the moment, I have two queries. The first selects a column from a row. The second then deletes that row. As both queries deal with the same row, I was wondering if it was possible to execute both queries in one (to reduce the amount of code).
I had a look at SELECT then immediately DELETE mysql record and tried Whatever Kitchen's answer
This was my code beforehand (which works fine):
$stmt = $con->prepare("SELECT number FROM viewings WHERE username=:user");
$stmt->bindParam(':user', $user);
$stmt->execute();
$row = $stmt->fetch();
$result = $row['number'];
$stmt = $con->prepare("DELETE FROM viewings WHERE username=:user");
$stmt->bindParam(':user', $user);
$stmt->execute();
echo $result;
This was my code after trying the answer:
$stmt = $con->prepare("DELETE FROM viewings WHERE username=:user IN (SELECT number FROM viewings WHERE username=:user LIMIT 1)");
$stmt->bindParam(':user', $user);
$stmt->execute();
$row = $stmt->fetch();
$result = $row['number'];
echo $result;
However, I receive these errors:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[42000]: Syntax error or access violation: 1235 This version
of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery''
in /home//public_html/page.php:47
Stack trace:
0 /home//public_html/page.php(47): PDOStatement->execute()
1 {main} thrown in /home//public_html/page.php on line 4
You can try using the EXISTS condition:
DELETE FROM viewings WHERE EXISTS (SELECT * FROM viewings WHERE username=:user LIMIT 1)
Source: SQL EXISTS condition

select using php mysql using where in PDO

i am trying to write a function in php and mysql to select values from PHP and mysql using PDO
function getRec($id=0)
{
($id==0?$addQuery="":$addQuery=" where id =".$id);
$statement = $dbh->prepare("select * from TCMS :name order by id");
$statement->execute(array(':name' => $addQuery));
$row = $statement->fetchAll();
return $row ;
}
i got 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 '' where id =2'
order by id' at line 1' in /Applications/XAMPP/xamppfiles/htdoc
actually what i am trying
if value (2) of ID is passed then statement will be
select * from TCMS where id=2 order by id
And if ID=0 then select statement will be
select * from TCMS order by id
i am new to PDO and not sure of exact syntax.
how to do this ?
Do this instead:
function getRec($id=0)
{
//($id==0?$addQuery="":$addQuery=" where id =".$id);
if ($id == 0)
{
$statement = $dbh->prepare("select * from TCMS order by id");
$statement->execute();
}
else
{
// Notice the SQL string has changed. Placeholder :name now properly takes the place of a SQL value.
$statement = $dbh->prepare("select * from TCMS where id = :name order by id");
$statement->execute(array(':name' => $id));
}
$row = $statement->fetchAll();
return $row ;
}
What you're doing wrong is you're attempting to bind and execute the SQL with the placeholder as arbitrary string values, which is not what the placeholder is for.
The placeholder is to be set in the place of the value (not table names or anything else) so that the value when passed in during execution will be properly handled by PDO internally for the correct escaping.
The function I wrote should help to create valid SQL.
If you need to dynamically add a WHERE clause, construct the SQL string first and prepare() it. If the condition was met to add parameters, you must then conditionally add the appropriate placeholder/value pairs to the array passed into execute().
You cannot bind a placeholder as an arbitrary SQL string.
// Array to pass into execute()
$values = array();
// Start your SQL...
$sql = "SELECT * FROM TCMS";
// Add the WHERE clause if $id is not zero
if ($id !== 0) {
$sql .= " WHERE id=:name ";
// And add the placeholder into the array
$values[':name'] = $id);
}
// add the ORDER BY clause
$sql .= " ORDER BY id";
// Prepare the statement
$statement = $dbh->prepare($sql);
$statement->execute($values);
// fetch, etc...

Why is my PDO query using LIKE & LIMIT not working?

I am making a search box feature that has this query:
$query="SELECT * FROM article WHERE title LIKE ? OR description LIKE ?";
Then in a foreach loop, I make this array:
$params[]= "%".$keyword."%";
$params[]= "%".$keyword."%";
Then I execute:
$stmt=$cxn->prepare($query);
$stmt->execute($params);
This WORKS, but...
If, after the foreach loop, I want to add " LIMIT ?,?", I do this:
$query.=" LIMIT ?, ?";
$params[]=$row_number;
$params[]=$items_per_page;
Then I execute the script, and it throws this Fatal Error:
PHP 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', '2'' at line 1' in ..../index.php:247
Stack trace:
#0 .../index.php(247): PDOStatement->execute(Array)
#1 {main}
thrown in ..../index.php on line 247
I tried to do add apostrophes around the keywords: $params= "'%".$keyword."%'";
But this didn't work.
Also, I tried the exact same query inside PHPMyAdmin and it worked.
Does anyone know why this is throwing an error?
Thanks a lot in advance.
Update:
$query="SELECT * FROM article WHERE title LIKE ? OR description LIKE ?";
$query.=" LIMIT ?, ?";
$stmt=$cxn->prepare($query);
$stmt->bindValue(1, "%".$keyword."%");
$stmt->bindValue(2, "%".$keyword."%");
$stmt->bindValue(3, $row_number, PDO::PARAM_INT);
$stmt->bindValue(4, $items_per_page, PDO::PARAM_INT);
$stmt->execute();
The reason LIKE isn't working, is because when you use bind parameters with LIKE it's treating '%value%' as a string.
You're going to have to use:
$query="SELECT * FROM article WHERE title LIKE CONCAT('%',?,'%') OR description LIKE CONCAT('%',?,'%')";
I think you need to convert the variable you have passed in your limit clause. see this ...to use near ''0', '2'' there are single quotes on the values in the LIMIT clause
try
$query.=" LIMIT ?, ?";
$params[] = intval($row_number);
$params[] = intval($items_per_page);

How to add variable values inside pdo->query

I want to upgrade my current code which is constantly sql injected with PDO.
Currently I'm stuck with using a variable inside a PDO query.
If I have two arguments like this
$rowsPerPage = 3;
// by default we show first page
$pageNum = 1;
if (isset($_GET['page'])) {
$pageNum = mysql_real_escape_string($_GET['page']);
}
$offset = ($pageNum - 1) * $rowsPerPage;
And I have query like this
$STH = $DBH->query("SELECT News.ID, LEFT(NewsText,650), Title, AID, Date, imgID," .
"DATE_FORMAT(Date, '%d.%m.%Y.') as formated_date " .
"FROM News, Categories, NewsCheck WHERE Name LIKE '%News - Block%' AND CID=Categories.ID AND JID=News.ID ".
"ORDER BY `Date` DESC LIMIT $offset, $rowsPerPage");
PDO reports an error in last line of the query ORDER BY
When I replace these line with
"ORDER BY Date DESC LIMIT3,3"); everything work.
So how to add variable values inside PDO::query ?
Updated:
Thanks to answer bellow I have updated my code like this
$STH = $DBH->prepare("SELECT News.ID, LEFT(NewsText,650), Title, AID, Date, imgID," .
"DATE_FORMAT(Date, '%d.%m.%Y.') as formated_date " .
"FROM News, Categories, NewsCheck WHERE Name LIKE '%News - Block%' AND CID=Categories.ID AND JID=News.ID ".
"ORDER BY `Date` DESC LIMIT :offset, :rowsPerPage;");
$STH->bindParam(':offset', $offset, PDO::PARAM_STR);
$STH->bindParam(':rowsPerPage', $rowsPerPage, PDO::PARAM_STR);
$STH->execute();
But error occured:
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 ''-3', '3'' at
line 1' in /pdo/test.php:42 Stack trace: #0
/pdo/test.php(42): PDOStatement->execute() #1 {main} thrown in
/pdo/test..
Second Update
Changed from PARAM_STR TO PARAM_INT like this
$STH->bindParam(':offset', $offset, PDO::PARAM_INT);
$STH->bindParam(':rowsPerPage', $rowsPerPage, PDO::PARAM_INT);
Everything works.
You want to use prepared statements and query parameters like the following:
$sth = $dbh->prepare('SELECT your_column FROM your_table WHERE column < :parameter');
$sth->bindParam(':parameter', $your_variable, PDO::PARAM_STR);
$sth->execute();
Using variables directly in your query will not protect you from SQL injections, even if you are using PDO. Parameters are the only good way to prevent them.

Categories