Почему моя переменная не интерполируется правильно, когда я создаю запрос Mysql? - PullRequest
1 голос
/ 06 марта 2009

Я пытаюсь написать выражение регулярного выражения в mysql из программы на Perl. Я хочу, чтобы запрос был такой:

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

В коде «без ошибок» обратите внимание на наличие лишних пробелов. Но если у меня есть лишние пробелы, я не получаю нужные результаты, потому что в БД нет «лишних пробелов».

Ответы [ 5 ]

7 голосов
/ 06 марта 2009

Только для полноты, это тоже работает:

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

${blah} недопустимо вне строки, но внутри интерполируемой строки это эквивалентно $blah.

Я бы подумал, что этот шаблон более распространен, чем другие ответы, хотя ... в конце концов, как еще вы хотите ввести "foo${var}bar"? Очевидно, "foo$var\bar" не работает, поскольку \b является распознанной escape-последовательностью.

6 голосов
/ 06 марта 2009

<Obligatory security moan>

Пожалуйста, используйте параметр DBI для каждого значения регулярного выражения вместо его интерполяции. Почему?

  1. Больше нет ограничений на то, какие символы разрешены. В настоящее время, если какой-либо элемент @andkeywords содержит кавычку, обратную косую черту или специальный символ регулярного выражения, все будет сломано. Например. ключевое слово "O'Reilly" приведет к ошибке базы данных.
  2. Люди не смогут создавать вредоносные ключевые слова, чтобы раскрыть информацию, которую они не должны видеть или нанести ущерб. (Представьте, что пользователь ввел "'; drop database;" в качестве ключевого слова.) Это называется атакой с использованием SQL-инъекций, и сеть распространена с плохо закодированными веб-сайтами, которые подвержены им. Не позволяй своим быть одним из них.

Даже если @andkeywords не заполняется из введенных пользователем данных, использование параметров DBI практически не требует дополнительных усилий, и ваш код будет безопасным для использования в будущих неизвестных средах.

</Obligatory security moan>

6 голосов
/ 06 марта 2009

Причина в этом случае заключается в том, что «$ andkeywords [$ i] [[:>:]]» интерпретируется как многомерный массив, а:>: не является допустимым индексом массива.

Лично я предпочитаю подход Майкрофта, но вы также можете достичь того же результата, избежав заключительной открывающей скобки, так:

$where=$where."'[[:<:]]$andkeywords[$i]\[[:>:]]' ";
2 голосов
/ 06 марта 2009

Я никогда не доверял автозамене переменных в подобных строках. Возможно, вы захотите явно выполнить объединение, которое вы хотите, следующим образом:

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

EDIT: Как указывает ephemient , общепринятый способ сделать это inline -

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

Лично я нахожу первый способ более читабельным, но, как и во всем Perl, TIMTOWTDI

0 голосов
/ 07 марта 2009

Было бы полезно, если бы вы включили текст любых сообщений об ошибках.

Что-то говорит мне, что

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

Может быть упрощено до

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

Или, возможно

$where .= join ' ', map { qq('[[:<:]]${_}[[:>:]]') } @andkeywords;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...