Hitung baris dengan PDO

192

Ada banyak pernyataan yang saling bertentangan di sekitar. Apa cara terbaik untuk menghitung jumlah menggunakan PDO di PHP? Sebelum menggunakan PDO, saya hanya cukup digunakan mysql_num_rows.

fetchAll adalah sesuatu yang tidak saya inginkan karena saya terkadang berurusan dengan dataset besar, jadi tidak baik untuk saya gunakan.

Apakah Anda punya saran?

James
sumber

Jawaban:

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

Bukan cara yang paling elegan untuk melakukannya, ditambah lagi itu melibatkan permintaan tambahan.

Memiliki PDO PDOStatement::rowCount(), yang tampaknya tidak berfungsi di MySql. Sungguh menyakitkan.

Dari Dokumen PDO:

Untuk sebagian besar database, PDOStatement :: rowCount () tidak mengembalikan jumlah baris yang dipengaruhi oleh pernyataan SELECT. Alih-alih, gunakan PDO :: query () untuk mengeluarkan pernyataan SELECT COUNT (*) dengan predikat yang sama dengan pernyataan SELECT yang Anda inginkan, lalu gunakan PDOStatement :: fetchColumn () untuk mengambil jumlah baris yang akan dikembalikan. Aplikasi Anda kemudian dapat melakukan tindakan yang benar.

EDIT: Contoh kode di atas menggunakan pernyataan yang disiapkan, yang dalam banyak kasus mungkin tidak perlu untuk tujuan menghitung baris, jadi:

$nRows = $pdo->query('select count(*) from blah')->fetchColumn(); 
echo $nRows;
karim79
sumber
ini berarti melakukan permintaan basis data tambahan. Saya berasumsi dia telah melakukan kueri pemilihan dan sekarang ingin tahu berapa banyak baris yang dikembalikan.
nickf
1
nickf benar. mysql_num_rows () tidak akan berfungsi saat menggunakan PDO, bukan?
James
Benar, rupanya ada PDOStatement :: rowCount () tapi itu tidak berfungsi di MySql
#
11
Menggunakan pendekatan ini, fetchColumn()mengembalikan string "1234" ... EDIT Anda echo count($nRows);- count()adalah fungsi array: P. Saya juga merekomendasikan tipe casting hasil dari fetchColumn()ke integer. $count = (int) $stmt->fetchColumn()
Cobby
1
@ karim79 Pendekatan pernyataan tidak siap hanya mengembalikan 1 bukan jumlah baris yang sebenarnya. Pernyataan yang disiapkan bekerja dengan baik. Apa yang bisa menjadi masalah?
SilentAssassin
86

Seperti yang saya tulis sebelumnya dalam jawaban untuk pertanyaan yang serupa , satu-satunya alasan yang mysql_num_rows()berhasil adalah karena secara internal mengambil semua baris untuk memberi Anda informasi itu, bahkan jika itu tidak seperti itu bagi Anda.

Jadi dalam PDO, opsi Anda adalah:

  1. Gunakan FOUND_ROWS()fungsi MySQL .
  2. Gunakan fetchAll()fungsi PDO untuk mengambil semua baris ke dalam array, lalu gunakan count()di atasnya.
  3. Lakukan permintaan tambahan SELECT COUNT(*), seperti yang disarankan karim79.
Chad Birch
sumber
8
Terima kasih telah mendidik saya lebih lanjut tentang mysql_num_rows () sepertinya itu mungkin menjadi hambatan penting yang saya berikan pada diri saya sendiri. Terima kasih lagi.
James
2
fetch_all sebenarnya adalah fetchAll () :)
dinamis
2
Opsi 2 tidak disarankan jika hasilnya besar.
Edson Horacio Junior
FOUND_ROWS () akan dihapus dari MySQL jadi silakan periksa tautannya ke FOUND_ROWS sebelum menggunakan ini jika Anda sudah terbiasa dengan ini.
anatak
28

Seperti yang sering terjadi, pertanyaan ini membingungkan sekali. Orang-orang datang ke sini memiliki dua tugas berbeda :

  1. Mereka perlu tahu berapa banyak baris dalam tabel
  2. Mereka perlu tahu apakah kueri mengembalikan baris apa pun

Itu dua tugas yang sangat berbeda yang tidak memiliki kesamaan dan tidak dapat diselesaikan dengan fungsi yang sama. Ironisnya, untuk keduanyaPDOStatement::rowCount() fungsi yang sebenarnya harus digunakan.

Mari kita lihat mengapa

