DB2 4 min read

Db2で列名が通らない ― WHEREの別名や二重引用符で落ちるときの逆引き

列は確かにあるのに、次のエラーで 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のフル記事にまとめています。

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

Db2のSQL0206N ― 列が「not valid in the context」になる原因とメッセージの読み方


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

他のRDBMSから移ってきたSQLは、動いたとしてもDb2で速い書き方とは限りません。実行計画の読み方、パッケージキャッシュからのボトルネックSQLの特定、書き換えの勘所を、本書 第9章「SQLチューニングの極意」で扱っています。

現場で引ける Db2 の教科書

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

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

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

Zennで読む →