在这里,我试图为特定查询绑定表名:
$sth = $dbh->prepare("SELECT id FROM ? WHERE service_id = ?");
和执行语句:
$sth->execute($table_name,$service_id);
它给出了一个 SQL 错误,为什么会这样?
有什么方法可以将表名绑定到特定查询?
您可以使用查询参数代替SQL 表达式 中的文字值。
即,在您通常会使用带引号的字符串文字或带引号的日期文字或数字的地方。
参数不能用于表名、列名、值列表(如 IN 子句)、SQL 关键字或 SQL 表达式。
要使表的名称动态化,您必须在准备之前将其插入到 SQL 查询字符串中:
my $table_name_lit = $dbh->quote_identifier($table_name);
my $sth = $dbh->prepare("SELECT id FROM $table_name_lit WHERE service_id = ?");
$sth->execute($service_id);
注意$table_name
不包含任何不受信任的内容。最好的方法是与$table_name
已知表名列表进行比较。换句话说,使用一个固定的表列表作为白名单。如果$table_name
与您的任何表名都不匹配,则使用默认表名。
@Karwin 响应没问题,还有关于 sql 注入问题的说明。在插入 SELECT 字符串之前,您应该检查 $table_name 是否包含有效的表名。例如,如果您使用 MySQL,您可以通过以下方式获取在 DB 中设置的当前表名:
my @tables = @{ $dbh->selectcol_arrayref('SHOW TABLES') };
并且很容易使用“grep”检查 $table_name 是否包含正确的值。也可以(并且独立于数据库)使用DBI 的表方法获取表目录。