Menghitung baris dalam tabel

Sebelum menggunakan PDO saya hanya cukup digunakan mysql_num_rows().

Berarti kamu sudah melakukan kesalahan. Menggunakan mysql_num_rows()atau rowCount()menghitung jumlah baris dalam tabel adalah bencana nyata dalam hal mengkonsumsi sumber daya server. Database harus membaca semua baris dari disk, menggunakan memori pada server database, kemudian mengirim semua tumpukan data ini ke PHP, menggunakan memori proses PHP juga, membebani server Anda dengan mutlak tanpa alasan.
Selain itu, memilih baris hanya untuk menghitungnya tidak masuk akal. Sebuah count(*)permintaan harus dijalankan sebagai gantinya. Basis data akan menghitung catatan dari indeks, tanpa membaca baris yang sebenarnya dan kemudian hanya satu baris yang dikembalikan.

Untuk tujuan ini, kode yang disarankan dalam jawaban yang diterima adalah adil.

Menghitung jumlah baris yang dikembalikan.

Kasus penggunaan kedua tidak seburuk yang tidak ada gunanya: jika Anda perlu tahu apakah permintaan Anda mengembalikan data, Anda selalu memiliki data itu sendiri!

Katakanlah, jika Anda hanya memilih satu baris. Baiklah, Anda dapat menggunakan baris yang diambil sebagai bendera:

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

Jika Anda perlu mendapatkan banyak baris, maka Anda dapat menggunakannya fetchAll().

fetchAll() adalah sesuatu yang tidak saya inginkan karena saya terkadang berurusan dengan dataset besar

Ya tentu saja, untuk kasus penggunaan pertama akan dua kali lebih buruk. Tapi seperti yang sudah kita pelajari, jangan pilih baris hanya untuk menghitungnya, baik dengan rowCount()maupunfetchAll() .

Tetapi jika Anda benar-benar akan menggunakan baris yang dipilih, tidak ada yang salah dalam menggunakan fetchAll(). Ingatlah bahwa dalam aplikasi web Anda tidak boleh memilih jumlah baris yang besar. Hanya baris yang akan benar-benar digunakan pada halaman web yang harus dipilih, maka Anda harus menggunakan LIMIT, WHEREatau klausa yang sama dalam SQL Anda. Dan untuk jumlah data yang moderat tidak apa-apa untuk digunakan fetchAll(). Dan sekali lagi, cukup gunakan hasil fungsi ini dalam kondisi:

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

Dan tentu saja akan menjadi kegilaan mutlak untuk menjalankan kueri tambahan hanya untuk mengetahui apakah kueri Anda yang lain mengembalikan baris, seperti yang disarankan dalam dua jawaban teratas.

Menghitung jumlah baris dalam hasil yang besar

Dalam kasus yang jarang terjadi ketika Anda perlu memilih jumlah baris yang sangat besar (dalam aplikasi konsol misalnya), Anda harus menggunakan kueri yang tidak dikacaukan , untuk mengurangi jumlah memori yang digunakan. Tetapi ini adalah kasus aktual ketika rowCount() tidak akan tersedia , sehingga tidak ada gunanya untuk fungsi ini juga.

Oleh karena itu, itulah satu-satunya kasus penggunaan ketika Anda mungkin perlu menjalankan kueri tambahan, jika Anda perlu mengetahui perkiraan dekat untuk jumlah baris yang dipilih.

Akal Sehat Anda
sumber
ini berguna jika API perlu mencetak hasil total dari permintaan pencarian. itu hanya akan memberi Anda 10 atau 15 baris kembali, tetapi juga akan memberi tahu Anda bahwa ada 284 hasil total.
Andres SK
4
@ andufo Tidak. Harap diingat: pengembang tidak boleh melakukannya dengan cara ini. Permintaan pencarian tidak boleh mengembalikan semua 284 baris. 15 harus dikembalikan untuk ditampilkan dan satu baris dari kueri terpisah untuk memberi tahu bahwa 284 ditemukan.
Akal Sehat Anda
2
Ini adalah poin yang sangat bagus - awalnya tidak intuitif, tetapi valid. Kebanyakan orang lupa bahwa dua query SQL sederhana cara lebih cepat dari satu sedikit lebih besar. Untuk membenarkan penghitungan apa pun, Anda harus memiliki kueri yang sangat lambat yang tidak dapat dioptimalkan dan akan menghasilkan beberapa hasil. Terima kasih telah menunjukkannya!
PeerBr
@Anda Common Sense: Hanya du pastikan: tidak akan mengambil semua () menjadi ide yang buruk jika resultset sangat besar? Bukankah lebih baik menggunakan fetch () untuk mendapatkan data secara berurutan.
timmornYE
@timmYYE itulah yang dikatakan di paragraf terakhir jawaban saya
Your Common Sense
21

