我在寻找最近3个小时的答案,我不知道该怎么做。这是代码:
function get_data($tablename)
{
try
{
$conn = $this->conn();
$stmt = $conn->prepare("SELECT * FROM :tablename ORDER BY id");
$stmt->bindParam(':tablename', $tablename, PDO::PARAM_STR);
$stmt->execute();
return $stmt;
}
catch (Exception $e)
{
echo "ERROR:" . $e->getMessage();
}
}
这是错误:
错误:SQLSTATE [42000]:语法错误或访问冲突:1064 SQL语法中有错误;检查与您的MySQL服务器版本相对应的手册,以便在第1行的''products'ORDER BY id'附近使用正确的语法
我做错了什么?...
答案 0 :(得分:2)
如上所述here(感谢@YourCommonSense),您不能将参数用作表名;如果你这样做,将会发生以下两件事之一:
这就是问题所在。至于解决方案:
如果您对设计感到满意(或无法改变设计),您需要一个丑陋不安全的黑客,如下所示:
function get_data($tablename, $acceptable_tablenames = array()) {
/* $acceptable_tablenames is an array of strings, containing
* table names that you'll accept. It's your job to make sure
* these are safe; this is a much easier task than arbitrary
* sanitization.
*/
if (array_search($tablename, $acceptable_tablenames, true) === FALSE) {
throw new Exception("Invalid table name"); /* Improve me! */
} else {
/* your try/catch block with PDO stuff in it goes here
* make sure to actually return the data
*/
}
}
将其称为get_data($table, array("my_datatable_1", "my_datatable_2"))
。感谢我在回答灵感时所链接的帖子。
答案 1 :(得分:0)
PDO使用单引号('
)转义参数。需要使用反引号(`)来转义MySql表名。
在提供的示例中,tablename参数Products正在转义单引号。这是PDO引擎的一个安全功能,可以防止注入攻击。
假设$tablename
的值在应用程序上下文中有意义(例如,验证当前用户可以看到指定表中的所有数据。)。
以下方法可行:
function get_data($tablename)
{
try
{
$conn = $this->conn();
$stmt = $conn->prepare("SELECT * FROM `" . str_replace("`","``",$tablename) . "` ORDER BY id;");
$stmt->execute();
return $stmt;
}
catch (Exception $e)
{
echo "ERROR:" . $e->getMessage();
}
}