PDOでの行数


192

多くの矛盾する発言があります。PHPでPDOを使用して行数をカウントする最良の方法は何ですか?PDOを使用する前は、単にを使用しましたmysql_num_rows

fetchAll 時々大きなデータセットを扱っている可能性があるので、私は使いたくないものです。

何か提案はありますか?

回答:


264
$sql = "SELECT count(*) FROM `table` WHERE foo = ?"; 
$result = $con->prepare($sql); 
$result->execute([$bar]); 
$number_of_rows = $result->fetchColumn(); 

それを行うための最もエレガントな方法ではなく、それには追加のクエリが含まれます。

PDOにはがありPDOStatement::rowCount()、これは明らかにMySql では機能しませ。なんて痛みだ。

PDO Docから:

ほとんどのデータベースでは、PDOStatement :: rowCount()はSELECTステートメントの影響を受ける行数を返しません。代わりに、PDO :: query()を使用して、目的のSELECTステートメントと同じ述語でSELECT COUNT(*)ステートメントを発行し、次にPDOStatement :: fetchColumn()を使用して、返される行数を取得します。その後、アプリケーションは正しいアクションを実行できます。

編集:上記のコード例では準備されたステートメントを使用していますが、多くの場合、これは行をカウントするためには不要です。

$nRows = $pdo->query('select count(*) from blah')->fetchColumn(); 
echo $nRows;

これは、追加のデータベースクエリを実行することを意味します。私は彼がすでに選択クエリを実行していて、返された行数を知りたいと思っています。
nickf 2009年

1
nickfは正しいです。mysql_num_rows()は、PDOを使用すると機能しませんか?
ジェームズ


11
このアプローチを使用fetchColumn()すると、文字列 "1234"が返されます... EDITにはecho count($nRows);- count()配列関数:Pがあります。結果をfetchColumn()整数に型キャストすることもお勧めします。$count = (int) $stmt->fetchColumn()
コビー

1
@ karim79準備されていないステートメントアプローチは、実際の行数ではなく1のみを返します。準備されたステートメントは正常に動作します。問題は何ですか?
SilentAssassin 2013

86

以前に同様の質問への回答で書いたように、唯一の理由はmysql_num_rows()は、それがあなたに思われなくても、情報を提供するためにすべての行を内部的にフェッチしていたためです。

したがって、PDOでは、次のオプションがあります。

  1. MySQLのFOUND_ROWS()関数を使用します。
  2. PDOのfetchAll()関数を使用してすべての行を配列にフェッチしてから、それを使用count()します。
  3. SELECT COUNT(*)karim79が提案したように、に追加のクエリを実行します。

8
mysql_num_rows()についてさらに説明していただきありがとうございます。それは、私が自分に与えていた重要なボトルネックになっているようです。再度、感謝します。
ジェームズ

2
fetch_allは実際にはfetchAll():)です
動的

2
結果が大きい場合、オプション2はお勧めできません。
エドソン

FOUND_ROWS()はMySQLから削除されるため、これに慣れている場合は、これを使用する前にFOUND_ROWSへのリンクを確認してください。
アナタック

28

よくあることですが、この質問は地獄のように混乱しています。人々は2つの異なるタスクを念頭に置いてここに来ています:

  1. テーブルの行数を知る必要がある
  2. クエリが行を返したかどうかを知る必要がある

これは、まったく共通点がなく、同じ関数では解決できない2つのまったく異なるタスクです。皮肉なことに、どちらにも実際のPDOStatement::rowCount()関数を使用する必要はありません。

理由を見てみましょう

テーブルの行を数える

PDOを使用する前は、単に使用しましたmysql_num_rows()

