データベース
PR

MySQLのLIMIT 20, 10(カンマ区切り)は卒業を|LIMIT … OFFSETへの書き換えとFETCH NEXT(標準SQL)の対応状況

saratogax
記事内に商品プロモーションを含む場合があります

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 など)。

FETCH NEXT 10 ROWS ONLYFETCH NEXT 1 ROW ONLY。英語としては単数・複数を使い分けたくなりますが、この構文をサポートする DB(PostgreSQL・SQL Server など)では、どちらを使っても構いません。コードの統一感のため、常に ROWS に固定する現場も多いです。

注意:MySQL と MariaDB は、この OFFSET ... FETCH NEXT 構文をサポートしていません。公式リファレンスでも、行数制限の構文は LIMIT [offset,] row_countLIMIT row_count OFFSET offset の 2 つだけです。AWS Aurora(MySQL 互換)も同様で、FETCH NEXT を書くと構文エラーになります。

主要データベースエンジンの対応状況比較

将来的に 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 のみ、FETCH NEXT は他エンジンで使えます。

このように、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 の記事もあわせてどうぞ。

あわせて読みたい
MySQLのDATE_FORMATで日付を整形する方法と書式一覧
MySQLのDATE_FORMATで日付を整形する方法と書式一覧
ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました