Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

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

Таким образом, для получения этого результата нет способа fancypants. Вам просто нужно их подсчитать: -)

Ответ 2

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

$statement->execute($arg)

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

$statement->rows

Ответ 3

"caveat" в документации (ссылка на комментарий к другому ответу) важна и дает реальный правильный ответ:

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

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

Ответ 4

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

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

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

Теперь каждая выбранная строка содержит текущий номер строки (полезный для нумерации строк подкачки) в 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) и полный счетчик (без начала и ограничения) в каждой выбранной строке.

Ответ 5

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

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

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

Ответ 6

CPAN говорит:

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

Итак, что-то вроде этого, вероятно, будет работать:

$sth->execute() or die $sth->errstr();
my $hasref = $sth->fetchall_hashref('id');
say "There is/are " .  scalar(keys(%{$hasref}) . " row(s).";

Ответ 7

Я динамически генерировал 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

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

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

Недавно я использовал что-то вроде этого:

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";
    }
}