Ini sangat terlambat, tetapi saya mengalami masalah dan saya melakukan ini:

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();

Ini sangat sederhana, dan mudah. :)

Dan
sumber
19
Memilih semua data hanya untuk menghitungnya, bertentangan dengan aturan paling dasar dari interaksi basis data.
Akal Sehat Anda
Mungkin Anda ingin memiliki bilah kemajuan untuk semua nilai yang dikembalikan, jadi Anda perlu tahu jumlah baris di muka.
Jonny
18

Saya akhirnya menggunakan ini:

$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>";
}
Eric Warnke
sumber
12

Posting ini sudah tua tetapi Mendapatkan jumlah baris dalam php dengan PDO sederhana

$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
TenTen Peter
sumber
3
Lihat dokumentasi yang dikutip dalam jawaban karim79. Ini terkadang berhasil tetapi tidak dapat diandalkan.
octern
5

Ini adalah pos lama, tetapi frustrasi mencari alternatif. Sangat disayangkan bahwa PDO tidak memiliki fitur ini, terutama karena PHP dan MySQL cenderung berjalan seiring.

Ada cacat yang disayangkan dalam menggunakan fetchColumn () karena Anda tidak dapat lagi menggunakan set hasil tersebut (secara efektif) karena fetchColumn () memindahkan jarum ke baris berikutnya. Jadi misalnya, jika Anda memiliki hasil yang mirip dengan

  1. Buah-> Pisang
  2. Buah-> Apple
  3. Buah-> Jeruk

Jika Anda menggunakan fetchColumn () Anda dapat menemukan bahwa ada 3 buah yang dikembalikan, tetapi jika Anda sekarang mengulang hasilnya, Anda hanya memiliki dua kolom, Harga fetchColumn () adalah hilangnya kolom hasil pertama hanya untuk menemukan berapa banyak baris yang dikembalikan. Itu mengarah ke pengkodean yang ceroboh, dan benar-benar kesalahan hasil yang ditunggangi jika diterapkan.

Jadi sekarang, menggunakan fetchColumn () Anda harus mengimplementasikan dan panggilan baru dan permintaan MySQL hanya untuk mendapatkan set hasil kerja yang baru. (yang semoga tidak berubah sejak permintaan terakhir Anda), saya tahu, tidak mungkin, tetapi itu bisa terjadi. Juga, overhead kueri ganda pada semua validasi jumlah baris. Yang untuk contoh ini kecil, tetapi menguraikan 2 juta baris pada kueri yang digabungkan, bukan harga yang menyenangkan untuk dibayar.

Saya suka PHP dan mendukung semua orang yang terlibat dalam pengembangannya serta masyarakat luas menggunakan PHP setiap hari, tetapi sangat berharap ini dibahas dalam rilis mendatang. Ini 'benar-benar' satu-satunya keluhan saya dengan PHP PDO, yang sebaliknya adalah kelas yang hebat.

Eric
sumber
2

Menjawab ini karena saya sudah terjebak dengan itu sekarang mengetahui ini dan mungkin itu akan berguna.

Ingatlah bahwa Anda tidak dapat mengambil hasil dua kali. Anda harus menyimpan hasil pengambilan ke dalam array, dapatkan jumlah baris count($array), dan hasil dengan foreach. Sebagai contoh:

$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
    }                       
}
csharp newbie
sumber
1

Jika Anda hanya ingin mendapatkan hitungan baris (bukan data) yaitu. menggunakan COUNT (*) dalam pernyataan yang disiapkan maka yang perlu Anda lakukan adalah mengambil hasilnya dan membaca nilainya:

$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)

Sebenarnya mengambil semua baris (data) untuk melakukan penghitungan sederhana adalah pemborosan sumber daya. Jika set hasil besar, server Anda mungkin tercekik.

ikan mas
sumber
1

Untuk menggunakan variabel dalam kueri, Anda harus menggunakan bindValue()atau bindParam(). Dan jangan menyatukan variabel dengan" . $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

Braian Coronel
sumber
0

Ketika soal mysql bagaimana cara menghitung atau mendapatkan berapa baris dalam sebuah tabel dengan PHP PDO saya menggunakan ini

// 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'];

