占位符可以用于数据库名称吗?

时间:2013-10-18 11:00:55

标签: php prepared-statement bind quotes

createDb.sql

create database `:name` ;

我正在尝试此文件以创建数据库。

$createSql = file_get_contents('createDb.sql');
$stmt = $db->prepare($createSql);
$stmt->bindValue(':name', $dbName);
$stmt->execute();

问题是,我得到了数据库名称的额外引用。例如,如果$ dbName = trash,则新创建的数据库名为'trash'(不带重音,但带引号)。我可以摆脱报价吗?

1 个答案:

答案 0 :(得分:0)

哇,回来......重新考虑一下你在这里做什么。准备好的语句只允许绑定,而不是查询的静态部分 例如,PDO可能允许您使用带有占位符的预处理语句作为数据库名称,但这是因为它模拟了预处理语句,可能是...
即便如此,您还是从.sql文件中获取数据库名称...为什么要经历所有这些努力,而不是简单地在数据库服务器上运行.sql脚本?好吧,为了将来参考,这里有几个笔记(在底部,是你问题的答案):

在任何情况下,对查询的静态部分(SELECTINSERT INTO数据库名称,...)使用占位符认真会降低准备的安全性陈述给你。这是因为准备好的陈述的本质

以下是它们的工作原理(简单表示):

SELECT * from db.tbl WHERE field = ?

此字符串被发送到DB,准备好准备。在准备好语句之后,您可以使用生成的资源并将实际值发送到DB服务器以与此语句一起使用:

<stmt> + 123

通过不同协议发送,然后正确转义,并插入预处理语句以保证正确转义。
现在将它应用于你的情况,假设它甚至可以工作:

CREATE DATABASE ?

无论接下来会传递什么价值,都不应该过多地逃避,因为:

CREATE DATABASE 'foobar'

不是有效的SQL,但是:

CREATE DATABASE IF NOT EXISTS foobar

也应被接受,因为有效的SQL,在某些方面,它比你当前使用的简单的create语句更优选。 /> 在这一点上,我们甚至没有讨论 options 而不是指定(charset,collat​​ion,table specific options ...)那些呢?

真的,最好的办法是重构,重新思考,并且问自己是否想要动态创建数据库
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的数据库。

一些有趣的链接: