Как я могу получить количество строк в DBI без выполнения двух отдельных вызовов для обработки? - PullRequest
12 голосов
/ 13 мая 2009

Я использую DBI в Perl и не могу понять, как, когда я запускаю подготовленный оператор, я могу выяснить, равно ли число возвращаемых строк 0.

Я понимаю, что могу установить счетчик внутри цикла while, где я получаю свои строки, но я надеялся, что был менее уродливый способ сделать это.

Ответы [ 11 ]

19 голосов
/ 13 мая 2009

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

$statement->execute($arg)

Вы можете получить доступ к количеству строк через

$statement->rows
11 голосов
/ 13 мая 2009

«Предостережение» в документации (ссылка на которое содержится в комментарии к другому ответу) важно и дает реальный, правильный ответ:

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

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

9 голосов
/ 14 мая 2009

Чтобы узнать, сколько строк в наборе результатов, у вас есть ровно две опции:

  1. select count(*)
  2. Перебрать набор результатов и подсчитать строки.

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

Так что нет никакого необычного способа получить такой результат. Вы просто должны посчитать их: -)

4 голосов
/ 17 апреля 2013

Уже немного поздно, но если кто-то использует ORACLE, то приходит потовое решение:

SELECT
  q.*,
  ROWNUM DB_ROWNUM,
  (SELECT max(ROWNUM) FROM ($sql)) DB_COUNT
FROM
  ($sql) q

$ sql, конечно, ваш запрос. Оптимизатор оракулов достаточно умен, чтобы не выполнять все дважды.

Теперь каждая извлеченная строка содержит текущий номер строки (полезно для нумерации строк сетки подкачки) в DB_ROWNUM и полное количество строк в DB_COUNT. Вам по-прежнему нужно выбрать хотя бы одну строку (так что это не совсем ответ на вопрос выше;)), но использование потом идет следующим образом:

Это также очень простой способ запуска и ограничения в Oracle и получения полного числа строк:

SELECT * FROM (
  SELECT /*+ FIRST_ROWS($limit) */
    q.*,
    ROWNUM DB_ROWNUM,
    (SELECT max(ROWNUM) FROM ($sql)) DB_COUNT
  FROM
    ($sql) q
  WHERE
    ROWNUM <= $limit
)
WHERE
  DB_ROWNUM > $start

При этом вы можете выбрать только строки 51-100 для второй страницы в вашей сетке, но при этом иметь реальный номер строки (начиная с 1) и полный счет (без начала и ограничения) в каждой выбранной строке.

2 голосов
/ 23 марта 2014

CPAN говорит:

[...] или после извлечения всех строк инструкции SELECT.

То, что вы делаете, похоже, сработает:

$sth->execute() or die $sth->errstr();
my $hasref = $sth->fetchall_hashref('id');
say "There is/are " .  scalar(keys(%{$hasref}) . " row(s).";
2 голосов
/ 05 января 2012

попробуйте это решение SQL, объедините ваш SQL для данных с оператором подсчета.

select null, null, null, count(*) from tablex
union
select foo, bar, foobar, null from tablex

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

1 голос
/ 07 февраля 2013

Я динамически сгенерировал SQL и выполняю его. Для меня select count(*) не представляется возможным, потому что мне нужно заново сгенерировать запрос. Следующий подход выглядел чистым для меня. Но вам нужно еще раз ввести s $h->execute() для получения данных строки.

$h->execute() or die "ERROR: Couldn't execute SQL statement";
$rowcount_ref = $h->fetchall_arrayref(0);
$rowcount = scalar (@{$rowcount_ref});

- Shaakunthala

0 голосов
/ 09 августа 2018

Я бы просто позволил базе данных делать подсчет вместо этого. Если все, что вы хотите, это количество строк. Найти все строки за январь 2018 года.

$year='2018';
my $qry = "SELECT COUNT(`my_key`) FROM `mtable` WHERE `my_date` LIKE '$year-01-%';";
my ($count) = $dbc->selectrow_array($qry);
0 голосов
/ 06 декабря 2017

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

Я недавно использовал что-то подобное:

foreach my $table ( qw(ACTOR DIRECTOR PRODUCER WRITER) ) {
    my $sth = $dbi->prepare(qq{SELECT * FROM $table WHERE DESCRIPTION != TRIM(DESCRIPTION)})
        or die $dbi->errstr;
    $sth->execute or die $sth->errstr;

    my @rows = @{ $sth->fetchall_arrayref() };

    next unless @rows;

    foreach my $row (@rows) {
        print join(", ", map {qq("$_")} @{$row}), "\n";
    }
}
0 голосов
/ 11 августа 2017

Если вы хотите узнать, сколько строк есть, прежде чем проходить все из них, решение для MySQL может быть следующим: FOUND_ROWS () .

В свой первый запрос добавьте SQL_CALC_FOUND_ROWS сразу после SELECT. Затем выполните SELECT FOUND_ROWS();, и вы сразу получите доступ к количеству строк. Теперь вы можете решить, хотите ли вы пройтись по всем строкам или лучше всего это сделать.

Обратите внимание, что наличие LIMIT в запросе даст вам общее количество запросов, которые были бы возвращены без LIMIT.

...