简体   繁体   English

PHP + mySQL:准备工作,bind_param无法正常运行

[英]PHP + mySQL: Prepare, bind_param not working as I'd expect it

I'll put here two examples where $stmt = $mysqli->prepare() + $stmt->bind_param() deny to work and I can't see for myself why. 我在这里举两个例子,其中$stmt = $mysqli->prepare() + $stmt->bind_param()拒绝工作,我自己看不出为什么。 Not working: 无法运作:

if ($stmt = $mySQLi->prepare("DROP DATABASE ?")) {
        $stmt->bind_param('s', $db_name);
        $stmt->execute(); 
        $stmt->store_result();
}

Current working workaround: 当前的解决方法:

 if ($stmt = $mySQLi->prepare("DROP DATABASE $db_name")) {
        //$stmt->bind_param('s', $db_name);
        $stmt->execute(); 
        $stmt->store_result();
 }

Not working: 无法运作:

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);
}

Current working workaround: 当前的解决方法:

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);
}

Any idea WHY? 知道为什么吗?

This is how mysqli::prepare() is working. 这就是mysqli::prepare()的工作方式。 It's completely written in the documentation. 它完全写在文档中。

http://php.net/manual/en/mysqli.prepare.php http://php.net/manual/zh/mysqli.prepare.php

Note:

The markers are legal only in certain places in SQL statements. 标记仅在SQL语句中的某些位置合法。 For example, they are allowed in the VALUES() list of an INSERT statement (to specify column values for a row), or in a comparison with a column in a WHERE clause to specify a comparison value. 例如,在INSERT语句的VALUES()列表中(允许为一行指定列值),或者在与WHERE子句中的列进行比较以指定比较值时,允许使用它们。

However, they are not allowed for identifiers (such as table or column names), in the select list that names the columns to be returned by a SELECT statement, or to specify both operands of a binary operator such as the = equal sign. 但是,不允许在标识符(例如表名或列名),选择列表中使用标识符(由SELECT语句返回)或指定二进制运算符的两个操作数(例如=等号)时使用标识符。 The latter restriction is necessary because it would be impossible to determine the parameter type. 后一种限制是必要的,因为将无法确定参数类型。 It's not allowed to compare marker with NULL by ? 不允许将标记与NULL比较? IS NULL too. 也为NULL。 In general, parameters are legal only in Data Manipulation Language (DML) statements, and not in Data Definition Language (DDL) statements. 通常,参数仅在数据操作语言(DML)语句中有效,而在数据定义语言(DDL)语句中无效。

This part mostly: they are not allowed for identifiers (such as table or column names) 这部分主要是: 不允许使用标识符(例如表名或列名)

The idea of binding parameters it that you are sending to the database engine the query and in the runtine it binds the values you have given. 绑定参数的想法是将查询发送给数据库引擎,在运行程序中它将绑定您给定的值。 If the table is not specified, the engine cannot build a valid statement, thus to continue executing the query and bind params is impossible. 如果未指定表,则引擎无法构建有效的语句,因此无法继续执行查询并绑定参数。

I would not suggest to use dynamic table names in general, whether it is safe or not. 无论安全与否,我都不建议一般使用动态表名。 However, if you really insist to do it, do not let the user to decide that. 但是,如果您确实坚持要这样做,则不要让用户自行决定。 Decide the {strtolower($lang)} on application level (ie from an array), not from the user input. 在应用程序级别(即从数组)而不是从用户输入确定{strtolower($lang)}

As far as I know from PDO (and I think it's the same for mysqli) this can't be done. 据我从PDO得知(我认为mysqli也是一样),这是无法完成的。

bind_param and bind_value() can only bind values, not table or column names. bind_parambind_value()只能绑定值,不能绑定表或列名。

You have to filter your data manually, maybe with a whitelist method. 您必须手动过滤数据,也许使用白名单方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM