外部キーの循環の検出
外部キーの循環を、表の向きつきで洗い出す。
CREATE TABLE と ALTER TABLE の外部キー(REFERENCES / FOREIGN KEY)を貼り付けると、表を頂点とした参照の向きから循環の候補を探します。自己参照も含め、NULL 許可の列や DEFERRABLE で緩和できる可能性を併記します。入力はブラウザの外へ送信しません。
テーブル定義を貼り付けて外部キーの循環を探す
入力した内容は送信されません。貼り付けた文字や選んだファイルは、お使いのブラウザの中だけで処理します。本サイトのサーバーや第三者へ送信・保存しません(通信を禁止する設定でページを配信しています)。
結果
エラー 0 件・警告 1 件・情報 0 件
指摘(エラー・警告・情報)
- 警告 1 行目 a・b の外部キーが循環している候補です(a(b_id) → b、b(a_id) → a)。外部キーは参照先の行が存在していることを求めるため(CREATE TABLE 文書の REFERENCES)、どの表から作り・入れるかが決まらなくなります。緩和する条件が見当たらないため、どれかの外部キーを NULL 許可にする、DEFERRABLE にする、または設計を見直してください。「候補」の検出であり、実際の登録順は業務の流れで確認してください。
| 表の数 | 2 個 |
|---|---|
| 外部キーの数 | 2 本 |
| 複数の表にまたがる循環 | 1 組 |
| 自己参照 | 0 表 |
循環の候補
| # | 循環に含まれる表 | 参照の向き(子 → 親) | 緩和の見込み |
|---|---|---|---|
| 1 | a ⇄ b | a(b_id) → b / b(a_id) → a | 全ての辺が NULL 不可・即時検査のため、緩和されにくい |
初期表示は入力例「2 つの表が互いを参照する」の結果です。入力を変えるとその場で処理し直します。判定の根拠は仕様と根拠にまとめています。
ご利用にあたって
- 結果は字句の読み取りにもとづく確認で、実際のデータベースでの解釈を保証するものではありません。
- ドキュメントは PostgreSQL License で公開されています。このサイトはその内容を要約して参照しており、転載はしていません。
使い方
- データベースの定義(CREATE TABLE と外部キーの ALTER TABLE)を入力欄に貼り付けます。
- 表の「循環に含まれる表」と「参照の向き」を確かめ、どの参照を切れば輪が解けるかを考えます。
- 「緩和の見込み」で NULL 許可の列や DEFERRABLE の辺があれば、その参照から見直します。
入力例と結果
代表的な入力・境界の入力・壊れた入力の例です。例ごとに入力・出力・指摘と、その結果になる理由(検算)を載せています。
| 入力例 | 結果 |
|---|---|
| 2 つの表が互いを参照する | エラー 0 件・警告 1 件・情報 0 件 |
| 親を指す自己参照 | エラー 0 件・警告 0 件・情報 1 件 |
| ALTER TABLE で足した 3 表の輪 | エラー 0 件・警告 1 件・情報 0 件 |
| DEFERRABLE で緩和できる循環 | エラー 0 件・警告 1 件・情報 0 件 |
| 循環のない親子の 2 表 | エラー 0 件・警告 0 件・情報 1 件 |
このツールでできないこと(制約)
- 完全な SQL の構文解析はしません。貼られていない表の参照は先をたどれず、循環を見逃すことがあります(その旨を情報で示します)。
- 「候補」の検出です。業務の流れ(どの表に先にデータが入るか)までは判定しません。
- 自己参照(階層構造の親子)は多くの設計で普通の形のため、複数の表にまたがる循環とは区別して情報で示します。
- CREATE TABLE ... AS などの列定義のない形は読みません。ALTER TABLE は ADD [CONSTRAINT] FOREIGN KEY だけを読みます。
よくある質問
循環していると何が困りますか?
外部キーは参照先に対応する行があることを求めるため(CREATE TABLE 文書)、輪になった表はどちらの行を先に入れても検査に引っかかり得ます。NULL の許可や検査の遅延などで順序を作る必要があります。
自己参照は問題ですか?
階層構造(親の ID を持つ表)では普通の形です。親の列が NULL を許可していれば、最上位の行を先に入れられます。情報として示すだけで、警告にはしません。
貼り付けた SQL はどこかに送られますか?
送られません。処理はお使いのブラウザの中だけで行い、ページは通信を禁止する設定(CSP の connect-src)で配信しています。