Каков предпочтительный способ вставки строк, которые могут содержать как одинарные, так и двойные кавычки (", '), в MySql с помощью DBI? Например, $val1
и $val2
могут содержать кавычки:
my $dbh = DBI->connect( ... );
my $sql = "insert into tbl_name(col_one,col_two) values($val1, $val2)";
my $sth = $dbh->prepare($sql);
$sth->execute();
Используйте связанный запрос, используя
$sth = $dbh->prepare("insert into tbl_name(col_one,col_two) values(?,?)");
$sth->execute($val1, $val2);
Если вы используете связанные переменные, для вас все экранируется.
Обновление: изменен мой пример, чтобы он соответствовал примеру, отредактированному в вопросе.
Обновление: я не знаю, почему Адам удалил свой ответ, но если по какой-то причине вы не можете использовать связанные переменные (также известные как «заполнители»), вы также можете использовать $dbh->quote($var)
для переменной. Например:
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote(q("Don't"));
Заполнители также обладают очень полезным свойством защиты от атак с использованием SQL-инъекций. Используй их. Всегда. Никогда помещает данные, предоставленные пользователем, непосредственно в ваши запросы.
«executeUpdate» должно быть просто «execute» (и это в любом случае вставка, а не обновление :-) Кстати, Адам, quote () тоже хороший ответ, бывают случаи, когда это предпочтительнее заполнителей. Но да, никогда не используйте данные, предоставленные пользователем, непосредственно в своих запросах и не подвергайтесь гневу Bobby Tables.
@ Адам, ты не должен был удалять свой ответ. Это была обычная информация.
Используйте метод quote()
. Он будет грамотно обрабатывать расценки за вас. Пример из документы:
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote("Don't");
Немного изменены, чтобы иметь оба типа котировок:
$sql = sprintf "SELECT foo FROM bar WHERE baz = %s",
$dbh->quote(q("Don't"));
Не помню, почему я удалил этот ответ. Так что я восстанавливаю его. :)
Одно небольшое предостережение по поводу связанных заполнителей: я создаю довольно большой скрипт загрузки базы данных, который изначально использовал связанные заполнители в более старой версии Perl / DBI и обнаружил утечку памяти в реализации заполнителя, поэтому, если вы ищете при использовании их в постоянном процессе / демоне или в контексте большого объема вы можете убедиться, что размер процесса не становится проблемой. Переход к построению строк запроса с использованием метода quote () устранил для меня проблему.
Интересно, хотя, возможно, именно тот факт, что объекты дескриптора операторов были созданы явно, вызывал проблемы с управлением памятью в Perl, то есть фрагментацию памяти. Perl действительно не очень хорош для восстановления освобожденной памяти ...
Заполнители DBI потрясающие. Они светятся, когда вам нужно выполнить один и тот же запрос в цикле. Учти это:
my $dbh = DBI->connect(...);
my $name_pairs = get_csv_data("data.csv");
my $sth = $dbh->prepare("INSERT INTO t1 (first_name, last_name) VALUES (?,?)");
for my $pair (@$name_pairs) {
unless ($sth->execute(@$pair)) {
warn($sth->errstr);
}
}
В этом случае иметь подготовленный дескриптор оператора, э-э, удобно.
Однако, исключая такого рода случаи с замкнутым циклом, мне нравится видеть фактический оператор, который был отправлен на сервер. Здесь я сильно полагаюсь на цитату и откровенно спринт.
# Here, I am confident about the hash keys, less so about the values
$sql = sprintf("INSERT INTO t1 (%s) VALUES (%s)",
join(",", keys(%hash)),
join("," map { $dbh->quote($_) } values(%hash))
);
$sth = $dbh->prepare($sql);
unless ($sth->execute) {
warn($sth->{Statement});
}
Обратите внимание, что вы должны установить RaiseError => 0 в $ dbh, чтобы вы могли видеть сбой SQL, но это очень помогло мне в прошлом.
Ваше здоровье.
Непонятно, почему этот точный и вежливый ответ был отвергнут, но что-то не так.
Обычно это называется использованием заполнителей.