Как узнать, сколько строк возвращает запрос Perl DBI?

Я пытаюсь в основном выполнить поиск по базе данных с 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 ответов


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();

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

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

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


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

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);

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

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

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

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'.


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

как правило, вы можете полагаться только на строку подсчет после выполнения без выбора (для некоторые конкретные операции, такие как UPDATE и удалить), или после извлечения всех строки инструкции SELECT.

для выбора утверждений, как правило, нет можно знать, сколько строк будет вернулся, только забрав их всех. Некоторые драйверы вернут количество строки, которые приложение извлекло так далеко, но другие могут вернуться -1 до все строки были выбраны. Поэтому использование метод rows или $DBI:: rows с Инструкции SELECT не рекомендуется.

while ($sth->fetch) для обработки каждой строки или для особых случае запрос, который будет возвращать только ноль или одну строку,
if ($sth->fetch) {
  # do stuff for one row returned
} else {
  # do stuff for no rows returned
}

эта статья может помочь пользователям 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 имя, адрес электронной почты от пользователей, где имя, как " % " предел 10;

ВЫБЕРИТЕ FOUND_ROWS();

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

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

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