IN statment on a MySQL INNER JOIN php pdo - php

i have an array i want to implode, then pass to a query and spit out all the matching values, but all i get is a 1064 violation, im sure its some silly syntax i've missed.
$filmImplode = implode("','", $filmList);
$query = "
SELECT
watch.film_id,
films.film_api_id
FROM
watch
INNER JOIN films ON films.film_id = watch.film_id
WHERE
films.film_api_id IN ('$filmImplode')
AND watch.user_id = :user_id";
$query_params = array(':user_id' => 1);
try {
$stmt = $db->prepare($query);
$getWatched = $stmt->execute($query_params);
} catch (PDOException $ex) {
echo 'something went wrong' . $ex->getMessage();
}
$getWatched = $stmt->fetchAll();
The SQL error reads
something went wrongSQLSTATE[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
'item0','item1','item2','itme3','item4' at line 3

I see 2 potential issues:
you may have film names with quote that will mess up your query. Escape them.
you have a space in your : user_id parameter
Try this:
array_walk($filmList, function(&$film){
$film = $db->quote($film);
});
$filmImplode = implode(",", $filmList);
$query = "
SELECT
watch.film_id,
films.film_api_id
FROM
watch
INNER JOIN films ON films.film_id = watch.film_id
WHERE
films.film_api_id IN ($filmImplode)
AND watch.user_id = :user_id";
$query_params = array(':user_id' => 1);
try {
$stmt = $db->prepare($query);
$getWatched = $stmt->execute($query_params);
} catch (PDOException $ex) {
echo 'something went wrong' . $ex->getMessage();
}
$getWatched = $stmt->fetchAll();
An even better approach, as suggested here, would be to build dynamically the IN condition writing the placeholders and to then bind the parameters in the prepare method.

The problem seems to be around filmImplode.
Are your film_api_ids int? If not, you should make sure they are passed as string constants in your SQL.
WHERE films.film_api_id IN ('XXX-123-XX', 'YYY-456-YY')
Instead of
WHERE films.film_api_id IN (XXX-123-XX, YYY-456-YY)
Also, those single quotes look shady, try without single quotes if all filmIds are integer.
WHERE films.film_api_id IN ($filmImplode)

Related

Postgresql not binding in prepared statement for SELECT in PHP

<?php
try
{
global $db;
$user = 'postgres';
$password = '*****'; //For security
$db = new PDO('pgsql:host=localhost;dbname=dnd', $user, $password);
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch (PDOException $ex)
{
echo 'ERROR!!: ' . $ex->getMessage();
die();
}
$table = htmlspecialchars($_REQUEST['table']);
$idNum = htmlspecialchars($_REQUEST['id']);
try {
//$query = "SELECT * FROM $table WHERE id = $idNum"; This works
//$query = "SELECT * FROM $table WHERE id = :number"; This works
$query = "SELECT * FROM :tableName WHERE id = :number";
$statement = $db->prepare($query);
$statement->bindValue(":tableName", $table, PDO::PARAM_STR);
$statement->bindValue(":number", $idNum, PDO::PARAM_INT);
$statement->execute();
$info = $statement->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $excep) {
echo "Opps: " . $excep->getMessage();
die();
}
Okay I'm going crazy here trying to get this to work.
I have a database set up that I need to query from. I receive the query from an AJAX request with the name of the table I want and the id for the item. When I try to query with both variables, the binding does not occur in the prepared statement and instead I get this error code
Opps: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "$1" LINE 1: SELECT * FROM $1 WHERE id = 1 ^
When I have just the straight PHP variables it works fine so I know it can work, but when I want to bind multiple it seems to fail and give a variable number as above.
I can also get it to work if I simply have one of the variables bound, such as the second commented out query in the code - this only works tho if I have the variable I want at the end and not if I wanted to lookup the table spot. (I.E.
$query = "SELECT * FROM :tableName WHERE id = $idNum"; does not work)
I need to cleanse the variables to prevent SQL injection, but I can't do that without binding the variables in a prepared statement. Any help would be appreciated!
According to the PHP manual you can't bind a tablename. As you mentioned it, you can replace it by a variable, but you can't replace it with a placeholder.
So the only solution that will work for you is the query you have above:
$query = "SELECT * FROM $table WHERE id = :number"
This will be what you're looking for. If you want to make it safe for injection, you have to find another way. (Regex for example).
Ref: http://us3.php.net/manual/en/book.pdo.php#69304

Syntax error or access violation: 1064 don t get it?

the text i get in the browser:
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' WHERE 'username'= 'cAASDASD'' at line 1
maybe it is in this part?
otherwise i have no more 'WHERE'.
public function user_exists($username) {
$query = $this->db->prepare("SELECT COUNT('id') FROM 'users' WHERE 'username'= ?");
$query->bindValue(1, $username);
try {
$query->execute();
$rows = $query->fetchColumn();
if($rows == 1) {
return true;
}
else {
return false;
}
}
catch (PDOException $e) {
die($e->getMessage());
}
}
in the real code you run there are 'single quotes' are used around table name, not backticks as in one posted here
And you have no idea where this error occurred because of the wrong way of using exceptions. So, as soon as you remove that useless try-catch, as soon you will be informed of the exact place where error occurred
The error doesn't relate to the snippet of PHP code you're showing. Going by the error message, it looks like you're using something like:
$query = $this->db->prepare("SELECT * FROM 'users' WHERE 'username' = ?");
Here, the table and column are both using single quotes rather than back ticks. What you want is:
$query = $this->db->prepare("SELECT * FROM `users` WHERE `username` = ?");

Insert a PHP variable in a MySql SQL Statement

I'm trying to do like this using PHP and MySql PDO:
//PHP Variables
$msg_a = 'Too Little';
$msg_b = 'Score OK';
$sql = "select if(stdScore >= stdRequired, $msg_a, $msg_b) from scores;"
$results = $conn->prepare($Sql);
$results->execute();
AFAIK this should have worked. But I keep getting the following error message:
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 '
How can something like this be done?
$results = $conn->prepare($Sql);
---------------------------------------------^ (capital S)
it should be with a lowercase s
$results = $conn->prepare($sql);
because you have:
$sql = "select if(stdScore >= stdRequired, $msg_a, $msg_b)
from scores";(//semicolon after double quotes)
---^
with a lowercase s ($sql)
Can you try this,
$sql = "select if(stdScore >= stdRequired, $msg_a, $msg_b) from scores";
$results = $conn->prepare($sql);
Have you tried it this way ?
$sql = "select if(stdScore >= stdRequired, "'.$msg_a.'", "'.$msg_b.'") from scores;"
Since you're already using PDO don't do query string interpolation leaving your code vulnerable to sql injections and value escaping problems. Instead use prepared statements properly.
Your code could've looked something like
$msg_a = 'Too Little';
$msg_b = 'Score OK';
// use placeholders in a query string
$sql = "SELECT IF(stdScore >= stdRequired, :msg_a, :msg_b) msg FROM scores";
// prepare the statement
$query = $conn->prepare($sql);
// bind parameters and execute the query
$query->execute(array(':msg_a' => $msg_a, ':msg_b' => $msg_b));
// fetch the resultset
$rows = $query->fetchall(PDO::FETCH_ASSOC);

Why do I get error SQLSTATE42000 in PHP/MySQL

I am working on a project using PHP and MySQL.
I have an HTML table that has 3 columns into which I load data from my "Tasks" table in MySQL. The columns are: id, taskname and a button column that when clicked on, takes you to the Edit page for the relevant task (I pass the task id as a URL) - http://localhost/tasks/?edit&id=3
The problem arises when I try to load the details about this task. This is the code:
if(isset($_GET["id"]))
{
try
{
$sql = "SELECT * FROM tasks WHERE id = :id";
$result = $pdo->prepare($sql);
$result->bindValue(":id", $_GET["id"]);
$result = $pdo->query($sql);
}
catch(PDOException $e)
{
$error = "Error trying to load task - " . $e->getMessage();
include "error.php";
exit();
}
foreach($result as $task)
{
$tasktext = $task["task"];
$id = $task["id"];
}
$title = "Edit task";
$action = "edittask";
$button = "Edit task";
include 'form.php';
exit();
resetParameters();
I get the following error:
Error trying to load task - 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 ':id' at line 1
When I replace the WHERE id = :id with WHERE id = 3 for example it works and loads the details about the task however I simply cannot get it to load the details about the task I have clicked on in the previous screen.
Could anyone spot anything wrong with my code/logic and point me in the right direction please?
You need to use execute() not query() when using prepared query's:
execute() PDOStatement::execute — Executes a prepared statement.
query() PDO::query — Executes an SQL statement.
Try:
<?php
try
{
$sql = "SELECT * FROM tasks WHERE id = :id";
$query = $pdo->prepare($sql);
$query->bindValue(":id", $_GET["id"]);
$query->execute();
$result = $query->fetchAll(PDO::FETCH_ASSOC);
}
catch(PDOException $e)
{
$error = "Error trying to load task - " . $e->getMessage();
include "error.php";
exit();
}
?>

What is wrong with the SQL?

I'm trying to use PDO, so i got this together:
So, $_GET['word'] = "Jimi Hendrix" and $_GET['cat'] = "music".
$now = htmlentities(rawurldecode($_GET['word']));
$cat = htmlentities($_GET['cat']);
$dsn = 'mysql:dbname=DATABASE;host=localhost';
$user = "USER";
$password = "PASS";
# connect to the database
try {
$DBH = new PDO($dsn, $user, $password);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
# the data to select
$data = array($cat, $now);
$STH = $DBH->prepare("SELECT id, name FROM ? WHERE name LIKE ?");
$STH->execute($data);
$result = $STH->fetchAll();
}
catch(PDOException $e) {
echo "Uh-Oh, something wen't wrong. Please try again later.";
file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}
echo "<pre>";
print_r($result);
echo "</pre>";
But the code above is returning:
SQLSTATE[42000]: Syntax error or access violation: 1064 You Have a Syntax error in your SQL near ''music' WHERE name LIKE 'Jimi Hendrix'' on line 1
You can't pass the table name as a parameter for the query. You'd need to construct/execute a dynamic SQL string.
It is probably because you are trying to insert the table name as a parameter. You may be able to do this as a stored procedure if necessary.
The category is converted into a string and when the query is prepared it is converted into:
SELECT id, name FROM 'cat' WHERE name 'music'
The table shouldn't be a string, what you can do is:
# the data to select
$data = array($now);
$STH = $DBH->prepare("SELECT id, name FROM $cat WHERE name LIKE ?");
$STH->execute($data);
As others have said, you cannot parameterize a table name with PDO (Or any other SQL interface that I know of).
You used to be able to find table naming conventions here:
http://www.mysql.com/doc/en/Legal_names.html
But it's been Larry Ellisowned.
I'd recommend finding a regex to validate MySQL table names and using that. A basic regex would be:
/[A-Za-z][A-Za-z0-9_]*/
But that wont account for reserved words.

Categories