あなたがすでにそれを間違ったことを意味します。使用するmysql_num_rows()か、rowCount()テーブル内の行数をカウントすることで、実際の災害サーバリソースを消費するという観点インチ データベースは、ディスクからすべての行を読み取り、データベースサーバーのメモリを消費し、このすべてのデータヒープをPHPに送信し、PHPプロセスのメモリも消費するため、サーバーにまったく理由がありません。
その上、それらをカウントするためだけに行を選択しても、単に意味がありません。count(*)クエリが代わりに実行する必要があります。データベースは、実際の行を読み取らずに1行のみを返すことなく、インデックスからレコードをカウントします。

この目的のために、受け入れられた回答で提案されたコードは公平です。

返された行数をカウントします。

2番目の使用例は、無意味なほど悲惨なものではありません。クエリがデータを返したかどうかを知る必要がある場合は、常にデータ自体があります。

行を1つだけ選択している場合は、言う。はい、フェッチした行をフラグとして使用できます。

$stmt->execute();
$row = $stmt->fetch();
if (!$row) { // here! as simple as that
    echo 'No data found';
}

多くの行を取得する必要がある場合は、を使用できますfetchAll()

fetchAll() 大規模なデータセットを扱うことがあるので、私は望まないものです

もちろん、最初のユースケースでは、2倍も悪くなります。ただし、すでに学んだように、行を選択するだけではなく、行数を数えるためだけではなく、rowCount()またはも使用しないでくださいfetchAll()

ただし、選択した行を実際に使用する場合は、を使用しても問題はありませんfetchAll()。Webアプリケーションでは、大量の行を選択しないでください。Webページで実際に使用される行のみを選択する必要があるためLIMIT、を使用する必要があります。WHERE、SQLでまたは同様の句ます。そして、そのような適度な量のデータについては、使用しても問題ありませんfetchAll()。繰り返しますが、この関数の結果を次の条件で使用します。

$stmt->execute();
$data = $stmt->fetchAll();
if (!$data) { // again, no rowCount() is needed!
    echo 'No data found';
}

そしてもちろん、それは絶対的な狂気になります、2つの上位の回答で示唆されているように、他のクエリが行を返したかどうかを通知するためだけに追加のクエリを実行ています。

大きな結果セットの行数を数える

(コンソールアプリケーションなどで)本当に大量の行を選択する必要があるようなまれなケースでは、使用されるメモリの量を減らすために、バッファなしのクエリを使用する必要があります。しかし、これは実際のケースですrowCount() は使用できない場合であり、この関数も使用できません

したがって、これは、選択した行数の詳細な見積もりを知る必要がある場合に備えて、追加のクエリを実行する必要がある場合の唯一の使用例です。


APIが検索クエリの合計結果を出力する必要がある場合に役立ちます。10行または15行しか返されませんが、合計284件の結果があることもわかります。
Andres SK

4
@andufoありません。覚えておいてください:開発者は決してこの方法でそれを行うべきではありません。検索クエリが284行すべてを返すことはありません。15を表示するために返す必要があり、284が見つかったことを通知するには、別のクエリから1行を返す必要があります。
常識

2
これは非常に良い点です-最初は直感的ではありませんが、有効です。ほとんどの人は、2つの単純なSQLクエリが方法速く大きめのものより。カウントを正当化するには、最適化できない非常に遅いクエリが必要であり、適切な結果が得られない可能性があります。指摘してくれてありがとう!
PeerBr 2014年

@あなたの常識:確かに:結果セットが非常に大きい場合、fetchAll()は悪い考えではありませんか?fetch()を使用してデータを連続的に取得する方が良いでしょう。
timmornYE 2016年

私の回答の最後の段落で述べられているとおりの@timmornYE
あなたの常識

21

これは非常に遅いですが、私は問題に遭遇し、これを行います:

function countAll($table){
   $dbh = dbConnect();
   $sql = "select * from `$table`";

   $stmt = $dbh->prepare($sql);
    try { $stmt->execute();}
    catch(PDOException $e){echo $e->getMessage();}

return $stmt->rowCount();

とてもシンプルで簡単です。:)


19
すべてのデータを選択してカウントすることは、データベースの相互作用に関する最も基本的なルールに反します。
常識

