他のRDBMSと同じつもりで Db2 のページングを書くと、構文エラーで止まることがあります。
SQL0104N An unexpected token "FETCH FIRST 5 ROWS ONLY" was found following
"...ORDER BY TABNAME". Expected tokens may include: "<space>". SQLSTATE=42601
このエラーの原因は、句が使えないことではなく書く順序です。この記事では正しい順序と、ページングまわりで迷う点の逆引きを最短でまとめます。バージョン別の実測と公式ドキュメントの変遷は末尾のZenn記事にあります。
まず見る(結論)
OFFSET は FETCH FIRST より前に書きます。逆に書くと SQL0104N です。
# 20件飛ばして10件(この順序が正しい)
db2 "SELECT ... FROM ... ORDER BY ... OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY"
ORDER BY を省くと返る行が毎回同じとは限りません。ページングでは必ず付けます。
症状 → 原因 → 対処(逆引き)
| 症状 | よくある原因 | まず打つ手 |
|---|---|---|
SQL0104N/FETCH FIRST … が unexpected token |
FETCH FIRST を OFFSET より先に書いている |
OFFSET y ROWS FETCH NEXT x ROWS ONLY の順に直す |
LIMIT が普通に動いてしまう |
11.1 以降は常時有効。仕様どおり | そのままでも動くが、公式は非標準としている。標準構文へ寄せる |
「DB2_COMPATIBILITY_VECTOR を立てろ」と書かれた情報が見つかる |
10.5 以前の情報。11.1 で常時有効になりビットは無視される | db2set は不要。バージョンを先に確認する |
| 同じ問い合わせなのに毎回違う行が返る | ORDER BY が無い |
ORDER BY を付ける。LIMIT も FETCH FIRST も順序は保証しない |
LIMIT 5, 5 がどちらの引数か分からない |
MySQL と同じ「5件飛ばして5件」 | OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY に書き換える |
OFFSET が使えない古い環境 |
バージョンが古い | ROW_NUMBER() OVER (ORDER BY …) を副問い合わせにして範囲で絞る |
FIRST と NEXT、ROW と ROWS はどちらでも通るので、そこを直しても解決しません。
エラーメッセージの Expected tokens may include は候補を1つしか出さないため、順序の誤りに対しては手がかりになりません。公式の offset-clause のページにも順序の制約は書かれていないので、ドキュメントを引いても辿り着きにくいところです。SQL0104N を見たらまず順序を疑うのが早道です。
それでも切り分からないとき(実機ログつきの詳解)
11.5.5.1/11.5.9/12.1.4 での実測比較、互換ベクターの説明が11.1で書き換わった経緯、非標準構文と標準構文の対応表は、Zennのフル記事にまとめています。
この記事のような現場のTIPSを、Db2運用の全体像として12章に体系化しました。公式マニュアルには載らない「あのとき知っていれば」を減らすための1冊です。
現場で引ける Db2 の教科書
現場で引ける!Db2実践エンジニア・バイブル
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ―― そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にまとめました。書いてあることはすべて実際の現場で経験したことです。
アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集 ―― 全12章+運用シェルスクリプト集。