2016-09-22 2 views
-1

Может кто-нибудь сказать мне, что случилось с этим запросом:у меня есть проблемы запроса

$query = "INSERT INTO ideas_tbl (idea, desc) VALUES ('$idea', '$desc')"; 
+0

wats ошибка? –

+1

'desc' - ключевое слово SQL (подумайте' ORDER BY'). Я голосую, чтобы закрыть такие вопросы, как простые типографские ошибки. –

+0

Он уязвим для [SQL injection attack] (https://en.wikipedia.org/wiki/Sql_injection_attack). Чтобы избежать этого и множество других проблем, используйте [параметры привязки] (https://metacpan.org/pod/DBI#Placeholders-and-Bind-Values). – Schwern

ответ

0

As @GordonLinoff mentioned in a comment проблема desc является SQL ключевое слово. Используемый таким образом SQL-сервер может рассматривать его как часть синтаксиса, а не имя столбца, и запутываться. Список ключевых слов SQL отличается от сервера к серверу, но here's a good baseline list from SQLite.

Существует два решения. Сначала нужно указать столбец ". В некоторых базах данных будет использоваться ` (MySQL) или [] (Microsoft), но " - это стандарт SQL. Несоответствующие базы данных могут быть сконфигурированы для поддержки стандарта ", например MySQL has ANSI_QUOTES.

Это также означает отказ от цитаты или мой предпочтительный вариант с использованием balanced quoting operators (при условии, что это Perl).

$query = qq[INSERT INTO ideas_tbl (idea, "desc") VALUES ('$idea', '$desc')]; 

мне не нравится этот вариант, потому что это означает, что каждый раз, когда этот столбец используется вы должны помнить, чтобы процитировать его. Лучший вариант - переименовать столбец в нечто другое, как «описание».


Теперь давайте поговорим о вашем дыре в безопасности. Поскольку вы поставили переменные прямо в строку запроса, ваш код уязвим для SQL Injection Attack. Это одно из самых распространенных явлений безопасности. Если $idea или $desc поступают с пользовательского ввода, умный человек может создавать некоторые данные, которые могут выпрыгивать из кавычек и интерпретироваться как больше SQL. Это также может произойти невинно, например, если $desc = "Our prices can't be beat!"

Вы можете делать всевозможные цитаты, но чтобы полностью победить его, и немного ускорить свой код, используйте prepared statements and bind parameters. Здесь я предполагаю, что это Perl, используя DBI.

my $sth = $dbh->prepare(q{ 
    INSERT INTO ideas_tbl 
      (idea, description) 
    VALUES (?, ? ) 
}; 
$sth->execute($idea, $desc); 

Другим преимуществом является то, что вы можете повторно использовать этот дескриптор инструкции, избегая накладных расходов на его перекомпиляцию. Например, если вы перебираете список идей.

for my $idea (@ideas) { 
    $sth->execute($idea->{idea}, $idea->{desc}); 
} 

Наконец, я подозреваю, что вы не получите сообщение об ошибке, когда ваш запрос не удалось из-за чего вы задаете вопрос. К сожалению, DBI не обрабатывает ошибки SQL как ошибки по умолчанию. Если вы забудете or die после каждого запроса, вы не получите сообщение об ошибке.

Чтобы избежать этого, включите RaiseError либо при подключении (лучше всего), либо после него.

my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1 }); 

or 

$dbh->RaiseError(1); 

Теперь все неудавшиеся запросы вызовут ошибку. Не нужно помнить, чтобы поставить or die "Something failed because $DBI::errstr" на каждый запрос.