php 我可以在准备好的语句中参数化表名吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11312737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:14:48  来源:igfitidea点击:

Can I parameterize the table name in a prepared statement?

phpmysqlsql

提问by GK1667

I've used the mysqli_stmt_bind_param function several times. However, if I separate variables that I'm trying to protect against SQL injection I run into errors.

我已经多次使用 mysqli_stmt_bind_param 函数。但是,如果我将试图防止 SQL 注入的变量分开,我就会遇到错误。

Here's some code sample:

这是一些代码示例:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
    $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}

Is it possible to somehow replace the .$new_table.concatenation with another question mark statement, make another bind parameter statement, or add onto the existing one to protect against SQL injection?

是否有可能以某种方式.$new_table.用另一个问号语句替换串联,制作另一个绑定参数语句,或者添加到现有的语句中以防止 SQL 注入?

Like this or some form of this:

像这样或这样的某种形式:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{    
    $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}

回答by Sam Graham

Short answer to your question is "no".

对您问题的简短回答是“否”。

In the strictest sense, at the database level, prepared statements only allow parameters to be bound for "values" bits of the SQL statement.

在最严格的意义上,在数据库级别,准备好的语句只允许为 SQL 语句的“值”位绑定参数。

One way of thinking of this is "things that can be substituted at runtime execution of the statement without altering its meaning". The table name(s) is not one of those runtime values, as it determines the validity of the SQL statement itself (ie, what column names are valid) and changing it at execution time would potentially alter whether the SQL statement was valid.

一种思考方式是“可以在语句的运行时执行时替换而不改变其含义的东西”。表名不是这些运行时值之一,因为它决定了 SQL 语句本身的有效性(即,哪些列名是有效的)并且在执行时更改它可能会改变 SQL 语句是否有效。

At a slightly higher level, even in database interfaces that emulate prepared statement parameter substitution rather than actually send prepared statements to the database, such as PDO, which could conceivably allow you to use a placeholder anywhere (since the placeholder gets replaced before being sent to the database in those systems), the value of the table placeholder would be a string, and enclosed as such within the SQL sent to the database, so SELECT * FROM ?with mytableas the param would actually end up sending SELECT * FROM 'mytable'to the database, which is invalid SQL.

在稍微高一点的层面上,即使在模拟准备好的语句参数替换而不是实际将准备好的语句发送到数据库的数据库接口中,例如 PDO,可以想象它可以允许您在任何地方使用占位符(因为占位符在发送到在这些系统上的数据库),该表占位符的值是一个字符串,并将其发送到数据库的SQL内封入作为这样,所以SELECT * FROM ?mytable作为PARAM将实际上最终发送SELECT * FROM 'mytable'到数据库中,这是无效的SQL。

Your best bet is just to continue with

你最好的选择就是继续

SELECT * FROM {$mytable}

but you absolutelyshould have a white-list of tables that you check against first if that $mytableis coming from user input.

但是你绝对应该有一个表的白名单,如果它$mytable来自用户输入,你首先要检查它。

回答by Funk Forty Niner

(Late answer, consult my side note).

(迟到的答案,请参阅我的附注)。

The same rule applies when trying to create a "database".

尝试创建“数据库”时也适用相同的规则。

You cannot use a prepared statement to bind a database.

您不能使用准备好的语句来绑定数据库。

I.e.:

IE:

CREATE DATABASE IF NOT EXISTS ?

will not work. Use a safelist instead.

不管用。改用安全列表。

Side note:I added this answer (as a community wiki) because it often used to close questions with, where some people posted questions similar to this in trying to bind a databaseand not a table and/or column.

旁注:我添加了这个答案(作为社区维基),因为它经常用来结束问题,有些人在尝试绑定数据库而不是表和/或列时发布了与此类似的问题。