DB2 4 min read

Db2で親子の表に追加・削除できない ― 外部キー制約エラーの逆引き

外部キー(参照制約)を付けた表では、次の2つのエラーがよく出ます。

SQL0530N  The insert or update value of the FOREIGN KEY
"DB2INST1.EMPLOYEE.RED" is not equal to any value of the parent key of the
parent table.  SQLSTATE=23503

SQL0532N  A parent row cannot be deleted because the relationship
"DB2INST1.PROJECT.FK_PROJECT_1" restricts the deletion.  SQLSTATE=23001

上は SAMPLE データベースで、存在しない部門の社員を登録したときと、部門 A00 を消そうとしたときのものです。

まず見る(結論)

引用符の中は スキーマ.子の表.制約名 です。親を消そうとして出たエラーでも、表示されるのは子の表です。制約名で SYSCAT.REFERENCES を引くと、親の表と列が分かります。

SELECT TABNAME, REFTABNAME, FK_COLNAMES, PK_COLNAMES, DELETERULE
  FROM SYSCAT.REFERENCES WHERE CONSTNAME = 'FK_PROJECT_1'

親を消す前は、WHERE REFTABNAME = '親の表' で親を参照している制約を全部引きます。メッセージに出るのは止めた制約1つだけです。

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

症状 よくある原因 まず打つ手
子への INSERT / UPDATE で SQL0530N 親に無い値を入れた 先に親の行を作る。親が決まらないなら NULL
親の DELETE で SQL0532N 子が参照している 子を消すか付け替える。ON DELETE CASCADE / SET NULL を検討
親キーの UPDATE で SQL0531N 子が参照している 子を付け替えてから親を変える
親の TRUNCATE で SQL20356N 参照制約の親は TRUNCATE できない DELETE を使う
制約名が SQL2610... のような数字 名前を付けずに作った外部キー SYSCAT.REFERENCES で引く
LOAD した子の表が SQL0668N 理由コード 1 LOAD は外部キーを検査しない 例外表を作って SET INTEGRITY ... FOR EXCEPTION
親の表を DROP したら外部キーが消えていた 親の DROP TABLE は通り、子の外部キーも一緒に消える DROP 前に外部キーの定義を控える

外部キーの列が NULL の行は検査されず、親が無くても入りました。SQL0532N の SQLSTATE は、削除規則が NO ACTION(既定)だと 23504、RESTRICT だと 23001 でした。

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

SAMPLE の DEPARTMENT を参照する3つの制約が削除規則ごとにどう振る舞うか、LOAD で入った孤児行を SET INTEGRITY で例外表に移す手順、親の DROP TABLE の結果は、Zennのフル記事にまとめています。

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

Db2のSQL0530N・SQL0532N ― 外部キー違反を制約名から特定して直す


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

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

現場で引ける Db2 の教科書

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

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

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

Zennで読む →