【MySQL】UPDATE・DELETE・INSERT実行後に処理件数を取得する方法


UPDATE・DELETE・INSERT実行後に出力されるQuery OK, 1 row affectedの件数を取得する方法です。

mysql> UPDATE animals SET name = 'cat' WHERE name = 'lion';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

SQLとPHP、2種類の方法を説明します。

SQLで取得する

ROW_COUNT()関数で取得できます。
必ずステートメント(UPDATE、DELETE、INSERTなどの実行単位)の完了直後に実行してください。

ROW_COUNT()の使い方

SELECT ROW_COUNT();を実行します。

-- UPDATE
mysql> UPDATE animals SET name = 'dog' WHERE name = 'wolf';
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> SELECT ROW_COUNT();
+-------------+
| ROW_COUNT() |
+-------------+
|           7 |
+-------------+
1 row in set (0.00 sec)

-- DELETE 
mysql> DELETE FROM animals WHERE id = 3;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROW_COUNT();
+-------------+
| ROW_COUNT() |
+-------------+
|           1 |
+-------------+
1 row in set (0.00 sec)

-- INSERT
mysql> INSERT INTO animals (name) VALUES('dog'), ('cat'), ('rabbit');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT ROW_COUNT();
+-------------+
| ROW_COUNT() |
+-------------+
|           3 |
+-------------+
1 row in set (0.00 sec)

ROW_COUNT()とは

  • MySQLの情報関数
  • 直前のステートメントで影響を受けた行数を返す
  • UPDATE・DELETE・INSERTの直後は変更、削除、または挿入された行数を返す
  • ステートメントの実行直後に呼び出すことができる

以下、MySQL公式マニュアルからの引用です。

ROW_COUNT()

ROW_COUNT() は、mysql_affected_rows() C API 関数から取得される値と同様で、ステートメントの実行後に mysql クライアントに表示される行数です。

mysql_affected_rows()

mysql_affected_rows() は、mysql_query() または mysql_real_query() によるステートメントの実行直後に呼び出すことができます。それは、最後のステートメントが UPDATE、DELETE、または INSERT であった場合に、それによって変更、削除、または挿入された行数を返します。SELECT ステートメントの場合、mysql_affected_rows() は mysql_num_rows() のように動作します。

events_statements_current テーブル

ROWS_AFFECTED
ステートメントに影響を受けた行数。「影響を受けた」の意味については、セクション23.7.7.1「mysql_affected_rows()」を参照してください。

ROW_COUNT()はAPIのmysql_affected_rows()やステートメントイベントを格納するテーブルevents_statements_currentROWS_AFFECTEDカラムの値と同じです。

PHPで取得する

PDOクラスとmysqliクラスを利用します。
PHP公式マニュアル: どのAPIを使うか

PDOクラス

PDOクラスのexec()は戻り値が処理件数です。
PHP公式マニュアル: PDO::exec

pdo_test1.php
$dbh = new PDO($dsn, $user, $password);
$count = $dbh->exec("INSERT INTO animals (name) VALUES('rabbit'), ('wolf')");

echo $count; # 2を返す

rowCount()でステートメントの実行直後に処理件数を取得することもできます。
PHP公式マニュアル: PDOStatement::rowCount

pdo_test2.php
$dbh = new PDO($dsn, $user, $password);
$del = $dbh->prepare("INSERT INTO animals (name) VALUES('rabbit'), ('wolf')");
$del->execute();
$count = $del->rowCount();

echo $count; # 2を返す

mysqliクラス

mysqliクラスはステートメントの実行直後にaffected_rowsプロパティから処理件数を取得できます。

PHP公式マニュアル: mysqli::$affected_rows

mysqli_test.php
$mysqli = new mysqli($host, $user, $password, $database);
$result = $mysqli->query("INSERT INTO animals (name) VALUES('rabbit'), ('wolf')");
$count = $mysqli->affected_rows;

echo $count; # 2を返す

他のRDMSでは使えるのか

MySQL以外のRDMSにもROW_COUNT()に相当する機能は存在しますが、RDMS毎に仕様が異なるようです。
公式マニュアルで仕様を確認した後で利用しましょう。

PHP公式マニュアル: PDOStatement::rowCountでも説明されています。

関連する PDOStatement によって実行された直近の SQL ステートメントが SELECT 文の場合、いくつかのデータベースは文によって返された 行数を返すかも知れません。しかしながら、 この振る舞いは全てのデータベースで保証されていません。 さまざまな場所で使用するアプリケーションでは、 これに頼ってはいけません。

このメソッドは SQLite ドライバの場合はあらゆる場合に "0" (ゼロ) を返します。 PostgreSQL ドライバの場合は ステートメント属性 PDO::ATTR_CURSOR の設定が PDO::CURSOR_SCROLL の場合にだけ "0" (ゼロ) を返します。

まとめ

多くのORMはSQL実行メソッドの戻り値=処理件数なので、利用機会は少なさそう。

採用PR

弊社で一緒に働く仲間を募集しています。
全てのオタクを幸せにしたい方、是非ご覧ください!