当我构建一个Mysql查询时,为什么我的变量没有正确插值?

时间:2009-03-05 21:53:27

标签: mysql perl

我正在尝试从Perl程序在mysql中编写正则表达式。我希望有这样的查询:

WHERE a.keywords REGEXP '[[:<:]]something[[:>:]]'

但是,在Perl中,当我进行此查询时,我在连接时遇到错误:

for($i=0;$i<$count;$i++){
    $where = $where . "'[[:<:]]$andkeywords[$i][[:>:]]' ";  #errors

这不会给我一个错误:

for($i=0;$i<$count;$i++){
    $where = $where . "'[[:<:]] $andkeywords[$i] [[:>:]]' ";  #no error

在“无错误”代码中注意有额外的空格。但是如果我有额外的空间,那么我就不会得到我想要的结果,因为在DB中没有'额外的空间'。

5 个答案:

答案 0 :(得分:7)

为了完整起见,这也有效:

for ($i = 0; $i < $count; $i++) {
    $where .= "'[[:<:]]${andkeywords[$i]}[[:>:]]' ";
}

${blah}在字符串之外无效,但在可插入字符串中,它等同于$blah

我原本以为这种模式比其他答案更常见,但是......毕竟,你还想怎么输入"foo${var}bar"?显然"foo$var\bar"不起作用,因为\b是一个公认的转义序列。

答案 1 :(得分:6)

在这种情况下的原因是“$ andkeywords [$ i] [[:&gt;:]]”被解释为多维数组,并且:&gt;:不是有效的数组索引。

我个人更喜欢Mykroft的方法,但你也可以通过逃避最终的开口括号来实现相同的结果:

$where=$where."'[[:<:]]$andkeywords[$i]\[[:>:]]' ";

答案 2 :(得分:6)

<Obligatory security moan>

为每个正则表达式值使用DBI参数,而不是对其进行插值。为什么呢?

  1. 对于允许使用哪些字符不再有任何限制。目前,如果@andkeywords的任何元素包含引号,反斜杠或特殊正则表达式字符,则事情将会中断。例如。关键字"O'Reilly"将导致数据库错误。
  2. 人们将无法构建恶意关键词来揭示他们不应该看到或造成严重破坏的信息。 (想象一下,如果用户输入"'; drop database;"作为关键字。)这称为SQL注入攻击,而网络 rife 包含编码较差的网站,这些网站容易受到攻击。不要让你的人成为其中之一。
  3. 即使没有从用户输入的数据中填充@andkeywords,也几乎不需要额外的努力来使用DBI参数,并且您的代码可以安全地用于未来的未知环境。

    </Obligatory security moan>

答案 3 :(得分:2)

我从来没有真正相信像这样的字符串中的变量的自动重放。您可能需要考虑明确地执行您想要的连接:

for($i=0;$i<$count;$i++){
    $where=$where . "'[[:<:]]" . $andkeywords[$i] . "[[:>:]]' ";

修改 正如ephemient所指出的那样,普遍接受的内联方式是

for($i=0;$i<$count;$i++){
    $where=$where . "'[[:<:]]${andkeywords[$i]}[[:>:]]' ";

就我个人而言,我发现第一种方式更具可读性,但与所有事物一样,TIMTOWTDI

答案 4 :(得分:0)

如果您要包含任何错误消息的文本,将会很有帮助。

东西告诉我

for($i=0;$i<$count;$i++){
    $where=$where . "'[[:<:]]" . $andkeywords[$i] . "[[:>:]]' ";
    ...
}

可以简化为

for (@andkeywords) {
    $where .= qq('[[:<:]]${_}[[:>]]' );
    ...
}

或者

$where .= join ' ', map { qq('[[:<:]]${_}[[:>:]]') } @andkeywords;