This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 5 years ago.
I have the following variable I want to pass to a prepare statement: $subject. It is done using PDO. Unfortunately it is being passed in with single quotes around it.Example is that i pass in maths and the query uses 'maths' instead. I have tried other answers such as bindParam, bindValue as well as specifying it is a string attribute, however I cannot get it to work. Thanks in advance if anyone knows what is wrong My code is below.
$query = "SELECT * FROM :subject;";
$sql = $connection->prepare($query);
$sql->bindParam(':subject', $subject);
try{
$sql->execute();
}catch(Exception $e){
echo $e;
}
And i get the following error:
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 ''maths'' at line 1' in D:\xampp\htdocs\acards\functions.php:18
Stack trace:
#0 D:\xampp\htdocs\acards\functions.php(18): PDOStatement->execute()
#1 D:\xampp\htdocs\acards\getMathsQuestions.php(13): Functions->getFeed('maths')
#2 {main}[]
The issue is here:
"SELECT * FROM :subject;";
bindParam is used with the parameters which are used in where clause, not in the table name.
The correct syntax is like:
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
Reference
If you want to create a "flexible" query, allowing the user to input a table name you can do so by providing some PHP logic before you get to the prepare statement like
$query="SELECT * FROM $subject";
But of course, this would open up your query to any kind of SQL-injection. But who is to say that you are not allowed to create your own "input-sanitization" on $subject before you use it in this statement? Just be aware, that this needs to be done very carefully!
Related
This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 4 years ago.
I am getting the error:
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 "mytable" at
line 1
When I call the below function using
$fields = Table::getFieldsForTable('mytable');
If I hard-code :t to my table name, then the code executes fine.
public static function getFieldsForTable ($table ) {
$sql = 'DESCRIBE :t';
try {
/**
* #var $db \PDO
*/
$db = static::getDB();
$stmt = $db->prepare($sql);
$stmt->bindValue(':t', $table, PDO::PARAM_STR);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (\PDOException $e){
echo "PDO ERROR" . $e->getMessage();
}
}
I have used the same code snippet over and over in other parts of the project, but I am failing to see what I have done wrong here.
Any help?
Simply because table or column names cannot be replaced by parameters in PDO - it's just a fundamental restriction in the way it works.
See answers to duplicate question:
Can PHP PDO Statements accept the table or column name as parameter?
https://stackoverflow.com/a/15990488/180733
is an excellent explanation.
If you are concerned about the security of accepting an arbitrary table name, consider an up-front fetch of all table names using SHOW TABLES, and then validate the proposed table name against that list, using in_array ($table, $tables).
bindValue with PDO::FETCH_ASSOC quotes the string as if it's a value you'd use for insert or select etc. Just concat the string
$sql="DESCRIBE ".$table;.
For security develop a regex that detects only valid table names, e.g. something like this
preg_match('/^[a-zA-Z]{1}[a-zA-Z_]{1,18}$/',$table);
Or match against a whitelist, e.g. array of accepted tables
This question already has answers here:
How do I create a PDO parameterized query with a LIKE statement?
(9 answers)
Closed 6 years ago.
I am using PDO with PHP to submit queries to my SQL server. I need to use the LIKE clause to check a username to ensure that it is allowed (eg; it does not contain any banned words), so I am using this SQL query...
SELECT * FROM `table` WHERE (`name` LIKE %?%);
I am then inserting the paramater with PDO later like this...
$statement->bindParam(1, $username)
When I try to run this, I get this 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 MariaDB server version for the right syntax to use near '%'dibdibs'%)' at line 1' in C:\xampp\htdocs\scripts\sql.php:57 Stack trace: #0 C:\xampp\htdocs\scripts\sql.php(57): PDOStatement->execute() #1 C:\xampp\htdocs\api\users.php(30): dibdibs\pdo->query('SELECT * FROM `...', Array) #2 {main} thrown in C:\xampp\htdocs\scripts\sql.php on line 5
The PDO code works fine for other queries, when I am using = instead of LIKE, but is is throwing the above error when I try to use the LIKE clause.
I have put my full code on Pastebin, if you need to check it. I am using GET to get data, as I am using this with AJAX (which is also working fine), but the username I have tried is 'dibdibs', which works fine in other queries.
Use This
U can use any of these two
$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->execute(array('%value%'));
while ($results = $query->fetch())
{
echo $results['column'];
}
// without loop
$query = "SELECT * FROM tbl WHERE address LIKE ?";
$params = array("%$var1%");
$stmt = $handle->prepare($query);
$stmt->execute($params);
This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 9 years ago.
I need to know can I use question marks (?) in PDO prepared statements as table name or not.
$table = $_POST['table'];
$id = $_POST['id'];
$sql = "UPDATE ? SET priority = priority + 1 WHERE id = ?";
$q = $db->prepare($sql);
$q->execute(array($table,$id));
I'm getting this error:
Warning: PDO::prepare() [pdo.prepare]: 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 '? SET priority = priority + 1 WHERE id = ?'
Aside from that simple problem, there is another one - your code smells of bad database design. In a properly planned database you would never need to receive a table name via POST request.
Most likely you are using multiple tables where you have to use only one.
You need to bind the parameters like this:
$q->bindParam(1, $table);
$q->bindParam(2, $id);
Source (see Example #2)
This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 9 years ago.
$tconn = new PDO('mysql:host='.WW_HST.';dbname='.WW_DB, WW_USR, WW_PS);
$res = $tconn->prepare('SELECT * FROM :tbl');
$res->execute(array(':tbl'=>"ugb"));
When I use this code to draw data from the 'ugb' table, I get the following error:
'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 ''ugb'' at line 1'
So it's correctly substituting :tbl for 'ugb' but whether I do a bind or just execute with an array, I always get an error. It works fine if I just do SELECT * FROM ugb though.
How can I correct this problem?
PDO does not allow you to set variables in FROM.
You only could add table name in query string.
I usually do by this way:
$allowedTables = array('first', 'second', 'third');
if(in_array($tblName, $allowedTables)) {
$$res = $tconn->prepare("SELECT * FROM $tblName");
}
I don't think that PDO will allow you to bind a parameter to the FROM statement. You could try manualy escaping the table name parameter and after that adding it to the query like this:
$table = "ugb";
$tconn = new PDO('mysql:host='.WW_HST.';dbname='.WW_DB, WW_USR, WW_PS);
$res = $tconn->prepare('SELECT * FROM '. $tconn->quote($table));
$res->execute();
Hope this helps.
I want to use a prepared statement in which the passed-in parameters are for the ORDER BY and LIMIT clauses, like so:
$sql = 'SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results';
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
'sort' => $_GET['sort'],
'dir' => $_GET['dir'],
'start' => $_GET['start'],
'results' => $_GET['results'],
)
);
But $stmt->fetchAll(PDO::FETCH_ASSOC); returns nothing.
Can someone point out what's the wrong thing I am doing? Can it be done? If not,what should I reference for a complete list of clauses where parameters can be used?
After using :
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
I got the message :
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', '10'' at line 1
So, when you use an array for execute, it consider your inputs as string which is not a good idea for LIMIT
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT);
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT);
$stmt->bindParam(':sort', $_GET['sort']);
$stmt->bindParam(':dir', $_GET['dir']);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);
Prepared statements allow the DBMS to generate a query plan for your query before actually executing the query for your supplied parameters. Changing the fields for ORDER BY requires a different query plan, because ordering you data in different ways can drastically affect how the DBMS might choose to get the data: for instance, certain indexes may help in one case but not in another. For this reason the ORDER BY fields should form part of the SQL string passed into the prepare() method, rather than being bound to the query prior to execute().
As for the LIMIT clause, it's not clear whether its parameters would affect the query plan, so these may be bound later, possibly depending upon your DBMS. According to this SO answer it should be allowed.
You can't bind a parameter to specify a language keyword or a field name - it has to be replacing a literal. Therefore, your limit values I think are fine, but your order by is not. It will be best for you to manually replace sort and dir in the string. Escape them but don't use the DB tools to do so, since they aren't string literals. Basically ensure no special characters are present.
Although this question is rather old, I think it might still be of interest. For me it worked after I
used bindParam in combination with PDO::PARAM_INT like suggested before
converted the variable content into an integer value by invoking intval()
The relevant part of the code then looks like this:
$stmt->bindParam(':start', intval($_GET['start']), PDO::PARAM_INT);
$stmt->bindParam(':number', intval($_GET['number']), PDO::PARAM_INT);
Without using intval() I also received the error 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', 10' at line 1