DB2 4 min read

Db2でページングを書く ― OFFSETとFETCH FIRSTがSQL0104Nになるときの逆引き

他の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記事にあります。

まず見る(結論)

OFFSETFETCH FIRST よりに書きます。逆に書くと SQL0104N です。

# 20件飛ばして10件(この順序が正しい)
db2 "SELECT ... FROM ... ORDER BY ... OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY"

ORDER BY を省くと返る行が毎回同じとは限りません。ページングでは必ず付けます。

症状 → 原因 → 対処(逆引き)

症状 よくある原因 まず打つ手
SQL0104NFETCH FIRST … が unexpected token FETCH FIRSTOFFSET より先に書いている OFFSET y ROWS FETCH NEXT x ROWS ONLY の順に直す
LIMIT が普通に動いてしまう 11.1 以降は常時有効。仕様どおり そのままでも動くが、公式は非標準としている。標準構文へ寄せる
DB2_COMPATIBILITY_VECTOR を立てろ」と書かれた情報が見つかる 10.5 以前の情報。11.1 で常時有効になりビットは無視される db2set は不要。バージョンを先に確認する
同じ問い合わせなのに毎回違う行が返る ORDER BY が無い ORDER BY を付ける。LIMITFETCH FIRST も順序は保証しない
LIMIT 5, 5 がどちらの引数か分からない MySQL と同じ「5件飛ばして5件」 OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY に書き換える
OFFSET が使えない古い環境 バージョンが古い ROW_NUMBER() OVER (ORDER BY …) を副問い合わせにして範囲で絞る

FIRSTNEXTROWROWS はどちらでも通るので、そこを直しても解決しません。

いちばん多い真因:句の順序

エラーメッセージの Expected tokens may include は候補を1つしか出さないため、順序の誤りに対しては手がかりになりません。公式の offset-clause のページにも順序の制約は書かれていないので、ドキュメントを引いても辿り着きにくいところです。SQL0104N を見たらまず順序を疑うのが早道です。

それでも切り分からないとき(実機ログつきの詳解)

11.5.5.1/11.5.9/12.1.4 での実測比較、互換ベクターの説明が11.1で書き換わった経緯、非標準構文と標準構文の対応表は、Zennのフル記事にまとめています。

▶ Zennで続きを読む(無料)

Db2でLIMITは使える ― 公式が「使うな」と書く非標準構文と、OFFSETの順序制約


実機ログつきの詳解を読む →

この記事のような現場のTIPSを、Db2運用の全体像として12章に体系化しました。公式マニュアルには載らない「あのとき知っていれば」を減らすための1冊です。

現場で引ける Db2 の教科書

現場で引ける!Db2実践エンジニア・バイブル

Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ―― そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にまとめました。書いてあることはすべて実際の現場で経験したことです。

アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集 ―― 全12章+運用シェルスクリプト集

Zennで読む →