私はPerlでDBIを実行していますが、プリペアドステートメントを実行すると、返される行数が0であるかどうかを判断する方法がわかりません。
行をフェッチするwhileループ内にカウンターを設定できることに気付きましたが、それを行うための醜い方法がないことを望んでいました。
ドキュメントの「警告」(別の回答へのコメントにリンクされている)は重要であり、実際の正しい答えを提供します。
一般に、行数に依存できるのは、SELECT以外の実行後(UPDATEやDELETEなどの特定の操作の場合)、またはSELECTステートメントのすべての行をフェッチした後のみです。
SELECTステートメントの場合、通常、すべてをフェッチする以外に、返される行数を知ることはできません。一部のドライバーは、アプリケーションがこれまでにフェッチした行数を返しますが、他のドライバーは、すべての行がフェッチされるまで-1を返す場合があります。したがって、SELECTステートメントでrowsメソッドまたは$ DBI::rowsを使用することはお勧めしません。
結果セットに含まれる行数を確認するには、次の2つのオプションがあります。
select count(*)
配列またはより凝ったものを返すストアドプロシージャを介していくつかの魔法を導入することができますが、最終的にはこれら2つのことのいずれかが発生する必要があります。
したがって、その結果を得るための派手な方法はありません。あなたはそれらを数える必要があります:-)
少し遅れていますが、誰かがORACLEを使用している場合は、ここにスウェットソリューションがあります。
SELECT
q.*,
ROWNUM DB_ROWNUM,
(SELECT max(ROWNUM) FROM ($sql)) DB_COUNT
FROM
($sql) q
もちろん、$sqlはクエリです。Oracleのオプティマイザは、すべてを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(*)を選択します 連合 tablexからfoo、bar、foobar、nullを選択します
最初のステートメントにはカウントがあり、最初の行である必要があります(そうでない場合は、それを回避するために注文できます)。その後、残りのレコードセットを自由に循環できます。
CPANは言う:
[...]またはSELECTステートメントのすべての行をフェッチした後。
したがって、このようなことを行うとおそらくうまくいくでしょう:
$sth->execute or die $sth->errstr;
say (scalar keys %{$sth->fetchall_hashref('id')}) . ' row(s).';
SQLを動的に生成して実行しました。select count(*)
クエリを再生成する必要があるため、私にとってはオプションではないようです。次のアプローチは私にはきれいに見えました。$h->execute()
ただし、行データを取得するには、もう一度sを発行する必要があります。
$h->execute() or die "ERROR: Couldn't execute SQL statement";
$rowcount_ref = $h->fetchall_arrayref(0);
$rowcount = scalar (@{$rowcount_ref});
--Shaakunthala
行は、データベース/ドライバのバージョンによって間違いなく異なります。私は間違いなく、予期しない結果を処理するロジックの一部に目を向けます。
すべての行をウォークスルーする前に行がいくつあるかを知りたい場合は、MySQL固有のソリューションはFOUND_ROWS()である可能性があります。
SQL_CALC_FOUND_ROWS
最初のクエリで、の直後に追加しますSELECT
。次にSELECT FOUND_ROWS();
、を実行すると、すぐに行数にアクセスできます。これで、すべての行をウォークスルーするか、それを実行するための最良の方法を決定できます。
LIMIT
クエリに含めると、クエリが。なしで返された総数が得られることに注意してくださいLIMIT
。
他の人がすでに言ったように、あなたは本当に行があるかどうかを調べるために行を取得する必要があります。すべての行でループを開始する前に知る必要があり、期待される結果が大きくない場合は、すべての結果を配列に入れて、それを確認できます。
私は最近そのようなものを使用しました:
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);
これは、参照を使用して非常に簡単に実現できると思います。以下のコードブローは、カウント後に行をフェッチするためにクエリを再実行する必要がないことを示しています。
my $sth = $dbh->prepare("SELECT NAME, LOCATION
FROM Employees");
$sth->execute() or die $DBI::errstr;
$nrows = $sth->fetchall_arrayref() ;
print "Number of rows found :" . @$nrows . "\n";
#while (my @row = $sth->fetchrow_array()) {
foreach my $row(@{$nrows}) {
my ($name, $location ) = @$row;
print " Name = $name, Location = $location\n";
}
これがここでの質問を満足させたことを願っています。