这里我试图为特定查询绑定表名:
$sth = $dbh->prepare("SELECT id FROM ? WHERE service_id = ?");
和执行语句:
$sth->execute($table_name,$service_id);
它给出了SQL错误,为什么会这样?
有没有办法将表名绑定到特定查询?
答案 0 :(得分:8)
您可以在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
与您的任何表名都不匹配,请使用默认表名。
答案 1 :(得分:3)
@Karwin响应没问题,关于sql注入问题的说明也是如此。在插入SELECT字符串之前,应检查$ table_name是否包含有效的表名。例如,如果使用MySQL,则可以使用以下命令获取在DB中设置的当前表名:
my @tables = @{ $dbh->selectcol_arrayref('SHOW TABLES') };
使用“grep”检查$ table_name是否包含正确的值很容易。此外,可以(和数据库无关)获取带有tables method of DBI的表目录。