Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】PDOStatement::rowCount()メソッドの使い方

rowCountメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

rowCountメソッドは、PHPのデータベース操作拡張機能であるPDOにおいて、SQL文の実行によって影響を受けた行の数を取得するために使用されるメソッドです。

このメソッドは、PDOStatementクラスのインスタンスが保持しており、主にデータの挿入(INSERT文)、更新(UPDATE文)、削除(DELETE文)といったデータ操作言語(DML)のSQL文を実行した後に呼び出します。例えば、UPDATE文で特定の条件に合致する複数のレコードを更新した場合、rowCountメソッドは実際に更新されたレコードの総数を整数値として返します。これにより、意図した通りの件数が処理されたかを確認することができます。

しかし、データの取得(SELECT文)を実行した後にこのメソッドを使用する際には、注意が必要です。ほとんどのデータベースシステムでは、SELECT文の結果セットに含まれる行数ではなく、0を返すことが一般的です。これは、SELECT文が直接的にデータベースの状態を変更するわけではないためです。

したがって、SELECT文によって取得される結果の行数を正確に知りたい場合には、rowCountメソッドではなく、SELECT COUNT(*)のような集計関数をSQL文自体に含めるか、あるいは取得した結果をPHP側で処理した後に数えるといった、別の方法を用いる必要があります。このメソッドは、SQL文の実行結果を検証し、アプリケーションのロジックに反映させる上で重要な役割を果たします。

構文(syntax)

1<?php
2
3// PDOインスタンスが $pdo に存在し、データベースに接続されていると仮定します。
4// 例: $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'username', 'password');
5
6// SQLステートメントを準備し、PDOStatementオブジェクトを取得します。
7// ここでは、データ更新のクエリを例とします。
8$stmt = $pdo->prepare("UPDATE users SET status = 'active' WHERE id = ?");
9
10// ステートメントを実行します。
11$stmt->execute([1]); // 例としてIDが1のユーザーを更新
12
13// 影響を受けた行数を取得します。
14$affectedRows = $stmt->rowCount();
15
16// $affectedRows には、実行されたUPDATE、DELETE、INSERT文によって影響を受けた行数が整数値で格納されます。
17
18?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

int

PDOStatement::rowCount メソッドは、実行された SQL ステートメントによって影響を受けた行数を整数で返します。SELECT ステートメントの場合、結果セット内の行数を表します。

サンプルコード

PHP PDO rowCount による影響行数取得

