Perl DBI:转义 LIKE 准备好的语句

Ada*_*hip 5 sql perl dbi

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

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

但是,$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%");
Run Code Online (Sandbox Code Playgroud)

但感觉转义是 DBI 应该能够处理的。我尝试过使用DBI::quote,但这是为引用整个字段而设计的,因此在这种情况下它还会引用%我添加的符号,并且文档中DBI::quote特别指出:

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

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

Cal*_*ahl -3

不管文档如何DBI::quote规定,LIKE参数都是一种特殊情况。您想要做的几乎就是您的示例中已经拥有的内容:首先通过应用于用户提供的字符串来确保没有用户提供的元字符quote(您在示例中使用正则表达式执行此操作),然后添加您自己的元字符(百分号,在本例中),然后将其用作绑定参数的食物。

  • `DBI::quote` 不会转义 `LIKE` 子句使用的通配符。它还返回带引号的字符串。因此,“user_input”的输入作为“user_input”从“quote()”中出来,其中“_”未转义(“%”字符也未转义),并且整个输入被引用,这意味着仍然需要使用常规表达式或其他一些方法来进行转义并在引号内添加元字符。 (2认同)
  • 忘记提及:将带引号的字符串传递到准备好的语句中也会导致该字符串被双引号括起来。 (2认同)