PDO Exception when DESCRIBE table [duplicate] - php

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

Related

Variable being passed with single quotes using PHP and MYSQL [duplicate]

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!

PHP - MySQLi - Insert with SELECT at the end not working

I have this function in PHP. I am trying to insert (if it's necessary) and then get the app_id from the table.
private function addApp($bundle_identifier,$os_id) {
$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL;
//Insert or update app details
if ($stmt = $this->db->prepare("INSERT IGNORE INTO app (app_identifier,os_id) VALUES (?,?); SELECT app_id FROM app WHERE app_identifier = ? AND os_id = ?")){
$stmt->bind_param("ssss", $bundle_identifier,$os_id,$bundle_identifier,$os_id);
$stmt->execute();
$stmt->bind_result($app_id);
if (!isset($app_id)) {
echo "is set";
$app_id=$stmt->insert_id;
}
}
if($this->db->commit()){
return $app_id;
}
return 0;
}
The issue here is that stmt is always false with the error:
Uncaught exception 'mysqli_sql_exception' with message '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 'SELECT app_id
FROM app WHERE app_identifier = ? AND os_id = ?' at line 1'
The weird thing is that this query works fine in my SQL.
Is that a limitation of mysqli?
According to http://php.net/manual/en/mysqli.prepare.php :
The query must consist of a single SQL statement.
Which basically answers your question. You have to use two db calls for two queries. Or use something like http://php.net/manual/en/mysqli.multi-query.php
The below is kept for information only as it refers PDO, while the question is about mysqli. It's generally useful though.
I think the reason for this working in mysql, but not in mysqli is that the latter supports prepared statements natively, while the former uses emulation. As your expression contains two queries, all bound parameters are given by driver to the first query (out of which is uses two and discards the other two). The second query then gets no parameters and therefore question marks are syntax errors. With prepared statements emulation PHP actually substitutes question marks with the properly escaped values and so forms two valid queries.
You can enable emulation using $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true), however, this may slightly affect performance.
See also http://www.php.net/manual/en/pdo.setattribute.php

PHP Insert Into Statement always fails [duplicate]

This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 7 years ago.
I am making myself a website and I am onto the backend administration section, I'm currently stuck on submitting the details from a form into my database, however I keep getting the same error over and over again no matter what, which is:
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 'Change) VALUES ('Connor', >'Connor')' at line 1
This is the code which is giving me the error (it connects perfectly to the database):
$query = "INSERT INTO changes (DevName,Change) VALUES ('$dev', '$changed')";
$a = mysql_query($query);
It keeps saying syntax error when I have been looking at other code, and it shows the exact same thing as the code that I have (except the variables of course).
That's cause Change is a reserve word in MySQL.. You will have to escape it using backtique.
The following works fine, otherwise explosions:
create table changes
( DevName varchar(100),
`Change` varchar(100)
);
insert changes(DevName,`Change`) values ('1','2');
Please don't use mysql_* methods because they are deprecated in PHP5.5 and removed in PHP7. Instead of that you should use PDO or mysqli
$sth = $dbh->prepare('INSERT INTO changes ('DevName', 'Change') VALUES (:dev, :changed)');
$sth->bindParam(':dev', $dev, PDO::PARAM_STR);
$sth->bindParam(':changed', $changed, PDO::PARAM_BOOL);
$sth->execute();
For more details about PDO visit site http://php.net/manual/en/book.pdo.php

Using question mark instead of table name in PDO prepared statements [duplicate]

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)

Prepare synatax error SQLSTATE[42000] [duplicate]

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.

Categories