おそらく、すべての戻り値の進行状況バーを表示したいので、前もって行数を知っておく必要があります。
ジョニー

18

私はこれを使ってしまいました:

$result = $db->query($query)->fetchAll();

if (count($result) > 0) {
    foreach ($result as $row) {
        echo $row['blah'] . '<br />';
    }
} else {
    echo "<p>Nothing matched your query.</p>";
}

12

この投稿は古いですが、PDOを使用してPHPで行数を取得するのは簡単です

$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();

3
karim79の回答で引用されているドキュメントを参照してください。これは時々動作しますが、信頼できません。
2015

5

これは古い投稿ですが、代替案を探してイライラしています。特にPHPとMySQLは連携する傾向があるため、PDOにこの機能がないのは非常に残念です。

fetchColumn()が針を次の行に移動すると、その結果セットを(効果的に)使用できなくなるため、fetchColumn()の使用には不幸な欠陥があります。たとえば、次のような結果がある場合

  1. フルーツ->バナナ
  2. 果物->リンゴ
  3. フルーツ->オレンジ

fetchColumn()を使用すると、3つの果物が返されることがわかりますが、結果をループ処理すると、列が2つしかありません。fetchColumn()の価格は、検索のために結果の最初の列が失われることです。返された行数。これはずさんなコーディングにつながり、実装すると完全にエラーが発生します。

したがって、今度はfetchColumn()を使用して、まったく新しい呼び出しとMySQLクエリを実装し、新しい作業結果セットを取得する必要があります。(うまくいけば、前回のクエリ以降は変更されていません)、可能性は低いですが、発生する可能性があります。また、すべての行数検証での二重クエリのオーバーヘッド。この例の場合はどちらが小さいのでしょうか。ただし、結合クエリで200万行を解析するのは快適な代償ではありません。

私はPHPが大好きで、PHPを日常的に使用して、開発に関わるすべての人とコミュニティ全体をサポートしていますが、これが将来のリリースで解決されることを本当に望んでいます。これは、「本当に」PHP PDOに対する私の唯一の不満です。それ以外の点では、これは素晴らしいクラスです。


2

これに答えるのは、私がこれを知っていることで自分を閉じ込めたからであり、多分それは役に立つでしょう。

結果を2回フェッチできないことに注意してください。フェッチ結果を配列に保存しcount($array)、行数をで取得し、結果をで出力する必要がありますforeach。例えば:

$query = "your_query_here";
$STH = $DBH->prepare($query);
$STH->execute();
$rows = $STH->fetchAll();
//all your results is in $rows array
$STH->setFetchMode(PDO::FETCH_ASSOC);           
if (count($rows) > 0) {             
    foreach ($rows as $row) {
        //output your rows
    }                       
}

1

行数(データではない)を取得するだけの場合。準備済みステートメントでCOUNT(*)を使用すると、結果を取得して値を読み取るだけで済みます。

$sql = "SELECT count(*) FROM `table` WHERE foo = bar";
$statement = $con->prepare($sql); 
$statement->execute(); 
$count = $statement->fetch(PDO::FETCH_NUM); // Return array indexed by column number
return reset($count); // Resets array cursor and returns first value (the count)

実際にすべての行(データ)を取得して単純なカウントを実行すると、リソースの無駄になります。結果セットが大きい場合は、サーバーが窒息する可能性があります。


1

このリンクをご覧ください:http : //php.net/manual/en/pdostatement.rowcount.php SELECTステートメントでrowCount()を使用することはお勧めしません!


1

クエリ内で変数を使用するには、bindValue()またはを使用する必要がありbindParam()ます。そして、していないと変数を連結" . $variable . "

$statement = "SELECT count(account_id) FROM account
                  WHERE email = ? AND is_email_confirmed;";
$preparedStatement = $this->postgreSqlHandler->prepare($statement);
$preparedStatement->bindValue(1, $account->getEmail());
$preparedStatement->execute();
$numberRows= $preparedStatement->fetchColumn();

GL


0

