Как узнать, сколько строк возвращает запрос Perl DBI? - PullRequest
18 голосов
/ 14 января 2009

Я пытаюсь выполнить поиск в базе данных с помощью Perl, чтобы определить, есть ли элемент с определенным идентификатором. Этот поиск не может вернуть ни одной строки, но он также может вернуть одну.

У меня есть следующий код:

my $th = $dbh->prepare(qq{SELECT bi_exim_id FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
if ($th->fetch()->[0] != $exid) {
        ...

По сути, это пытается увидеть, был ли возвращен идентификатор, и если нет, продолжите работу со сценарием. Но он выдает ошибку ссылки на нулевой массив для вещи $th->fetch()->[0]. Как я могу просто проверить, вернулись ли строки или сейчас?

Ответы [ 7 ]

32 голосов
/ 14 января 2009

Драйвер DBD :: mysql имеет метод rows(), который может возвращать количество результатов:

$sth = $dbh->prepare( ... );
$sth->execute;
$rows = $sth->rows;

Это зависит от драйвера базы данных, поэтому он может не работать в других драйверах или работать в других драйверах иначе.

13 голосов
/ 14 января 2009
my $th = $dbh->prepare(qq{SELECT bi_exim_id FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
my $found = 0;
while ($th->fetch()) 
{
   $found = 1;
}

Ваш запрос не вернет ничего, если строка не существует, поэтому вы не можете отменить ссылку на выборку.

Обновление : возможно, вы захотите переписать это как

my $found = $th->fetch();
4 голосов
/ 14 января 2009

Почему бы вам просто не "выбрать количество (*) ..." ??

my ($got_id) = $dbh->selectrow_array("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = '$exid'");

Или помешать Маленькие столики Бобби :

my $q_exid = $dbh->quote($exid);
my ($got_id) = $dbh->selectrow_array("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = $q_exid");

Или, если вы собираетесь выполнить это много:

my $sth = $dbh->prepare("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = ?");
....save $sth (or use prepare_cached()) and then later
my ($got_id) = $dbh->selectrow_array($sth, undef, $exid);
3 голосов
/ 14 января 2009

В общем, я не уверен, почему люди так боятся исключений. Вы ловите их и идете дальше.

my $sth = prepare ...
$sth->execute;
my $result = eval { $sth->fetchrow_arrayref->[1] };

if($result){ say "OH HAI. YOU HAVE A RESULT." }
else       { say "0 row(s) returned."         }

В этом случае, однако, ответ Пола самый лучший.

Кроме того, $sth->rows обычно не работает, пока вы не загрузите все строки. Если вы хотите узнать, сколько строк соответствует, то вам нужно задать движку базы данных вопрос, на который вы хотите знать ответ; а именно select count(1) from foo where bar='baz'.

3 голосов
/ 14 января 2009

Изменить выберите, чтобы всегда что-то возвращать? Это должно работать в Sybase, не знаю о других БД.

my $th = $dbh->prepare(qq{SELECT count(*) FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
if ($th->fetch()->[0]) {
....
}
1 голос
/ 07 ноября 2012

Эта статья может помочь пользователям MySQL:

http://www.arraystudio.com/as-workshop/mysql-get-total-number-of-rows-when-using-limit.html

К счастью, начиная с MySQL 4.0.0, вы можете использовать опцию SQL_CALC_FOUND_ROWS в своем запросе, которая скажет MySQL подсчитать общее количество строк без учета предложения LIMIT. Вам все еще нужно выполнить второй запрос, чтобы получить количество строк, но это простой запрос, не такой сложный, как ваш запрос, который извлек данные.

Использование довольно просто. В ваш основной запрос вам нужно добавить опцию SQL_CALC_FOUND_ROWS сразу после SELECT, а во втором запросе вам нужно использовать функцию FOUND_ROWS (), чтобы получить общее количество строк. Запросы выглядят так:

ВЫБЕРИТЕ имя SQL_CALC_FOUND_ROWS, электронная почта от пользователей, ГДЕ имя НРАВИТСЯ 'a%' LIMIT 10;

SELECT FOUND_ROWS ();

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

Хотя это решение также требует двух запросов, оно намного быстрее, поскольку основной запрос выполняется только один раз.

Вы можете узнать больше о SQL_CALC_FOUND_ROWS и FOUND_ROWS () в документации по MySQL.

1 голос
/ 14 января 2009

Единственный надежный способ узнать, сколько строк возвращено запросом SELECT, - это извлечь их все и сосчитать. Как указано в документации DBI :

Как правило, вы можете рассчитывать только на ряд считать после выполнения без SELECT (для некоторые конкретные операции, такие как ОБНОВЛЕНИЕ и УДАЛИТЬ), или после получения всех строки оператора SELECT.

для SELECT заявления, как правило, не можно узнать, сколько строк будет вернулся, за исключением того, чтобы забрать их всех. Некоторые водители будут возвращать количество строк приложение получило так далеко, но другие могут вернуть -1, пока все строки были получены Так что использование метод строк или $ DBI :: строки с Операторы SELECT не рекомендуется.

Однако, когда вы приступаете к этому, вам почти никогда не нужно знать об этом заранее. Просто зацикливайтесь на while ($sth->fetch) для обработки каждой строки или, для особого случая запроса, который вернет только ноль или одну строку,

if ($sth->fetch) {
  # do stuff for one row returned
} else {
  # do stuff for no rows returned
}
...