【发布时间】: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,看来我也应该逃避
[和]。