PDOStatement::rowCount()で値が0になる例

このページは、PHPの PDOStatement::rowCount() で値が0になる例をまとめたページです。

PDOStatement::rowCount()で値が0になる例

  • MySQL, MariaDBで非バッファモード (PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false) でSELECTしている
  • SQLiteを使用している
  • スクロール可能カーソル (PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL) を使用している

MySQL, MariaDBで非バッファモードでSELECTしている

非バッファモードを使用した例 (PHP 8.1, MariaDB 10.4)
$dsn = 'mysql:host=localhost;dbname=test'; // DSN
$user = 'root'; // ユーザー
$pass = ''; // パスワード
$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
]);

// 3件登録
$pdo->query('DROP TABLE IF EXISTS emp');
$pdo->query('CREATE TABLE emp (id SERIAL, name VARCHAR(100))');
$pdo->query("INSERT INTO emp VALUES(1, 'emp1'), (2, 'emp2'), (3, 'emp3')");

// 全件取得
$stmt1 = $pdo->query('SELECT * FROM emp');
echo $stmt1->rowCount(); // 0。PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true (または未指定) だと3

INSERT, UPDATE, DELETEなどの後だと非バッファモードでも影響した件数の値になります。(rowCount()の値はC APIのmysql_stmt_affected_rows()の値になっているため)

ext/pdo_mysql/mysql_statement.c (PHP 8.1)
static void pdo_mysql_stmt_set_row_count(pdo_stmt_t *stmt) /* {{{ */
{
	pdo_mysql_stmt *S = stmt->driver_data;
	zend_long row_count = (zend_long) mysql_stmt_affected_rows(S->stmt);
	if (row_count != (zend_long)-1) {
		stmt->row_count = row_count;
	}
}
ext/pdo/pdo_stmt.c (PHP 8.1)
PHP_METHOD(PDOStatement, rowCount)
{
	ZEND_PARSE_PARAMETERS_NONE();

	PHP_STMT_GET_OBJ;
	RETURN_LONG(stmt->row_count);
}

SQLiteを使用している

SQLiteを使用した例 (PHP 8.1)
$dsn = 'sqlite:memory'; // DSN
$pdo = new PDO($dsn, '', '', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

// 3件登録
$pdo->query('DROP TABLE IF EXISTS emp');
$pdo->query('CREATE TABLE emp (id SERIAL, name VARCHAR(100))');
$pdo->query("INSERT INTO emp VALUES(1, 'emp1'), (2, 'emp2'), (3, 'emp3')");

// 全件取得
$stmt1 = $pdo->query('SELECT * FROM emp');
echo $stmt1->rowCount(); // 0

スクロール可能カーソルを使用している

スクロール可能カーソルを使用した例 (PHP 8.1, PostgreSQL 15.1)
$dsn = 'pgsql:host=localhost;dbname=test'; // DSN
$user = 'postgres'; // ユーザー
$pass = 'postgres'; // パスワード
$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

// 3件登録
$pdo->query('DROP TABLE IF EXISTS emp');
$pdo->query('CREATE TABLE emp (id SERIAL, name VARCHAR(100))');
$pdo->query("INSERT INTO emp VALUES(1, 'emp1'), (2, 'emp2'), (3, 'emp3')");

// 全件取得
$stmt1 = $pdo->prepare('SELECT * FROM emp', [ PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL ]);
$stmt1->execute();
echo $stmt1->rowCount(); // 0。PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY (または未指定) だと3