【问题标题】:Perl DBI: Escaping a LIKE prepared statementPerl DBI:转义 LIKE 准备好的语句
【发布时间】:2016-04-18 02:09:30
【问题描述】:

我有一个将参数绑定到 LIKE 语句的查询,如下所示:

my $sth = $dbh->prepare('SELECT foo FROM bar WHERE baz LIKE ?');
$sth->execute("%$like%");

但是,$like 是用户输入的值。因此,如果该值包含LIKE 子句(&_\)识别的任何特殊字符,则这些字符将不转义地传递给数据库并解析为通配符或转义字符。例如,如果用户输入%value,将提交的查询是:SELECT foo FROM bar WHERE baz LIKE '%%value',而不是我所期望的LIKE '%\%value

目前我正在使用正则表达式手动转义字段:

# Escape LIKE wildcard characters
$like =~ s!\\!\\\\!g;
$like =~ s!%!\\%!g;
$like =~ s!_!\\_!g;

my $sth = $dbh->prepare('SELECT foo FROM bar WHERE baz LIKE ?');
$sth->execute("%$like%");

但感觉转义是 DBI 应该能够处理的。我玩过DBI::quote,但这是为引用整个字段而设计的,所以在这种情况下,它也会引用我添加的% 符号,DBI::quote 的文档特别指出:

quote() 方法不应与“占位符和绑定”一起使用 价值观”。

有没有更好的方法来将用户提供的输入绑定到 LIKE 子句,同时转义输入并添加相关的通配符,而无需手动转义输入?

【问题讨论】:

  • $like =~ s/(?=[\\%_])/\\/g
  • @Borodin 我不知道环视断言!相当于s/([\\%_])/\\$1/g 似乎。但是我的目标是消除对正则表达式的需求,而不是重写它。
  • 这就是我没有将其作为解决方案发布的原因。 DBI 中没有任何内容可以满足您的描述
  • 我认为最好的方法是将该功能猴子修补到 DBI 中,例如 quote_like(),然后使用它。
  • @simbaque 是的,我认为这就是我要采取的方法。有点惊讶这不支持开箱即用。我想知道是否有特定于驱动程序的问题使得这很难做到。多读一点 LIKE,看来我也应该逃避 []

标签: sql perl dbi


【解决方案1】:

尽管DBI::quote 的文档说了什么,LIKE 参数有点特殊。您想要做的几乎就是您在示例中已有的内容:首先通过将quote 应用于用户提供的字符串来确保没有用户提供的元字符(您在示例中使用正则表达式),然后添加您的自己的元字符(在本例中为百分号),然后将其用作绑定参数的食物。

【讨论】:

  • DBI::quote 不会转义 LIKE 子句使用的通配符。它还返回一个带引号的字符串。因此user_input 的输入来自quote() 作为'user_input',其中_ 未转义(% 字符也未转义)并且整个输入被引用,这意味着仍然需要使用正则表达式或其他一些进行转义并在引号内添加元字符的方法。
  • 忘了提及:将带引号的字符串传递到准备好的语句中,也会导致字符串被双引号。
猜你喜欢
  • 2014-04-17
  • 2011-08-18
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多