PHP PDOを使用してテーブル内の行数をカウントまたは取得する方法mysqlの問題である場合、これを使用します

// count total number of rows
$query = "SELECT COUNT(*) as total_rows FROM sometable";
$stmt = $con->prepare($query);

// execute query
$stmt->execute();

// get total rows
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$total_rows = $row['total_rows'];

クレジットはMike @ codeofaninja.comに送られます


-1

最初のエントリを返すための簡単なワンライナー。これは非常に基本的なクエリに適しています。

<?php
$count = current($db->query("select count(*) from table")->fetch());
?>

参照


-1

$count = $stmt->rowCount();Oracle 11.2 を試しましたが、うまくいきませんでした。以下のようにforループを使用することにしました。

   $count =  "";
    $stmt =  $conn->prepare($sql);
    $stmt->execute();
   echo "<table border='1'>\n";
   while($row = $stmt->fetch(PDO::FETCH_OBJ)) {
        $count++;
        echo "<tr>\n";
    foreach ($row as $item) {
    echo "<td class='td2'>".($item !== null ? htmlentities($item, ENT_QUOTES):"&nbsp;")."</td>\n";
        } //foreach ends
        }// while ends
        echo "</table>\n";
       //echo " no of rows : ". oci_num_rows($stmt);
       //equivalent in pdo::prepare statement
       echo "no.of rows :".$count;

-1

特定の行が必要で、それが見つかったかどうかを知りたいストレートクエリの場合、次のようなものを使用します。

function fetchSpecificRow(&$myRecord) {
    $myRecord = array();
    $myQuery = "some sql...";
    $stmt = $this->prepare($myQuery);
    $stmt->execute(array($parm1, $parm2, ...));
    if ($myRecord = $stmt->fetch(PDO::FETCH_ASSOC)) return 0;
    return $myErrNum;
}

-1

簡単な解決策があります。PDOを使用する場合は、次のようにDBに接続します。

try {
    $handler = new PDO('mysql:host=localhost;dbname=name_of_your_db', 'your_login', 'your_password'); 
    $handler -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} 
    catch (PDOException $e) {   
    echo $e->getMessage();
}

次に、DBへのクエリは次のようになります。

$query = $handler->query("SELECT id FROM your_table WHERE ...");

そして最後に、クエリに一致する行をカウントするには、次のように記述します

$amountOfRows = $query->rowcount();

ほとんどの場合、なぜこれが-1を返すのですか?データがあっても。。
インガス

-1

fetchColumn()

レコードの数を取得する場合に使用されます[effisien]

$sql   = "SELECT COUNT(*) FROM fruit WHERE calories > 100";
$res   = $conn->query($sql);
$count = $res->fetchColumn(); // ex = 2

query()

データとレコード数を取得する場合に使用されます[オプション]

$sql = "SELECT * FROM fruit WHERE calories > 100";
$res = $conn->query($sql);

if ( $res->rowCount() > 0) {

    foreach ( $res as $row ) {
        print "Name: {$row['NAME']} <br />";
    }

}
else {
    print "No rows matched the query.";
}

PDOStatement :: rowCount


あなたは決してそれをするべきではありません。多かれ少なかれ大きなテーブルでは、すべてのサーバーのメモリを消費し、サーバーをクラッシュさせます
常識

これで、あなたの答えはダースの既存の答えを複製するだけです。
常識

-2

あなたのようにmysqlステートメントでCOUNT(*)を作成すると

$q = $db->query("SELECT COUNT(*) FROM ...");

あなたのmysqlクエリはすでに結果の数を数えていますが、なぜphpでもう一度数えるのですか?あなたのmysqlの結果を取得する

$q = $db->query("SELECT COUNT(*) as counted FROM ...");
$nb = $q->fetch(PDO::FETCH_OBJ);
$nb = $nb->counted;

そして $nbあなたは少し長い書き込みへのMySQLの文でカウントされている整数を含んでいますが、高速で実行します