1<?php
2
3/**
4 * PDOStatement::rowCount() の使用例
5 *
6 * このスクリプトは、PDO (PHP Data Objects) を使用してMySQLデータベースに接続し、
7 * INSERT、UPDATE、DELETE文を実行した後に、その影響を受けた行数を
8 * PDOStatement::rowCount() メソッドで取得する方法を示します。
9 *
10 * システムエンジニアを目指す初心者向けに、正確かつ簡潔なコードを提供します。
11 *
12 * 注意: SELECT文の場合、多くのデータベースドライバ(MySQLを含む)では、
13 * PDOStatement::rowCount() は結果セットの行数を正確に返しません(通常0を返します)。
14 * このメソッドは、INSERT、UPDATE、DELETEのようなDML (Data Manipulation Language) 文で
15 * 影響を受けた行数を取得するのに適しています。
16 */
17
18// データベース接続情報
19// 実際に使用する際は、以下の値を自身の環境に合わせて変更してください。
20// セキュリティのため、本番環境では設定ファイルや環境変数から読み込むことを強く推奨します。
21$dsn = 'mysql:host=localhost;dbname=your_database;charset=utf8mb4';
22$user = 'your_username';
23$password = 'your_password';
24
25try {
26    // PDO (PHP Data Objects) インスタンスを作成し、データベースに接続します。
27    // PDO::ATTR_ERRMODE を PDO::ERRMODE_EXCEPTION に設定することで、
28    // SQL実行時のエラーをPDOExceptionとして捕捉できるようになります。
29    $pdo = new PDO($dsn, $user, $password, [
30        PDO::ATTR_ERRMODE          => PDO::ERRMODE_EXCEPTION,
31        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 結果を連想配列で取得するよう設定
32        PDO::ATTR_EMULATE_PREPARES => false,              // プリペアドステートメントのネイティブエミュレーションを無効化
33    ]);
34
35    echo "データベースに接続しました。\n";
36
37    // サンプルのために一時的な 'users' テーブルを作成します。
38    // このCREATE TABLE文は、テーブルが存在しない場合にのみ実行されます。
39    $pdo->exec("
40        CREATE TABLE IF NOT EXISTS users (
41            id INT AUTO_INCREMENT PRIMARY KEY,
42            name VARCHAR(255) NOT NULL,
43            email VARCHAR(255) UNIQUE NOT NULL
44        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
45    ");
46    echo "usersテーブルの準備ができました。\n";
47
48    // --- INSERT文での PDOStatement::rowCount() の使用例 ---
49    echo "\n--- INSERT操作 ---\n";
50
51    // INSERT文のプリペアドステートメントを準備します。
52    $insertStmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
53
54    // 1行目のデータを挿入します。
55    $insertStmt->execute([':name' => 'Alice Smith', ':email' => 'alice@example.com']);
56    $insertedRows1 = $insertStmt->rowCount(); // 影響を受けた行数を取得 (成功すれば1)
57    echo "1行目のデータ挿入。影響を受けた行数: {$insertedRows1}行\n";
58
59    // 2行目のデータを挿入します。
60    $insertStmt->execute([':name' => 'Bob Johnson', ':email' => 'bob@example.com']);
61    $insertedRows2 = $insertStmt->rowCount(); // 影響を受けた行数を取得 (成功すれば1)
62    echo "2行目のデータ挿入。影響を受けた行数: {$insertedRows2}行\n";
63
64    // 既に存在するメールアドレスで挿入を試みます (UNIQUE制約違反を想定)。
65    // この場合、PDOExceptionがスローされ、rowCount()は通常0を返します。
66    try {
67        $insertStmt->execute([':name' => 'Charlie Brown', ':email' => 'alice@example.com']);
68        $insertedRowsError = $insertStmt->rowCount();
69        echo "重複データ挿入の試行。影響を受けた行数: {$insertedRowsError}行\n";
70    } catch (PDOException $e) {
71        // SQLSTATE '23000' は整合性制約違反(例: UNIQUEキー重複)を示します。
72        if ($e->getCode() === '23000') {
73            echo "エラー: メールアドレス 'alice@example.com' は既に存在します。(SQLSTATE: {$e->getCode()})\n";
74            // 挿入が失敗した場合、rowCount() は通常0を返します。
75            $failedInsertRowCount = $insertStmt->rowCount();
76            echo "失敗時の rowCount(): {$failedInsertRowCount}行\n";
77        } else {
78            // その他のエラーは再スローして、上位で処理させます。
79            throw $e;
80        }
81    }
82
83    // --- UPDATE文での PDOStatement::rowCount() の使用例 ---
84    echo "\n--- UPDATE操作 ---\n";
85
86    // UPDATE文のプリペアドステートメントを準備します。
87    $updateStmt = $pdo->prepare("UPDATE users SET name = :new_name WHERE email = :email");
88
89    // 存在するデータを更新します。
90    $updateStmt->execute([':new_name' => 'Alice Wonderland', ':email' => 'alice@example.com']);
91    $updatedRows1 = $updateStmt->rowCount(); // 影響を受けた行数を取得 (成功すれば1)
92    echo "存在するデータの更新。影響を受けた行数: {$updatedRows1}行\n";
93
94    // 更新対象がないデータを更新します。
95    // この場合、rowCount()は0を返します。
96    $updateStmt->execute([':new_name' => 'David Lee', ':email' => 'nonexistent@example.com']);
97    $updatedRows2 = $updateStmt->rowCount(); // 影響を受けた行数を取得 (0)
98    echo "存在しないデータの更新。影響を受けた行数: {$updatedRows2}行\n";
99
100    // --- DELETE文での PDOStatement::rowCount() の使用例 ---
101    echo "\n--- DELETE操作 ---\n";
102
103    // DELETE文のプリペアドステートメントを準備します。
104    $deleteStmt = $pdo->prepare("DELETE FROM users WHERE email = :email");
105
106    // 存在するデータを削除します。
107    $deleteStmt->execute([':email' => 'bob@example.com']);
108    $deletedRows1 = $deleteStmt->rowCount(); // 影響を受けた行数を取得 (成功すれば1)
109    echo "存在するデータの削除。影響を受けた行数: {$deletedRows1}行\n";
110
111    // 既に削除された、または存在しないデータを削除します。
112    // この場合、rowCount()は0を返します。
113    $deleteStmt->execute([':email' => 'bob@example.com']);
114    $deletedRows2 = $deleteStmt->rowCount(); // 影響を受けた行数を取得 (0)
115    echo "存在しないデータの削除。影響を受けた行数: {$deletedRows2}行\n";
116
117    echo "\nすべての操作が完了しました。\n";
118
119} catch (PDOException $e) {
120    // データベース接続エラーやSQL実行エラーが発生した場合
121    echo "データベースエラーが発生しました: " . $e->getMessage() . "\n";
122    // デバッグ時には、$e->getCode() や $e->getTraceAsString() も有用です。
123} finally {
124    // データベース接続を閉じます。
125    // PHPではスクリプト終了時に自動的に閉じられますが、明示的にnullを代入することも可能です。
126    $pdo = null;
127    $insertStmt = null;
128    $updateStmt = null;
129    $deleteStmt = null;
130    echo "データベース接続を閉じました。\n";
131}
132

PHP 8のPDOStatement::rowCount()メソッドは、データベースに対して実行されたSQL文によって影響を受けた行数を取得するために使われます。このメソッドは、PDOStatementオブジェクトに対してINSERTUPDATEDELETEなどのデータ操作言語(DML)文を実行した際に、実際に挿入、更新、または削除されたレコードの数を整数値(int)で返します。引数は必要ありません。

このサンプルコードでは、INSERT文で新しいデータが挿入された場合、UPDATE文で既存のデータが変更された場合、DELETE文でデータが削除された場合に、それぞれrowCount()が何を返すかを示しています。例えば、1行のデータが挿入されれば1、更新対象がなければ0が返される様子が確認できます。

特に注意すべき点として、SELECT文でデータを取得する際には、多くのデータベースドライバ(MySQLなど)においてrowCount()は結果セットの行数を正確に返しません。通常0が返されるため、SELECT文で取得した行数を知る目的には適していません。rowCount()は、あくまでINSERTUPDATEDELETEといったDML文によるデータベースの変更結果を確認するために利用されるメソッドです。

PDOStatement::rowCount()は、INSERTUPDATEDELETEといったデータ操作言語(DML)文によってデータベースが影響を受けた行数を取得する際に用います。システムエンジニアを目指す初心者の方は、SELECT文でこのメソッドを使用した場合、多くのデータベースドライバ(MySQLを含む)では期待する結果セットの行数ではなく、通常0が返される点に特に注意が必要です。SELECT結果の行数取得には、別途COUNT(*)を使用するか、データをフェッチ後に数える方法をご検討ください。また、データの挿入が制約違反などで失敗した際も、rowCount()は通常0を返しますので、例外処理と合わせて確認してください。データベース接続情報は本番環境でコードに直接記述せず、安全な方法で管理することが重要です。サンプルコードのようにプリペアドステートメントを利用し、SQLインジェクション対策を徹底してください。

PHP PDOStatement rowCountで影響行数を取得する

1<?php
2
3/**
4 * PDOStatement::rowCount() メソッドの使用例を示します。
5 * 主にINSERT, UPDATE, DELETE文で影響を受けた行数を取得するために使用されます。
6 * SELECT文での正確な行数取得には適していません(データベースドライバに依存するため)。
7 */
8function demonstrateRowCount(): void
9{
10    // SQLiteのインメモリデータベースに接続します。
11    // 実際のアプリケーションでは、ファイルパスや他のデータベース接続情報を使用します。
12    try {
13        $pdo = new PDO('sqlite::memory:');
14        // エラー発生時に例外をスローするように設定します。
15        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
16
17        echo "データベースに接続しました。\n\n";
18
19        // サンプルテーブルを作成します。
20        $pdo->exec(
21            'CREATE TABLE IF NOT EXISTS users (
22            id INTEGER PRIMARY KEY AUTOINCREMENT,
23            name VARCHAR(50),
24            email VARCHAR(100)
25        )'
26        );
27        echo "テーブル 'users' を作成しました。\n\n";
28
29        // --- INSERT文でのrowCountの使用 ---
30        // データを挿入するSQL文を準備します。
31        $stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
32
33        // データをバインドして実行します。
34        $stmt->execute([':name' => 'Alice', ':email' => 'alice@example.com']);
35        // 挿入された行数を取得します。
36        $insertedRows = $stmt->rowCount();
37        echo "INSERT文を実行: {$insertedRows} 行が挿入されました。\n";
38
39        $stmt->execute([':name' => 'Bob', ':email' => 'bob@example.com']);
40        $insertedRows = $stmt->rowCount();
41        echo "INSERT文を実行: {$insertedRows} 行が挿入されました。\n";
42
43        $stmt->execute([':name' => 'Charlie', ':email' => 'charlie@example.com']);
44        $insertedRows = $stmt->rowCount();
45        echo "INSERT文を実行: {$insertedRows} 行が挿入されました。\n\n";
46
47        // --- UPDATE文でのrowCountの使用 ---
48        // データを更新するSQL文を準備します。
49        $stmt = $pdo->prepare('UPDATE users SET email = :new_email WHERE name = :name');
50        $stmt->execute([':new_email' => 'alice.smith@example.com', ':name' => 'Alice']);
51        // 更新された行数を取得します。
52        $updatedRows = $stmt->rowCount();
53        echo "UPDATE文を実行: {$updatedRows} 行が更新されました。\n\n";
54
55        // 更新対象がない場合
56        $stmt->execute([':new_email' => 'notfound@example.com', ':name' => 'David']);
57        $updatedRows = $stmt->rowCount();
58        echo "UPDATE文を実行 (対象なし): {$updatedRows} 行が更新されました。\n\n";
59
60
61        // --- DELETE文でのrowCountの使用 ---
62        // データを削除するSQL文を準備します。
63        $stmt = $pdo->prepare('DELETE FROM users WHERE name = :name');
64        $stmt->execute([':name' => 'Bob']);
65        // 削除された行数を取得します。
66        $deletedRows = $stmt->rowCount();
67        echo "DELETE文を実行: {$deletedRows} 行が削除されました。\n\n";
68
69        // SELECT文でのrowCountの利用について(注意点)
70        // PDOStatement::rowCount() はSELECT文に対しては、ほとんどのデータベースで意味のある値を返しません。
71        // SELECT文の結果の行数を取得するには、一般的にFETCH_NUM や COUNT(*) クエリを使用します。
72        $stmt = $pdo->query('SELECT * FROM users');
73        $selectRowCount = $stmt->rowCount(); // この値は信頼できません
74        echo "SELECT文を実行 (不正確なrowCount): この値は {$selectRowCount} ですが、SELECT文では信頼できません。\n";
75        echo "現在のテーブルに残っている行数:\n";
76        $stmt = $pdo->query('SELECT name, email FROM users');
77        foreach ($stmt as $row) {
78            echo "- Name: {$row['name']}, Email: {$row['email']}\n";
79        }
80
81    } catch (PDOException $e) {
82        // データベース関連のエラーをキャッチします。
83        echo "データベースエラー: " . $e->getMessage() . "\n";
84    } catch (Exception $e) {
85        // その他のエラーをキャッチします。
86        echo "エラー: " . $e->getMessage() . "\n";
87    }
88}
89
90// 関数を実行します。
91demonstrateRowCount();

PDOStatement::rowCount()メソッドは、PHPでデータベースを操作する際に、直前に実行されたSQL文によって「影響を受けた行数」を取得するために使用されます。このメソッドはPDOStatementクラスに属し、引数を取らずに整数(int)の値を返します。

特に、データベースにデータを追加するINSERT文、既存のデータを更新するUPDATE文、またはデータを削除するDELETE文の実行後にrowCount()を呼び出すと、実際に挿入、更新、または削除された行の数を正確に把握できます。これにより、意図した操作がどの程度のデータに影響を与えたかを確認でき、アプリケーションのロジックで活用することが可能です。

ただし、SELECT文(データベースからデータを取得する文)でrowCount()を使用する場合、ほとんどのデータベースドライバでは、結果セットの全行数を正確に返さないことに注意が必要です。SELECT文で取得される行数を数える必要がある場合は、COUNT(*)のようなSQL関数を別途使用するか、取得した結果セットの配列の要素数を数えるのが一般的です。

このサンプルコードは、SQLiteのインメモリデータベースに接続してusersテーブルを作成し、INSERTUPDATEDELETEの各SQL文を実行した後にrowCount()がどのように機能するかを具体的に示しています。また、SELECT文でrowCount()を呼び出した際に、その値が信頼できないことを示し、その注意点を明確に解説しています。データベース操作の基本を学ぶ上で、このメソッドの適切な使い方と制限を理解することは非常に重要です。

PDOStatement::rowCount()は、主にINSERTUPDATEDELETE文で、データベースに影響を与えた行数を取得する際に利用します。これがこのメソッドの主な用途です。

最も注意すべき点は、SELECT文でこのメソッドを使用すると、ほとんどのデータベースドライバでは正確な行数を返さないことです。データベースの種類やドライバによって挙動が異なるため、SELECT文の実行結果の行数を知る目的では信頼できません。

SELECT文の行数を取得したい場合は、SELECT COUNT(*)クエリを別途実行するか、取得した結果セットをプログラム側で数えるのが安全な方法です。この特性を理解し、正しく使い分けることが、予期せぬ動作を避け、堅牢なアプリケーションを開発する上で非常に重要です。

関連コンテンツ