PDO class - Syntax error or access violation 1064 - php

I am creating a class for connecting to my database but I keep getting an message saying my sql syntax has an error, when echoing the query i get SELECT id, username from :table where :row = :value and it seems fine with no errors.
<?php
class db{
protected $datab;
public function __construct($username, $password, $host, $dbname, $options){
try {
$this->datab = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex) {
die("Failed to connect to the database: " . $ex->getMessage());
}
$this->datab->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->datab->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
public function select($array, $table, $row, $value){
$query = "SELECT";
foreach($array as $val) {
if ($val === end($array)){
$query.= " ".$val;
}else{
$query.= " ".$val.",";
}
}
$query.=" FROM :table WHERE :row = :value";
$query_params = array(
':table' => $table,
':row' => $row,
':value' => $value
);
echo $query; // SELECT id, username from :table where :row = :value
try{
$stmt = $this->datab->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex) {
die("Failed to run query: " . $ex->getMessage());
}
$row = $stmt->fetch();
return $row;
}
}
$kit = new db("root", "", "localhost", "kit", array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$kit->select(array("id", "username"), "user", "username", "yusaf");
?>
Error message:
Failed to run query: 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 ''user' where 'username' = 'yusaf'' at line 1
EDIT
I got a downvote please comment why you have given me this.
I guess I should have mentioned this is only for learning purposes I'm not actually going to use this class in an application it's pointless.

You cannot use :table or :row as a substitution value, you have to know the name of the tables and columns.
SELECT id, username from :table where :row = :value
Should be
SELECT id, username from tablename where columnname = :value

This select() function of yours is utterly useless.
Look, you are trying to save yourself TWO words, FROM and WHERE. In exchange you are losing both flexibility and readability of SQL. Too much a price for a questionable syntax sugar. What if you need order by? join? complex where? Not to mention you are actually obfuscating plain and readable SQL. Having such a unction is a mere nonsense.
What it have to be:
public function getRow($query, $params){
$stmt = $this->datab->prepare($query);
return $stmt->execute($params)->fetch();
}
So it can be used as
$row = $kit->getRow("SELECT id, username FROM user WHERE username =?", array("yusaf"));

The substitution replaces :table and :row with quoted values, resulting in :
SELECT id, username FROM 'user' WHERE 'username' = 'yusaf'
when it should be
SELECT id, username FROM user WHERE username = 'yusaf'
Change this line :
$query.=" FROM :table WHERE :row = :value";
to :
$query.=" FROM `$table` WHERE `$row` = :value";

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

IN statment on a MySQL INNER JOIN php pdo

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)

PHP MySQL query with parameters returns sytax error because of the parameters

I have the following code in php:
$id=1;
$query = 'select id from role_perm where perm_id = :id';
if($statement =$GLOBALS["DB"]->prepare($query)){
$result =& $statement->execute(array(':id' => $id));
$t = $result->fetch_all();
But when I try to ran this code i get an 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 ':id' at line 1
I looked through a lot of questions and info on internet trying to put my statements in different ways, but I always end up with error like this, I tried ? for parameters too. How can I make it recognize parameters?
My database config:
$databaseConnection = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if ($databaseConnection->connect_error)
{
die("Database selection failed: " . $databaseConnection->connect_error);
}
// Create tables if needed.
prep_DB_content();
$GLOBALS['DB'] = $databaseConnection ;
$query = 'select id from role_perm where perm_id = ?';
if($statement = $GLOBALS["DB"]->prepare($query)){
$statement->bind_param("i", $id);
$statement->execute();
$statement->store_result();
$statement->bind_result($id_result);
while ($statement->fetch()) {
// code here
}
$statement->close();
}

PDO Prepared statement returns no Results

function db_execute($sql,$db,$array)
{
require(getcwd() . '/config/config.php');
if (empty($array))
{
$array = "";
print "Something wrong";
}
$connection = db_connect($db_host,$db_username,$db_password,$db);
$q = $connection->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$q ->execute(array($array));
if(!$q)
{
die("Error! " . $connection->errorInfo());
}
$result = $q -> fetchAll();
return $result;
}
$sql = "SELECT VALUE FROM users WHERE :id = :idnum";
$array = array(':id' => 'USER_ID', ':idnum' => '2');
printFormattedArray($array);
printFormattedArray(db_execute($sql,"user_db",$array));
For some reason I can't get any results from this function to return any results. But when I substitute the query with
$sql = "SELECT VALUE FROM users WHERE USER_ID = 2";
It gives me the required results. What am I doing wrong?
Basically, you have 2 choices.
.1. Refrain from using dynamical identifiers in your queries.
So, go for your second query.
$sql = "SELECT VALUE FROM users WHERE USER_ID = :idnum";
$array = array(':idnum' => '2');
$data = db_execute($sql, $array);
.2. If you need dynamical identifiers, you need a distinct placeholder for them as well
So, your code would be like
$sql = "SELECT VALUE FROM users WHERE ?n = ?i";
$data = db_execute($sql, 'USER_ID', 2);
Also,
never connect in the query execution function. Connect once and then use opened connection
always set your PDO to report mysql errors
add this code after connect
$connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

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