PerlでDBIを実行していますが、プリペアドステートメントを実行したときに、返される行数が0であるかどうかを確認する方法がわかりません。
行をフェッチするwhileループ内にカウンターを設定できることに気付きましたが、それを行うための醜い方法がないことを望んでいました。
結果セットに含まれる行数を確認するには、次の2つのオプションがあります。
select count(*)
配列またはもっと凝ったものを返すストアドプロシージャを介して魔法を導入することができますが、最終的にはこれら2つのことのいずれかが発生する必要があります。
したがって、その結果を得るための派手な方法はありません。あなたはそれらを数える必要があります:-)
ドキュメントの「警告」 (別の回答のコメントにリンクされています)は重要であり、実際の正しい回答を提供します。
一般に、行数に依存できるのは、non-SELECTの実行後(UPDATEやDELETEなどの特定の操作の場合)、またはすべてのSELECTステートメントの行。
SELECTステートメントの場合、通常、すべてをフェッチする以外に返される行数を知ることはできません。一部のドライバーは、アプリケーションがこれまでにフェッチした行数を返しますが、他のドライバーは、すべての行がフェッチされるまで-1を返す場合があります。したがって、SELECTステートメントでrowsメソッドまたは$ DBI :: rowsを使用することはお勧めしません。
少し遅れていますが、誰かがOracleを使用している場合は、ここに汗の解決策があります。
SELECT
q.*,
ROWNUM DB_ROWNUM,
(SELECT max(ROWNUM) FROM ($sql)) DB_COUNT
FROM
($sql) q
もちろん、$ sqlはクエリです。 Oraclesオプティマイザは、すべてを2回実行しないほどインテリジェントです。
これで、フェッチされたすべての行がDB_ROWNUMに現在の行番号(ページンググリッドの行番号付けに役立ちます)とDB_COUNTに行の完全な数を保持します。少なくとも1つの行をフェッチする必要があります(したがって、上記の質問に対する正確な答えではありません;))が、次に汗を使用します。
これは、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
これにより、グリッドの2番目のページの行51から100のみを実際にフェッチできますが、フェッチされたすべての行に実際の行番号(1から開始)と完全なカウント(開始と制限なし)があります。
このSQLソリューションを試して、データのSQLをcountステートメントと組み合わせてください。
tablexからnull、null、null、count(*)を選択 union tablexからfoo、bar、foobar、nullを選択
最初のステートメントにはカウントがあり、最初の行である必要があります(そうでない場合は、それを回避するために注文できます)。その後、残りのレコードセットを自由に循環できます。
CPANは言う:
[...]またはSELECTステートメントのすべての行をフェッチした後。
したがって、このようなことを行うとおそらくうまくいくでしょう:
$sth->execute() or die $sth->errstr();
my $hasref = $sth->fetchall_hashref('id');
say "There is/are " . scalar(keys(%{$hasref}) . " row(s).";
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
他の人がすでに言ったように、あなたは本当に行があるかどうかを見つけるために行を取得する必要があります。すべての行でループを開始する前に知る必要があり、期待される結果が大きくない場合は、すべての結果を配列に入れて、それを確認できます。
私は最近そのようなものを使用しました:
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";
}
}
代わりに、データベースにカウントを実行させます。行数だけが必要な場合。 2018年1月のすべての行を検索します。
$year='2018';
my $qry = "SELECT COUNT(`my_key`) FROM `mtable` WHERE `my_date` LIKE '$year-01-%';";
my ($count) = $dbc->selectrow_array($qry);
行は、データベース/ドライバーのバージョンによって間違いなく異なります。私は間違いなく、予期しない結果を処理するロジックの一部に目を向けます。
すべての行をウォークスルーする前に行がいくつあるかを知りたい場合、MySQL固有のソリューションは FOUND_ROWS() である可能性があります。
最初のクエリで、SELECT
の直後に_SQL_CALC_FOUND_ROWS
_を追加します。次に、SELECT FOUND_ROWS();
を実行すると、行数にすぐにアクセスできます。これで、すべての行をウォークスルーするか、それを実行するための最良の方法を決定できます。
クエリにLIMIT
を含めると、LIMIT
なしでクエリが返した合計数が得られることに注意してください。