MySQLのLIMIT 20, 10(カンマ区切り)は卒業を|LIMIT … OFFSETへの書き換えとFETCH NEXT(標準SQL)の対応状況
MySQL を使っているエンジニアにとって、レコードの取得件数を制限する LIMIT 句はお馴染みの存在です。しかし、LIMIT 20, 10 のようなカンマ区切りの書き方が「MySQL 特有の書き方(方言)」であることをご存知でしょうか。
近年、クラウドネイティブな環境(AWS Aurora など)やモダンなユニットテスト環境(H2 Database 2.x)への移行が進む中で、この「書き方」の選択が将来のメンテナンス性に大きな影響を与えるようになっています。
本記事では、MySQL の LIMIT 句の変遷から、各 DB エンジンの対応状況、そしてなぜ今「標準 SQL」への完全移行がベストプラクティスなのかを解説します。
LIMIT 句の 3 つの書き方とその違い
現在、主要な RDBMS では以下の 3 つの形式で件数制限が行われています。
① MySQL 特有(カンマ区切り)
SELECT * FROM orders LIMIT 20, 10;- 特徴: 左が OFFSET(飛ばす数)、右が LIMIT(取る数)。
- リスク: どちらがどっちか直感的に分かりにくく、書き間違いが発生しやすい。
② デファクトスタンダード(LIMIT OFFSET)
SELECT * FROM orders LIMIT 10 OFFSET 20;- 特徴: PostgreSQL や SQLite でも採用されており、可読性が高い。
- リスク: 多くの DB で動くが、実はこれでも「標準規格」ではない。
③ 標準 SQL 準拠(OFFSET FETCH NEXT)
SELECT * FROM orders
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;- 特徴: SQL:2008 で定義された公式な書き方。
- メリット: 最も寿命が長く、Oracle や SQL Server との互換性も高い。
- 注意: ただし MySQL / MariaDB では使えません(対応は PostgreSQL・SQL Server・Oracle・H2 など)。
主要データベースエンジンの対応状況比較
将来的に DB を乗り換える、あるいはマルチ DB 環境で開発する場合、LIMIT の有無は大きな壁になります。
| データベースエンジン | LIMIT 句 | OFFSET / FETCH NEXT | 備考 |
|---|---|---|---|
| MySQL / MariaDB (Aurora 含む) | ○ | × | FETCH 非対応。LIMIT … OFFSET を使う |
| PostgreSQL | ○ | ○ | 古くから両方の構文に対応 |
| SQL Server | × | ○ | LIMIT非対応(TOP句またはOFFSET-FETCH) |
| Oracle (12c以降) | × | ○ | 12cから標準SQLのFETCH句を導入 |
| H2 Database (2.x) | ○ | ○ | 2.x系より標準SQL準拠を強力に推進 |
このように、MySQL 系は LIMIT だけ、SQL Server や Oracle は FETCH だけと、すべての DB で共通して動く構文はありません。複数 DB をまたぎたい場合は、生 SQL を無理にそろえるより ORM やクエリビルダに任せるのが現実的です。
MySQL では何に書き換えるべきか
ここまでの整理から、MySQL でやるべきなのは LIMIT 20, 10(カンマ区切り)を LIMIT 10 OFFSET 20 に書き換えることです。
FETCH NEXT は MySQL では使えないため、「MySQL を FETCH NEXT に移行する」ことはできません。ここはよく誤解されるので注意してください。
カンマ区切りをやめる理由
LIMIT 20, 10 は「どちらが OFFSET でどちらが件数か」が直感的に分からず、引数を逆にするミスが起きやすい書き方です。
LIMIT 10 OFFSET 20 なら役割が明示され、PostgreSQL や SQLite とも同じ書き方になるので、可読性・移植性の両面で有利です。
MyBatis での書き換え例
MyBatis の XML なら、LIMIT #{offset}, #{limit} ではなく LIMIT #{limit} OFFSET #{offset} と書くと、パラメータの役割が明確になり、順番の取り違えを防げます。
本当に DB 非依存にしたいなら
MySQL と、FETCH NEXT を使う DB(PostgreSQL・SQL Server・Oracle など)の両方でそのまま動く「生の SQL」は存在しません。
開発・テスト・本番で異なる DB を使う、あるいは将来の乗り換えに備えるなら、ページング処理は ORM やクエリビルダ(または DB 別の MyBatis XML)に寄せて、方言の差を吸収させるのが堅実です。
まとめ:DB ごとに正しい書き方を選ぶ
行数制限の書き方は DB エンジンによって異なるため、環境に合わせて選ぶのが正解です。
- MySQL / MariaDB(Aurora 含む):
LIMIT 10 OFFSET 20を使う。カンマ区切りは卒業。FETCH NEXTは使えない。 - PostgreSQL / SQL Server / Oracle / H2: 標準SQLの
OFFSET ... FETCH NEXT ...が使える。 - 複数 DB 対応: 生 SQL を統一しようとせず、ORM/クエリビルダに任せる。
方言に依存し続けるリスクは無視できませんが、「どの DB でも同じ SQL」を目指すより、各 DB で正しい書き方を選ぶ・抽象化に任せるほうが、結局は堅実です。
MySQL の DATE_FORMAT による日付整形など、ほかの SQL の記事もあわせてどうぞ。