編集:間違った投稿で申し訳ありませんが、いくつかの例ではカウントインを含むクエリを示していますが、mysqlの結果を使用することを提案しましたが、SQLでカウントを使用しない場合、fetchAll()は効率的であり、結果を変数に保存するとラインを失うことはありません。

$data = $dbh->query("SELECT * FROM ...");
$table = $data->fetchAll(PDO::FETCH_OBJ);

count($table)は行数を返しますが、好きな後に$row = $table[0] または結果を使用することができますforeach

foreach($table as $row){
  print $row->id;
}

1
問題は、mysqlステートメントでCOUNT(*)を行わないときにカウントを取得する方法です
常識

-2

これは、最後のクエリの「WHERE」基準に含まれる行数を取得するヘルパー関数を使用した、PDOクラスのカスタム作成拡張です。

ただし、使用するコマンドによっては、「ハンドラー」をさらに追加する必要があります。現在のところ、「FROM」または「UPDATE」を使用するクエリでのみ機能します。

class PDO_V extends PDO
{
    private $lastQuery = null;

    public function query($query)
    {
        $this->lastQuery = $query;    
        return parent::query($query);
    }
    public function getLastQueryRowCount()
    {
        $lastQuery = $this->lastQuery;
        $commandBeforeTableName = null;
        if (strpos($lastQuery, 'FROM') !== false)
            $commandBeforeTableName = 'FROM';
        if (strpos($lastQuery, 'UPDATE') !== false)
            $commandBeforeTableName = 'UPDATE';

        $after = substr($lastQuery, strpos($lastQuery, $commandBeforeTableName) + (strlen($commandBeforeTableName) + 1));
        $table = substr($after, 0, strpos($after, ' '));

        $wherePart = substr($lastQuery, strpos($lastQuery, 'WHERE'));

        $result = parent::query("SELECT COUNT(*) FROM $table " . $wherePart);
        if ($result == null)
            return 0;
        return $result->fetchColumn();
    }
}

問題は努力する価値がありません。このような番号が必要になることはまれなので、専用の内線番号は必要ありません。言うまでもなく、それは準備されたステートメントをサポートしていません-PDOを使用する唯一の理由。
常識

-2

最適なメソッドを1つの行または関数に組み合わせて、新しいクエリを自動生成させることができます。

function getRowCount($q){ 
    global $db;
    return $db->query(preg_replace('/SELECT [A-Za-z,]+ FROM /i','SELECT count(*) FROM ',$q))->fetchColumn();
}

$numRows = getRowCount($query);

この方法には最善のものはありません。返された行数を知るためだけに追加のクエリを実行しても、まったく意味がありません。
常識2016年

-2
<table>
      <thead>
           <tr>
                <th>Sn.</th>
                <th>Name</th>
           </tr>
      </thead>
      <tbody>
<?php
     $i=0;
     $statement = $db->prepare("SELECT * FROM tbl_user ORDER BY name ASC");
     $statement->execute();
     $result = $statement->fetchColumn();
     foreach($result as $row) {
        $i++;
    ?>  
      <tr>
         <td><?php echo $i; ?></td>
         <td><?php echo $row['name']; ?></td>
      </tr>
     <?php
          }
     ?>
     </tbody>
</table>

1
これは本当に悪い考えです。すべての行を選択すると、帯域幅の浪費になります。
Nafees 2017年

-2
function count_x($connect) {  
 $query = "  SELECT * FROM tbl WHERE id = '0' ";  
 $statement = $connect->prepare($query);  $statement->execute();  
 $total_rows = $statement->rowCount();  
 return $total_rows; 
}

-4

パラメータを使用しますarray(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL)。それ以外の場合は、-1を表示します 。

Usen parametro array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL)、sin ello sale -1

例:

$res1 = $mdb2->prepare("SELECT clave FROM $tb WHERE id_usuario='$username' AND activo=1 and id_tipo_usuario='4'", array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$res1->execute();

$count=$res1->rowCount();
echo $count;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.