列は確かにあるのに、次のエラーで SQL が落ちることがあります。
SQL0206N "ANNUAL" is not valid in the context where it is used. SQLSTATE=42703
このメッセージには表名が出ません。引用符の中の名前が、列名なのか、別名なのか、値なのかで原因が分かれます。
まず見る(結論)
引用符の中の名前が SQL のどこに書いたものかを確認し、列名ならカタログで実在を確かめます。
# その列がどの表にあるか(大文字小文字を無視して探す)
db2 "SELECT TABSCHEMA, TABNAME, COLNAME FROM SYSCAT.COLUMNS WHERE UPPER(COLNAME) = 'WORKDEPT'"
# 表関数(MON_GET_*)が返す列の一覧
db2 "DESCRIBE SELECT * FROM TABLE(MON_GET_INSTANCE(-2))"
症状 → 原因 → 対処(逆引き)
| 症状 | よくある原因 | まず打つ手 |
|---|---|---|
引用符の中が SELECT で付けた別名 |
別名を WHERE / GROUP BY / HAVING で使った |
式をそのまま書くか、導出表で包んで外から参照する。ORDER BY では別名を使える |
引用符の中が検索したい値("HAAS") |
文字列を二重引用符で囲んだ | 'HAAS' と単一引用符にする |
書いた列名が大文字で出る(UserName → "USERNAME") |
列が "UserName" と引用符付きで作られている |
SQL でも "UserName" と書く |
引用符の中が EMPLOYEE.EMPNO |
FROM EMPLOYEE E と相関名を付けたのに表名で修飾した |
E.EMPNO と書く |
引用符の中が SYSTIMESTAMP / ROWNUM |
他の DB の疑似列 | CURRENT TIMESTAMP / FETCH FIRST n ROWS ONLY |
MON_GET_* や SYSIBMADM のビューで出る |
列名を推測で書いた(OPTYPE など) |
DESCRIBE か SYSCAT.ROUTINEPARMS(ROWTYPE='R')で列名を確かめる |
表が見つからない場合は SQL0204N、同じ列名が結合した2つの表にある場合は SQL0203N、関数が見つからない場合は SQL0440N です。
それでも切り分けられないとき(実機ログつきの詳解)
別名が使える句と使えない句の実測、SYSDATE など他 DB の書き方がどれだけ通るか、監視関数で踏みやすい列名の一覧は、Zennのフル記事にまとめています。
他のRDBMSから移ってきたSQLは、動いたとしてもDb2で速い書き方とは限りません。実行計画の読み方、パッケージキャッシュからのボトルネックSQLの特定、書き換えの勘所を、本書 第9章「SQLチューニングの極意」で扱っています。
現場で引ける Db2 の教科書
現場で引ける!Db2実践エンジニア・バイブル
Db2はRDBMS市場でシェア数%。情報が少なく、頼れるのは膨大な公式マニュアルだけ―― そんな現状を変えたくて、「なぜこの値にするのか」「この障害のとき次に何を見るのか」という、マニュアルに載っていない現場の文脈を1冊にまとめました。書いてあることはすべて実際の現場で経験したことです。
アーキテクチャ/構成パラメーター選定/セキュリティ/バックアップ・リカバリ/HADR/pureScale/日常点検の自動化/メモリ・ロック競合/SQLチューニング/RUNSTATS・REORG/MON_GET監視/現場の難題集 ―― 全12章+運用シェルスクリプト集。