PHP + mySQL:准备,bind_param不能像我期望的那样工作

时间:2014-01-09 09:35:57

标签: php mysql mysqli

我会在这里放两个例子,其中$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);
}

任何想法为什么?

2 个答案:

答案 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_parambind_value()只能绑定值,而不能绑定表名或列名。

您必须手动过滤数据,可能使用白名单方法。