kredit jatuh ke Mike @ codeofaninja.com

Robert
sumber
-1

Satu liner cepat untuk mendapatkan entri pertama dikembalikan. Ini bagus untuk pertanyaan yang sangat mendasar.

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

Referensi

itsazzad
sumber
-1

Saya mencoba $count = $stmt->rowCount();dengan Oracle 11.2 dan tidak berhasil. Saya memutuskan untuk menggunakan for for seperti yang ditunjukkan di bawah ini.

   $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;
manas mukherjee
sumber
-1

Untuk kueri langsung di mana saya ingin baris tertentu, dan ingin tahu apakah itu ditemukan, saya menggunakan sesuatu seperti:

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;
}
pengguna5862537
sumber
-1

Ada solusi sederhana. Jika Anda menggunakan PDO terhubung ke DB Anda seperti ini:

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();
}

Kemudian, permintaan ke DB adalah:

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

Dan akhirnya, untuk menghitung baris yang cocok dengan kueri Anda, tulis seperti ini

$amountOfRows = $query->rowcount();
Vlad
sumber
Mengapa ini mengembalikan saya -1 untuk sebagian besar waktu? Bahkan jika ada data. .
Ingus
-1

fetchColumn ()

digunakan jika ingin mendapatkan hitungan record [effisien]

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

pertanyaan()

digunakan jika ingin mengambil data dan menghitung rekaman [opsi]

$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

antelove
sumber
Anda seharusnya tidak pernah melakukan itu. Di meja yang lebih besar atau lebih besar, ia akan memakan semua memori server dan menabrak server
Your Common Sense
Sekarang jawaban Anda hanya menduplikasi selusin jawaban yang ada.
Akal Sehat Anda
-2

ketika Anda membuat COUNT (*) dalam pernyataan mysql Anda seperti pada

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

permintaan mysql Anda sudah menghitung jumlah hasil mengapa menghitung lagi di php? untuk mendapatkan hasil mysql Anda

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

dan $nbakan berisi bilangan bulat yang telah Anda hitung dengan pernyataan mysql Anda agak lama untuk ditulis tetapi cepat dieksekusi

Sunting: maaf untuk posting yang salah tetapi karena beberapa contoh menampilkan kueri dengan hitungan masuk, saya menyarankan menggunakan hasil mysql, tetapi jika Anda tidak menggunakan hitungan dalam sql fetchAll () lebih efisien, jika Anda menyimpan hasilnya dalam variabel Anda tidak akan kehilangan garis.

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

count($table)akan mengembalikan jumlah baris dan Anda masih dapat menggunakan hasilnya setelah suka $row = $table[0] atau menggunakanforeach

foreach($table as $row){
  print $row->id;
}
Kejutan
sumber
1
Pertanyaannya adalah bagaimana cara menghitung ketika Anda TIDAK membuat COUNT (*) dalam pernyataan mysql
Anda
-2

Ini adalah ekstensi custom-made dari kelas PDO, dengan fungsi pembantu untuk mengambil jumlah baris yang dimasukkan oleh kriteria "WHERE" kueri terakhir.

Anda mungkin perlu menambahkan lebih banyak 'penangan', tergantung pada perintah apa yang Anda gunakan. Saat ini hanya berfungsi untuk kueri yang menggunakan "FROM" atau "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();
    }
}
Venryx
sumber
Masalahnya tidak sepadan dengan usaha. Jumlah seperti itu sangat dibutuhkan sehingga seseorang tidak perlu ekstensi khusus. Belum lagi itu tidak mendukung pernyataan yang disiapkan - satu-satunya alasan untuk menggunakan PDO.
Akal Sehat Anda
-2

Anda dapat menggabungkan metode terbaik menjadi satu baris atau fungsi, dan membuat kueri baru yang dibuat secara otomatis untuk Anda:

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

$numRows = getRowCount($query);
Bryan
sumber
Tidak ada yang terbaik dalam metode ini. Untuk menjalankan kueri tambahan hanya untuk mengetahui berapa banyak baris yang dikembalikan sama sekali tidak masuk akal.
Akal Sehat Anda
-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>
Amranur Rahman
sumber
1
Ini ide yang sangat buruk. Memilih semua baris, itu adalah pemborosan besar bandwidth.
Nafees
-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; 
}
alpazull
sumber
-4

Gunakan parameter array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL), yang lain menunjukkan -1:

Gunakan parametro array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL), sin ello sale -1

contoh:

$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;
Victor Idrogo Aliaga
sumber