2015-08-08 4 views
2

Предположим, у меня есть подпрограмма, которая соединяется с БД. Тогда я хочу сделать запрос и получить вывод и что-то сделать с ним, конечно, но что, если запрос недействителен?Perl DBI Statement Handles and Error Handling

Итак, давайте предположим, у меня есть что-то вроде:

$dbh = DBI->connect(<db>, <user>, <pass>); 
$query = 'select a, b, c from table'; 
$sth = $dbh->prepare($query); 
$sth->execute(); 

Я понимаю, что я мог бы также использовать «делать», но это будет проще для меня понять. Поэтому в сценарии, где «таблица» не имеет столбца «c», запрос был бы недопустимым, делая дескриптор $ sth недействительным и не выполнив. Правильно?

Теперь, в случае отказа как такового, что происходит с $ sth? Я не могу называть его завершение, потому что это неверно.

+0

Спасибо за все ответы. Они оба очень полезны. –

ответ

4

Так в сценарии, где «таблица» не имеет столбец «С», то запрос будет быть недействительным, делая дескриптор $ sth недействительным и не выполнив. Правильно?

Непонятно, что вы подразумеваете под «недействительным».

Некоторые водители, как и DBD :: Oracle, может отправить заявление SQL на сервер при вызове prepare, в этом случае ошибка будет обнаружена сервером и prepare потерпит неудачу, возвращая UNDEF. (Смотри также @ записку Бородина о RaiseError.)

Если водитель не отправить заявление на сервер, когда prepare вызывается тогда драйвер создает и возвращает дескриптор, который имеет строку оператора, хранящуюся в нем.

Теперь, в случае отказа как такового, что происходит с $ sth? Я не могу называть его завершение, потому что это неверно.

Опять же, неясно, что вы подразумеваете под «недействительным». (Мне очень полезно попытаться быть действительно ясно о концепциях и ситуациях, о которых я думаю. Принуждение к этому часто означает, что я нахожу ответы на свои собственные вопросы, потому что «проблема» была в словах, которые я был используя)

Таким образом, как я описал выше, либо prepare не удалось, и возвратил UNDEF (или выбросил исключение из-за RaiseError. - рекомендуется), или prepare вернулся действительный $ sth-.

Если prepare вернул undef, тогда perl выдаст исключение при попытке вызвать execute.

Если prepare вернулся действительный $ sth- то execute будет называться, заявление будет отправлено на сервер, сервер обнаружит ошибку, и execute вернет ложь (или исключение, если RaiseError установлен - рекомендуется) ,

Ни в коем случае не могу назвать $ sth "invalid". Либо у вас вообще нет $ sth, потому что подготовка завершилась неудачно, либо у вас есть $ sth, что вполне допустимо, но при выполнении ошибки.

В этом случае, если вы звоните $sth->finish, это будет работать, но, поскольку @ThisSuitIsBlackNot правильно отметил, это было бы бессмысленно. (Я должен был переименовать finish в discard_pending_rows много лет назад.)

5

Это, безусловно, лучший способ сделать что-то. Stick с prepare (что вам нужно сделать только один раз) и execute и избегать do. Вы также должны использовать вопросительные знаки как заполнители для любых параметров запроса и передать значения в вызове execute. Помимо всего прочего, этот способ обрабатывает любые необходимые цитаты значений для вас

Очень редко необходимо позвонить по телефону finish или disconnect. Вы должны оставить их, пока вы не знаете свой путь вокруг DBI лучше

Вы правы, $sth будет undef, и код ошибки и сообщение об ошибке будет возвращено $dbh->err и $dbh->errstr. Кроме того, по умолчанию установлена ​​опция PrintError, которая вызывает DBI для генерации предупреждения, если есть какие-либо ошибки при выполнении. Если вы хотите, чтобы ваша программа полностью остановилась, а затем отключите PrintError и включите RaiseError

Кроме того, это действительно так, что вы решили сделать в случае ошибки. Например, некоторые ошибки могут быть восстановлены, и в этом случае вы можете отключить какPrintError, так иRaiseError и проверить, является ли возвращаемое значение undef. Тогда вы бы выполнить некоторые действия, возможно, на основе кода ошибки, возвращенного $dbh->err

Я надеюсь, что помогает

+0

Комментарий Бородина относительно вызовов 'finish' или' disconnect' является истинным, но один из этих редких случаев укусил меня в прикладе, когда я работал с широко распространенной базой данных, поэтому теперь я всегда вызываю явное рассогласование, а не ожидаю, что это будет сделанный как часть процесса очистки Perl. –

+0

@RonBergin: Если вам нужно позвонить 'disconnect', вы должны, вероятно, также вызвать' rollback'. Используете ли вы DBD :: ODBC? – Borodin

+0

@Flimzy Хм, это полная противоположность тому, что говорят DBI: «Добавление вызовов к завершению после цикла, который извлекает все строки, является распространенной ошибкой, не делайте этого, он может маскировать неподдельные проблемы, такие как ошибки нечеткой выборки. данные были извлечены из инструкции SELECT, драйвер автоматически вызовет завершение для вас. Поэтому вы не должны вызывать его явно, за исключением случаев, когда вы знаете, что вы не извлекли все данные из дескриптора инструкции, и дескриптор не будет скоро уничтожится ». Из любопытства, можете ли вы привести пример, где вас это укусит? Возможно, это зависит от водителя ... – ThisSuitIsBlackNot

 Смежные вопросы

  • Нет связанных вопросов^_^