- 開発技術
MySQLの更新で気を付けるポイント(ROW_COUNT)
- QueryBuilder
- MySQL

気を付けるポイントについて
【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc. 詳細はこちらから>
自動テストで更新データの件数を取得する場合や、更新データの件数に応じた処理を記載する場合など、DBで更新した後のデータの件数を取得することがあると思う。
1 2 3 4 5 6 7 8 9 |
// Laravel(QueryBuilder)での記載例(必要箇所のみ抜粋) DB::table(‘users’) ->where(‘id’, $data->id) ->update([ ‘name’ => $data->name, ‘position’ => $data->position, ‘age’ => $data->age, ]) ->rowCount(); |
このrowCount ()だが、使用するDBがMySQLの場合、上記処理をROW_COUNTで対象のデータを取得している。このROW_COUNTには、実際にデータが更新されている件数を取得しているという仕様がある。
そのため、更新自体は行われても、更新前後のデータ値が全く同じ場合、そのデータはROW_COUNTに加算されないことに気を付けた方が良い。
対策
● CLIENT_FOUND_ROWSフラグ設定する(非推奨)
MySQLに接続する時に利用するmysql_real_connect()で、client_flagにCLIENT_FOUND_ROWSを設定する方法である。こちらを設定すると、ROW_COUNTで取得するデータの件数が、更新対象となる(WHERE句の条件を満たす)データの件数になる。
こちらの方法だが、要件を満たす一方、DB接続する際に影響を及ぼすため、修正などでこちらの対応をするのはあまりお勧めしない。次の対策ができない場合にどうしても、とした方がいいだろう。
● 対象テーブルに更新日時カラムを追加する
対象テーブルに更新日時カラムが設定されていない場合、そのカラムを追加する。更新日時に現在時刻を更新するよう対応することで、更新前後のデータが異なるようになり、それ以外の更新値が同じであってもROW_COUNTに加算されるようになる。
特に気を付けるタイミング
● 自動テスト
自動テストを実施するタイミングでDBにデータを登録する場合、更新日時に設定する値が現在日時になっていると、テスト時間によっては、DB追加した時刻とテストで更新した時刻が完全に一致してしまい、rowCount()を用いた更新チェックで想定と異なる結果になる可能性がある。
実際に現場で「更新テストを手動で行うと成功するが、自動テストでは失敗する」という状態に遭遇したことがあった。同様の状態になったら、自動テストで挿入するデータの更新日時が現在時刻になっていないか確認し、なっていたら固定日時やTODAYのように時刻が00:00になる値を設定すると良いだろう。
参考資料
https://dev.mysql.com/doc/refman/8.0/ja/information-functions.html
https://dev.mysql.com/doc/c-api/8.4/en/mysql-real-connect.html
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>