哇,备份...重新考虑你在这里做什么。准备好的语句只允许绑定值,而不是查询的静态部分。
例如,PDO 可能确实允许您使用带有占位符的预准备语句作为数据库名称,但那是因为它正在模拟预准备语句,可能......
即使如此,您还是从 .sql 文件中获取数据库名称。 .. 为什么要付出所有这些努力,而不是首先在您的数据库服务器上运行 .sql 脚本?嗯,为了将来参考,这里有几个注释(在底部,是你问题的答案):
在任何情况下,为查询的那些静态部分使用占位符(SELECT
、INSERT INTO
数据库名称、...)会严重降低准备好的语句给您的安全性。这是因为准备好的语句的本质。
以下是它们的工作方式(简单表示):
SELECT * from db.tbl WHERE field = ?
该字符串被发送到数据库,准备就绪。准备好语句后,您可以使用生成的资源并将实际值发送到数据库服务器以与该语句一起使用:
<stmt> + 123
这些值通过不同的协议发送,然后正确转义,并插入到预处理语句中以保证正确转义。
现在将其应用于您的案例,假设它甚至可以工作:
CREATE DATABASE ?
无论接下来要传递什么值,都不应该过多地转义,因为:
CREATE DATABASE 'foobar'
不是有效的 SQL,但随后:
CREATE DATABASE IF NOT EXISTS foobar
也应该被接受,因为这是有效的 SQL,并且在某些方面,它比您当前使用的简单 create 语句更可取。
在这一点上,我们甚至还没有讨论可以指定的选项(字符集、排序规则、特定于表的选项......)那些呢?
确实,最好的办法是重构、重新思考并问自己是否甚至想要动态创建数据库。
9/10,甚至 99.99999% 的时间,您最好创建表格。即使这样,您也可能不想将变量用于表名,除非它们至少经过适当的清理。
但顺便说一句,如果你想继续你正在做的事情,并且没有那些引号,你应该这样做:
$dbName = str_replace(' ', '_', strtolower(trim($dbName)));//remove spaces, trim
$dbName = preg_replace('/^\d*|[^a-z0-9]/','',$dbName);//remove leading digits and non alf-num chars
$db->query('CREATE DATABASE '.$dbName);
通过输入123foo% bar 3
,这将创建一个名为foo_bar3
.
几个有趣的链接: