我在使用这段代码时出现问题,但无法找到任何错误:
$query = "CREATE TABLE ? (? INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(?), ? VARCHAR(30), ? VARCHAR(50), ? TIMESTAMP, ? VARCHAR(50), ? DECIMAL(15, 2), ? DECIMAL(3, 2), ? VARCHAR(255))";
$array = array($table_name, $id, $id, $a_title, $c_title, $date_updated_title, $s_title, $ds_title, $ps_title, $u_title);
try {
$results = db_query($db, $query, $array); // db_query() is my PDO function to query the database. This function works fine elsewhere.
echo($table_name . " create successfully!");
} catch (PDOException $e) {
echo('<br />Could not create table "' . $table_name . '".');
return false;
error($e); //error() is my function to write errors to my log, and works fine elsewhere.
}
当我在浏览器中运行时,它会返回我捕获的异常&#39;无法创建表&#34;名称&#34;。&#39;但是,我在日志中看不到任何错误,因此我不知道它是否是语法问题,或者是什么。
当我自己进行查询,并将问号替换为实际值,并将其转储到PHPMyAdmin中时,它会创建表格。我不确定这里的问题是什么。我在另一个网站上用PDO取得了合理的成功,但我还是比较新的。有什么想法吗?
感谢您的帮助!
[编辑]自尝试使用此查询以来我已经
了"CREATE TABLE $a_title (? INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(?), ? VARCHAR(30), ? VARCHAR(50), ? TIMESTAMP, ? VARCHAR(50), ? DECIMAL(15, 2), ? DECIMAL(3, 2), ? VARCHAR(255))";
我尝试过单引号和双引号。我还从数组中删除了$ table_name变量。仍然会出现语法错误,并且不确定原因。
答案 0 :(得分:3)
来自@DCoder的评论是正确的。您可以使用查询参数 only ,通常可以放置 单个字符串文字,日期文字或数字文字。
您不能将查询参数用于:
表名
错误:SELECT * FROM ?
列名
错误:SELECT * FROM table WHERE ? = 1234
值列表
错误:SELECT * FROM table WHERE column IN (?)
虽然您可以将IN()
与参数占位符列表一起使用,但每个标量值都有一个。
SQL运算符,表达式或关键字
错误:SELECT * FROM table WHERE column ? 'value' AND ? ORDER BY column ?
对于这些情况,如果您希望动态内容成为查询的一部分,则在调用prepare()
之前,内容必须是查询的一部分。
但这意味着你要回到将变量插入到SQL查询字符串中,我们被告知它的SQL注入风险是禁止的。
解决方案是使用过滤和白名单来确保内容不包含某些不安全的内容。例如,如果它是一个动态表名,除去你想要保留的字符以外的任何字符,然后还要分隔表名,以防有人为其表命名为“table”或“order”之类的保留字。
$table = preg_replace("/[^\w]/", "", $table);
$sql = "CREATE TABLE `{$table}` ( ... )";
重新评论:
是的,列名也不受限制。正如我在顶部所说,参数仅用于标量值。
您还需要了解三种不同类型的引号的适当用法。