我会在这里放两个例子,其中$stmt = $mysqli->prepare()
+ $stmt->bind_param()
拒绝工作,我无法看到自己的原因。
不工作:
if ($stmt = $mySQLi->prepare("DROP DATABASE ?")) {
$stmt->bind_param('s', $db_name);
$stmt->execute();
$stmt->store_result();
}
当前的解决方法:
if ($stmt = $mySQLi->prepare("DROP DATABASE $db_name")) {
//$stmt->bind_param('s', $db_name);
$stmt->execute();
$stmt->store_result();
}
不工作:
if ($stmt = $strSQLi->prepare("SELECT ? FROM Strings.texts WHERE keyName = ? LIMIT 1")) {
$stmt->bind_param('ss', strtolower($lang), strtolower("help_".$key));
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($result);
}
当前的解决方法:
if ($stmt = $strSQLi->prepare("SELECT {strtolower($lang)} FROM EVEStrings.texts WHERE keyName = ? LIMIT 1")) {
$stmt->bind_param('s', strtolower("help_".$key));
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($result);
}
任何想法为什么?
答案 0 :(得分:4)
这就是mysqli::prepare()
的工作方式。它完全写在文档中。
http://php.net/manual/en/mysqli.prepare.php
Note:
标记仅在SQL语句的某些位置是合法的。对于 例如,它们被允许在INSERT语句的VALUES()列表中 (指定行的列值),或与列进行比较 在WHERE子句中指定比较值。
但是,不允许使用标识符(例如表格或列) 名称),在选择列表中,用于命名要由a返回的列 SELECT语句,或指定二元运算符的两个操作数 例如=等号。后一种限制是必要的,因为 无法确定参数类型。不是 允许比较标记与NULL?也是NULL。一般来说, 参数仅在数据操作语言(DML)中是合法的 语句,而不是数据定义语言(DDL)语句。
这一部分主要是:不允许使用标识符(例如表格或列名称)
将您要发送到数据库引擎的参数绑定到查询的想法,并在runtine中绑定您给出的值。如果未指定表,则引擎无法构建有效语句,因此继续执行查询并且无法绑定params。
我不建议一般使用动态表名,无论它是否安全。但是,如果您真的坚持这样做,请不要让用户做出决定。在应用程序级别(即从数组中)决定{strtolower($lang)}
,而不是从用户输入。
答案 1 :(得分:0)
据我所知,从PDO(我认为它与mysqli相同)无法做到这一点。
bind_param
和bind_value()
只能绑定值,而不能绑定表名或列名。
您必须手动过滤数据,可能使用白名单方法。