Многие разработчики используют расширение PHP Data Objects (PDO) для PHP, предоставляющее разработчику простой и универсальный интерфейс для доступа к различным базам данных. У PDO множество плюсов, однако есть и минусы. PDO не предоставляет метод для узнавания количества полученных строк.
Для работы с БД разработчики PHP предлагают использовать расширение MySQLi или PDO. MySQLi является улучшенной версией устаревшего расширения MySQL. В этих PHP расширениях есть соответсвующие функции mysql_num_rows
и mysqli_num_rows
, которые получают число рядов в результате. А как же дела обстоят с PDO?
В PDO есть метод columnCount()
, который возвращает столько столбцов сколько было запрошено в SELECT
вне зависимости от количества рядов, т.е. вернёт количество столбцов даже если результата выборки нет, т.е. 0 рядов. В то же время в PDO нет надёжного метода, который бы вернул количество полученных в результате запроса строк/рядов. Как разработчики такой мощной вещи как PDO не сделали что-нибудь в стиле numRows? Как тогда в PHP Data Objects (PDO) получить количество строк выбранных запросом SELECT
?
Дело в том, что определение количества выбранных записей с точки зрения концепции реляционных БД является нежелательной операцией, потому что требует полной выборки всего результата запроса в память, а не работы с указателем на текущий ряд выборки в БД. Если запрос возвращает большие данные с типом BLOB, то это может быть вообще невозможно. Как выйти из сложившейся ситуации? Лучше всего переписать алгоритм так, чтобы он не требовал определения общего количества записей, а просто работал с выборкой пока она не закончится.
Способы получения количества выбранных строк в PDO
Но если вам всё же сильно нужно количество выбранных строк, то есть некоторые варианты.
PDO метод rowCount
PDOStatement::rowCount()
— негарантированный метод. Если последним запросом, запущенным соответствующим объектом PDOStatement
, было SQL выражение SELECT
, некоторые СУБД могут вернуть количество строк в результирующем наборе. Однако, такое поведение метода не гарантируется для всех баз данных, и это нужно учитывать при проектировании приложений.
Вообще, метод rowCount
возвращает количество именно затронутых запросом рядов, т.е. изменённых/обновлённых или добавленных. Таким образом возвращается результата только после операций DELETE
, INSERT
или UPDATE
, но никак не SELECT
. И всё же некоторые СУБД, например, MySQL, при запросе SELECT
возвращают количество результатов при вызове rowCount()
, хотя делать этого не должны. В общем, если использовать rowCount
, тогда о портабельности можно забыть т.к. он не будет работать со всеми БД.
Пример использования PDO метода rowCount:
$query = $dbh->query("SELECT id FROM users"); $members = $query->rowCount();
Можно записать короче:
$members = $dbh->query("SELECT id FROM users")->rowCount();
SQL оператор COUNT
Предварительно выполнять запрос с аналогичными условиями (WHERE
и GROUP BY
), но вместо списка полей выбрать COUNT(0)
:
SELECT COUNT(0) AS ROW_COUNT FROM <здесь все то же самое, что идет вашем запросе после слова FROM>
Если лень писать еще один запрос, то можно так (менее оптимально, но удобнее):
SELECT COUNT(0) AS ROW_COUNT FROM (<здесь ваш запрос в исходном виде>)
Пример использования SQL оператора COUNT:
$query = $dbh->query("SELECT COUNT(*) as count FROM users"); $query->setFetchMode(PDO::FETCH_ASSOC); $row = $query->fetch(); $members = $row['count'];
PDO метод fetchAll
Выбрать все записи в память вызовом PDOStatement::fetchAll()
, а затем просто проверить длину возвращенного этим вызовом массива. Требует памяти для хранения полного результата запроса:
Использование этого метода для извлечения строк больших результирующих наборов может пагубно сказаться на производительности системы и сетевых ресурсов. Вместо извлечения всех данных и их обработки в PHP рекомендуется использовать встроенные средства СУБД. Например, использование выражений WHETE
и ORDER BY
языка SQL может уменьшить размеры результирующего набора.
Какой вариант лучше
Как быстрее и правильнее подсчитать количество записей в базе данных MySQL, используя PDO? Правильнее работать с указателем и ничего не подсчитывать. Если же надо подсчитать, то всё индивидуально в зависимости от конкретного случая.
PDO и MySQLi
Почему в PHP расширениях MySQL и MySQLi есть метод для получения количества рядов запроса, а в PDO его нет? Потому что эту операцию поддерживает только СУБД MySQL, в то время как другие СУБД не поддерживают, как то рекомендуется в концепции реляционных БД. PHP расширения MySQL и MySQLi работают только с СУБД MySQL, в то время как PDO это портабельное решения, работающее с множеством СУБД.