erdscope #

erdscope は、稼働中の MySQL または PostgreSQL データベースから自己完結型のインタラクティブな ER 図と、 必要に応じてExcel テーブル定義書を生成します。単一の Python ファイル (erd.py、インストール不要)として配布され、必須の依存関係はゼロです。

データベースが唯一の真実源です — テーブル、カラム、コメント、インデックス、実際の外部キーはすべて データベースのカタログ(MySQL では information_schema、PostgreSQL では pg_catalog)から取得されます。アプリケーションコード(Rails、Prisma、Django)を --models で任意に重ね合わせることで、データベース単体では表現できない関連のセマンティクス (has_many :through、ポリモーフィック関連など)を追加できます。

ライブデモを試す → — コメント・インデックス・実際の FK・推測された関連を含む小さな EC サイトのスキーマです。 デモの内容はすべて単一の自己完結型 HTML ファイルであり、あなた自身の図も同じ方法で生成されます。

users・orders・products などのテーブルとその関連を示す erdscope の ER 図

データベースの真実

テーブル、カラム(完全な SQL 型、デフォルト値、extra 属性)、コメント、インデックス、実際の FK 制約 — すべてデータベースから直接読み取ります。

コード側のセマンティクスを重ね合わせ

--models は Rails / Prisma / Django の関連をマージします。association ですでにカバーされている DB FK は重複排除され、残りには「DB FK」バッジが付きます。

インタラクティブな探索

深度と方向を指定したフォーカス、2段階の非表示、テーブル・カラム検索、名前付きビュー、共有リンク。

読みやすいレイアウト

ビューポートを考慮した自動配置、ドラッグ時のスナップ、複数選択での整列/分布、Auto-tidy、undo/redo。

エクスポート

PNG、SVG、Mermaid、PlantUML — それぞれコピーとダウンロードに対応 — に加えて Excel ワークブック。

論理名

テーブルの DB コメントは検索可能な「論理名」を兼ね、物理名と並べて表示されます。

インストール・必要要件 #

PyPI からインストールすると erdscope コマンドが使えるようになります。

pip install erdscope        # または: pipx install erdscope
erdscope mysql://readonly@127.0.0.1:3306/myapp -o erd.html

何もインストールしたくない場合は、erd.py が依存ゼロの単一ファイルなので、ダウンロードして任意の Python 3.9 以降で実行できます。このマニュアル全体で 使っている erdscope コマンドと完全に同じ動作です。

curl -O https://raw.githubusercontent.com/orapli/erdscope/main/erd.py
python3 erd.py mysql://readonly@127.0.0.1:3306/myapp -o erd.html

必要要件は厳密には Python 3.9 以降のみです。ツールをより使いやすくする2つのライブラリが ありますが、どちらも完全にオプションです — インストールされていなくても erdscope は正しくフォールバック して動作します。pip でインストールした場合は extras でまとめて導入できます (pip install 'erdscope[mysql]' で PyMySQL、'erdscope[postgres]' で psycopg、 'erdscope[yaml]' で PyYAML、'erdscope[all]' で全部)。

ライブラリ用途未インストールの場合
PyMySQLMySQL 接続mysql CLI(PATH 上にある必要あり)へのシェルアウトにフォールバック — トラブルシューティング参照
psycopg(または psycopg2)PostgreSQL 接続psql CLI(PATH 上にある必要あり)へのシェルアウトにフォールバック — トラブルシューティング参照
PyYAML.yml/.yaml 設定ファイルの読み込み.json 設定ファイルであれば依存関係なしで動作します。PyYAML がない状態で .yml/.yaml を指定した場合は、明確なエラーで終了します

--excel 出力には上記のどれも不要です — スプレッドシート用パッケージではなく、 Python 標準ライブラリの zipfile/XML 処理を使って直接書き出しています。

もう2つのライブラリはテストスイート専用で、実行時には一切使われません: openpyxl(ユニットテストで --excel 出力をラウンドトリップ検証)と Playwright(ブラウザ E2E スイートで生成 HTML を操作)です。 どちらも図の生成・閲覧には不要です。

クイックスタート #

erdscope mysql://readonly@127.0.0.1:3306/myapp_production -o erd.html

# アプリケーションコードから解析した関連セマンティクスで拡張(任意)
erdscope mysql://readonly@127.0.0.1:3306/myapp_production \
        --models /path/to/rails/app -o erd.html

# テーブル定義書も同時に出力
erdscope mysql://readonly@127.0.0.1:3306/myapp_production \
        --excel table_definitions.xlsx -o erd.html

# PostgreSQL の場合も同じ — スキーマはデフォルトで public、?schema=name で上書き可能
erdscope postgres://readonly@127.0.0.1:5432/myapp_production -o erd.html

生成された erd.html を任意のブラウザで開いてください — すべてが1ファイルに内包されている ので、メールで送ったり、Wiki にコミットしたり、共有ドライブに置いたりできます。

パスワードの扱い

読み取り専用の DB アカウントを使い、接続 URL にパスワードを書かないでください — シェル履歴に残ってしまいます。erdscope は次の順序でパスワードを解決します。

  1. URL に埋め込まれたパスワード(mysql://user:pass@host/db)— 実運用では避けてください。
  2. MYSQL_PWD(MySQL)/ PGPASSWORD(PostgreSQL)環境変数(設定されている場合)。
  3. それ以外で、標準入力が対話的な端末であれば、隠し入力のパスワードプロンプト (argv にもシェル履歴にも残りません)。
非対話実行の場合(CI・スクリプト・パイプ) erdscope は標準入力が TTY のときだけプロンプトを出します。スクリプトや CI ジョブの中ではプロンプトを 完全にスキップし、ブロックすることなく、手元にあるパスワード(無い場合もあります)でそのまま接続を試みます。 それが間違っていれば通常の接続エラーメッセージが出るだけで、ハングすることはありません。 user:@host/db(明示的な空パスワード)と書いた場合も「パスワードが指定された」扱いになり、 プロンプトはスキップされます。PostgreSQL の場合、プロンプトに空行で答えると PGPASSWORD は 未設定のままになるため、libpq 自身の ~/.pgpass 参照がそのまま働きます。

踏み台サーバー / SSH トンネル経由

ssh -N -L 3307:db-host:3306 bastion &
erdscope mysql://readonly@127.0.0.1:3307/myapp_production -o erd.html

CLIリファレンス #

この表は erd.pyargparse 定義に基づいて検証済みです — 手元のバージョンと 一致しているか、いつでも erdscope --help を実行して確認できます。

erdscope [mysql://user@host/db | postgres://user@host/db] [options]
引数説明
mysql://… または postgres://…位置引数。データベース接続 URL。postgres:// は任意の ?schema=name(デフォルト public)を受け付けます。postgresql:// という表記も使えます。設定ファイルの engine/host/port/user/database から組み立てることもできます(パスワード用のフィールドはありません — 設定ファイル参照)。
-o, --output OUTPUT出力 HTML ファイル(デフォルト: erd.html
--models PATHアプリケーションコードから解析した関連セマンティクスをマージ: Rails プロジェクト(または app/models ディレクトリ)、schema.prisma、または Django プロジェクト — ソースは自動判別されます
--excel FILE.xlsxテーブル定義書も出力: 概要シート+テーブルごとのシート
--excel-template FILE.xlsxワークブックの色/フォント/罫線をテンプレート .xlsx から上書き — 5セル契約についてはエクスポートを参照。--excel なしでは効果がなく(警告が出ます)
--max-rows Nテーブルごとにスクロールなしで表示するカラム数の上限(デフォルト: 15)
--only 'user*,post*'指定した glob パターンに一致するテーブルのみを含める。繰り返し指定可、カンマ区切りリストも可
--exclude '*_logs'指定した glob パターンに一致するテーブルを除外。--only と同じ構文
--infer-fk実際の association/FK による裏付けがない場合に、*_id というカラム名から関連を推測する。デフォルトはオフ — トラブルシューティング参照
--table-map 'Widget=crm_widgets'Rails 専用: 静的解析でテーブルを特定できないモデルのテーブルを上書き。繰り返し指定可、カンマ区切りリストも可 — トラブルシューティング参照
--config PATH設定ファイルからデフォルト値を読み込む。指定がない場合はカレントディレクトリの .erdscope.json/.yml/.yaml が自動検出されます
--no-configカレントディレクトリに .erdscope.* があっても自動検出をスキップする

設定ファイル #

フラグの一覧が長くなってきたら、代わりに設定ファイルにまとめましょう。ツールを実行する場所に .erdscope.json(PyYAML がインストールされていれば .erdscope.yml/.yamlも可) を置くと自動的に読み込まれます — --config は不要です。ほとんどのキーは上記の CLI オプション に対応します(snake_case)。engine/host/port/user/database (DB 接続情報 — engine はデフォルトの "mysql""postgres" を指定し、 "postgres" にするとデフォルトポートも 5432 に切り替わります)と relations (手動 FK 宣言)は設定ファイル専用で、対応する CLI オプションはありません。

{
  "host": "127.0.0.1",
  "port": 3306,
  "user": "readonly",
  "database": "myapp_production",

  "output": "erd.html",
  "models": "../myapp",
  "max_rows": 15,
  "infer_fk": true,
  "only": ["user*", "post*"],
  "table_map": { "Widget": "crm_widgets" },

  "relations": [
    { "table": "orders", "column": "buyer_code", "references": "users" },
    { "table": "profiles", "column": "person_ref", "references": "users",
      "one_to_one": true, "name": "owner" }
  ]
}

明示的な CLI フラグは常に同名の設定キーより優先され、値を完全に置き換えます(only のような リスト値も設定ファイルの内容とマージされることはありません)。意図的に password/url キーは存在しません — host/port/user/database が 別々のフィールドになっているのは、パスワードを書き込める場所をそもそも作らないためです。CLI と同じように MYSQL_PWD/PGPASSWORD~/.my.cnf/~/.pgpass、または 対話プロンプトで指定してください。

すべてのキーを説明した完全な注釈付きサンプルは erdscope.example.yml (ライブデモのスキーマがベース)を参照してください。

手動での関連宣言

relations は、他のどのソース(実際の FK 制約、*_id による名前推測、 --models によるコード解析)でも見つけられない関連を宣言します — 命名が特殊なカラムや、 gem 提供の concern・動的な association によって静的解析から隠れているものなどです。 --models をまったく使わなくても単独で機能し、設定ファイルだけで完全な関連グラフを 組み立てることもできます。優先順位はコード解析による association と同じです — --infer-fk より先に適用される(そのため該当カラムに対する誤った名前ベースの推測も抑制します)ほか、同じカラムに 対する実際の DB FK 制約よりも優先されます。relations 内の未知のテーブル/カラム/参照先は 常にタイプミスとみなされ、サイレントに無視されるのではなく、必ずハードエラーになります。

設定値の型に注意 キーは名前だけでなく、erdscope 実行前に型もチェックされます。only/exclude は 単なる文字列ではなく文字列のリストである必要があります(文字列のままだと1パターンとしてではなく 文字単位でマッチしてしまいます)。infer_fk は文字列の "true"/"false" ではなく、真の JSON boolean である必要があります。型が一致しない場合、以前は図がサイレントに間違った ものになっていましたが、現在は明確なエラーとして事前に検出されます — エラーに遭遇したら、上の例と 照らし合わせて値の型を確認してください。

ビューアガイド #

以下はすべて、生成された HTML ファイル自体 — つまりブラウザで開く図そのもの — について説明しています。 CLI については触れません。読みながらライブデモで 実際に各コントロールを試してみてください。

ペイン #

ページは3つのペインで構成されています: Tables(左 — チェックボックス付きの テーブル一覧と検索)、diagram(中央の図)、Details(右 — 選択中の対象のカラム・インデックス・関連)です。

  • リサイズ — サイドペインと図の間にある細い区切り線をドラッグします(幅は140px〜560pxの範囲に制限されます)。
  • 折りたたみ / 展開 — ペインのタイトルバーにある ◀/▶ ボタンで折りたたみ、その端に現れる小さなタブから再表示できます。
  • ペイン幅と折りたたみ状態は、次にこの図を開いたときのためにブラウザに記憶されます。

フォーカスと探索 #

テーブル(一覧上でもキャンバス上でも可)をダブルクリックするとそのテーブルに フォーカスします — 図はそのテーブルと関連テーブルだけに絞り込まれます。フォーカス中のテーブルを再度 ダブルクリックするか、Esc を押すか、✕ Back to overview / Exit focus ボタンのいずれかで全体表示に戻ります。

フォーカス中は上部のバーに 🔍 Focused: <テーブル名> (depth <深度>, <方向>) と表示されます。左ペインのチェックボックスは全体表示にのみ影響し、フォーカス中のビューには影響しません (その旨のヒントも表示されます)。Apply to checks は、フォーカスビューに 現在表示されているテーブルをそのまま全体表示側のチェック状態に反映してから、フォーカスを終了します。

フォーカス(および後述の Auto-expand)が何を引き込むかは、次の3つのコントロールで決まります。

コントロール選択肢効果
Depth(深度)1 / 2 / 3 / フォーカス中のテーブルから何ホップ先の関連まで含めるか
Direction(方向)Both / Deps / DependentsDeps はこのテーブルが依存しているもの(FK で参照している親)をたどります。Dependents はこのテーブルに依存しているもの(このテーブルを参照している子)をたどります。Auto-expand の設定に関わらず、各テーブルの ボタンにもこの設定が適用されます。
Auto-expand(自動展開)ツールバーのチェックボックスオンにすると、全体表示でチェックされているすべてのテーブルが起点となり、現在の深度/方向の範囲でその関連テーブルを引き込みます。フォーカスモードでは、この設定に関わらず常にフォーカス中のテーブルから展開します。

各ノードには ボタンもあり、そのテーブルの直接の関連テーブルだけを(現在の方向設定に 従って)一時的に引き込みます — それ自体が新たな展開の起点になることはないため、1回のクリックでスキーマ 全体が芋づる式に広がることはありません。

orders テーブルに depth 2・Deps 方向でフォーカスした状態。orders とその上流の依存先(shipments、users、addresses)が表示されている

orders にフォーカス — depth 2、Deps 方向。フォーカスバーに両方の設定が表示されています。ツールバーの depth/direction コントロールは、フォーカス中か Auto-expand がオンのときだけ表示されます。

テーブルの非表示 — 2段階 #

erdscope にはテーブルを表示から外す独立した2つの方法があり、強さが異なります。

Exclude(除外)Ban(禁止/完全非表示)
トリガー一覧のチェックを外す、またはノードの ボタン一覧の行にある 🚫 ボタンのみ
強さ軽い — Auto-expand によって他のテーブルの関連先として再び現れたり、チェックを入れ直したり、他のテーブルの から戻ってくることがあります強い — 禁止解除するまで、Auto-expand であっても二度と表示されません
元に戻すチェックを入れ直すその行で再度 🚫、または何か禁止されている間だけ表示される赤いバナー内の Unban all

フォーカス中のテーブルを禁止するとフォーカスは終了します。除外セットと禁止セットはどちらもブラウザに 記憶され、名前付きビューや共有リンクにも含まれます。

左ペインに赤い「banned: 1 table(s)」バナーと Unban all リンクが表示され、その下に products の行が取り消し線付きでグレーアウトしている

一覧の 🚫 ボタンで products を禁止した状態 — 取り消し線が引かれ、チェックボックスはロックされ、上の赤いバナーにカウントされます。

erdscope には性質の異なる2つの検索ボックスがあります。

フィルタ(左ペイン、"Search tables / columns…")

テーブル名・カラム名・カラムのコメント・テーブルのコメントに一致します。入力するたびにテーブル一覧をその場でフィルタします。Enter を押すと図の中の最有力候補にジャンプし(表示から外れていれば戻し)、一致したカラムをハイライトします。

ハイライト(ツールバー、"Highlight…")

一致対象はフィルタと同じですが、表示からは何も取り除きません — 一致したテーブル/カラムに印を付け、それ以外を薄暗くするだけの、あくまでオーバーレイです。Enter/Shift+Enter で次/前の一致に移動します。選択状態と違い、ハイライトの検索語は PNG/SVG エクスポートにも引き継がれます。

どちらのボックスも、独立した Aa(大文字小文字を区別)と .*(正規表現)の 切り替えボタンを持っています — フィルタ側で正規表現モードを有効にしても、ハイライト側には影響しません。

ツールバーのハイライトボックスに 'user' と入力し、一致したテーブルとカラムがアンバー色の枠で示され、無関係なテーブルは薄暗く表示されている

user をハイライト — 一致したテーブル/カラムにアンバー色の枠が付き、それ以外は薄暗くなりますが、図から取り除かれるものは何もありません。

レイアウトと選択 #

  • パン — 何もないキャンバス上をドラッグするか、2本指でスクロールします。
  • ズーム — ピンチ操作 / Ctrl+スクロール、またはツールバーの + / / 1:1 / ⊡ Fit ボタン。
  • 複数選択 — クリックで1つだけ選択、Shift-クリックまたは Ctrl/Cmd-クリックで選択に追加/削除、何もないキャンバス上から Shift-ドラッグでラバーバンド選択。何もないキャンバスをクリックするとすべて選択解除されます。
  • ドラッグで移動 — 選択中のテーブルをドラッグすると、選択中のもの全体が一緒に動きます。ドラッグ中の端は近くのテーブルの端/中心に数ピクセル以内でスナップし、赤いガイド線(Figma のような)が表示されます — ドラッグ中に Alt を押すとスナップを無効化できます。
  • 整列 / 分布 — 2つ以上選択すると、右ペインに ⇤ Left / ⇡ Top / ↔ Center / ↕ Middle が表示されます。3つ以上選択すると ⇔ Horiz. / ⇕ Vert. の分布も使えるようになります(両端のテーブルは固定したまま、間の間隔を均等にします)。
  • Auto-tidy — 表示中のテーブル集合が変わるたびに、レイアウトを自動的に再配置・再フィットするツールバーのトグルです。 ボタンは Auto-tidy の設定に関わらず、その場で即座に再配置します。
  • Undo/redo — ツールバーの / ボタン、または Ctrl/Cmd+Z / Ctrl/Cmd+Shift+Z(もしくは Ctrl/Cmd+Y)。対象はテーブルの位置変更のみです。フォーカスの開始/終了や保存済みビューの読み込みはレイアウト全体を置き換えるため、その際に履歴はクリアされます。
payments・shipments・order_coupons の3テーブルが青くハイライトされて複数選択され、右ペインの Align と Distribute のボタングループが両方とも有効になっている

3テーブルを選択した状態 — 3つ以上選択すると、Align(整列)とDistribute(分布)の両方が使えるようになります(2つの選択では Align のみ有効)。

カラム表示モード #

ツールバーのコントロールで、すべてのテーブルの表示を All(全カラム)、 PK/FK(主キー・外部キーのみ)、Name(テーブル名のみ、カラムなし)の いずれかに切り替えられます。各ノードにも独自の ボタンがあり、そのテーブルだけの 表示モードを個別に切り替えられます — 1つの大きなテーブルだけを詳しく見つつ、残りはコンパクトに保ちたい ときに便利です。全体のモードを切り替えると、テーブルごとの個別設定はリセットされます。

論理名 #

テーブルの DB コメントは、検索可能な「論理名」を兼ねます — 例えば users(Customer accounts) のように表示されます。ツールバーのトグルで、ライブビューの表示を Both / Physical / Logical のいずれかに切り替えられます。エクスポートにはエクスポートパネル内に独自の、 独立した Both/Phys./Log. の選択肢があります(エクスポート参照)— 今見ている表示を 変えても、エクスポートされる内容は変わりません(その逆も同様です)。

名前付きビューと共有 #

💾 Save は名前の入力を求め、現在のビューをその名前で保存します (既存の名前を指定すると上書きされます)。保存されるビューには、除外テーブル、禁止テーブル、 Auto-expand、depth、direction、カラム表示モード、そして現在表示中の各テーブルの位置が含まれます。

保存済みビューに含まれないもの 名前表示モード(Both/Physical/Logical)、ダークモード、max-rows、ラベルの表示/非表示は、保存済みビューや 共有リンクには含まれません — これらはページ全体に対する別個の設定です。

Views… ドロップダウンから保存済みビューを読み込むか、🗑 で削除できます。🔗共有リンクをコピーします — 現在のビューを JSON エンコードしてページ自身の URL に付加したものです。そのリンクを開くと自動的に 同じビューが再現されるので、PR の説明文やチャットにそのまま貼り付けられます。

エッジの種類 #

図には3種類の関連が反映されますが、キャンバス上の線のスタイルは2種類しかなく、 残りは Details ペインのバッジで区別されます。

  • 実線 — デフォルト: --models による宣言済みの association、または実際の DB FK 制約。キャンバス上ではこの2つは同じ見た目です。Details ペインの関連一覧では、制約に基づくエッジには DB FK バッジが付き、単なる宣言済み association にはバッジが付きません。
  • 破線 — 多対多の関連(join テーブル経由でしか到達できないもの / has_and_belongs_to_many / through。直接の belongs_to/has_one がない場合)。
  • 薄い点線--infer-fk による名前ベースの推測。そのエッジを支える association がすべて推測によるものである場合のみ表示されます。Details ペインには inferred バッジが付きます。カラム一覧の「FK」バッジは、推測だけでは決して付与されません — 実際の association がある場合のみです。

manual バッジは、設定ファイルの relations から来た association を示します。(破線のエッジとは別に)破線のノードの枠は、そのテーブルが 直接チェックされたのではなく Auto-expand によって引き込まれたことを示します。

キーボードショートカット #

これが全リストです — ズーム、保存、エクスポートにショートカットはありません。ツールバーの ? ボタンから、このショートカット一覧の簡易版と、マウス操作の説明、 そしてこのマニュアルへのリンクをビューア内で直接確認できます。

キー動作
Esc状況に応じて、次の優先順で実行されます: 開いているツールバーのメニュー(Export または ? help)を閉じる → フィルタボックスにフォーカスがあり空でなければクリア → ハイライトボックスも同様にクリア → フォーカスモードを終了 → それ以外の場合はすべての選択を解除
Ctrl/Cmd+Z直前のレイアウト変更を取り消す
Ctrl/Cmd+Shift+Z または Ctrl/Cmd+Yやり直す
Enter(フィルタボックス内)最有力候補のテーブル/カラムにジャンプ
Enter / Shift+Enter(ハイライトボックス内)次/前の一致に移動

ダークモード #

🌙 ツールバーボタンで図のダークモードを切り替えます。これは手動での切り替えのみです — ビューアは OS/ブラウザのカラースキームを自動的には追従しません — 選択内容は次回開いたときのために ブラウザに記憶されます。エクスポート(PNG/SVG)は、現在どちらのモードで見ていても常にライトパレットで 描画されます。

印刷 #

専用の印刷ボタンはありません — ブラウザ自体の印刷コマンド(Ctrl/Cmd+P)を使ってください。 印刷用のスタイルシートがすべてのクロム(ペイン、ツールバー、凡例、フォーカスバー)を自動的に隠し、 プレーンな白背景に図だけを残します。

エクスポート #

ツールバーの ⬇ Export ボタンを押すと、上部に画像オプション、下部に フォーマットごとの行が並んだパネルが開きます。各行には CopyDownload の別々のボタンがあります — 画像をクリップボードに書き込めるブラウザであっても、 ファイル保存という選択肢を奪わないよう、コピーとダウンロードは意図的に別のアクションとして分離されています。

エクスポートパネルが開いた状態。Join-table labels がチェック済み、root badges が未チェック、Names: Both の画像オプションの下に、PNG・SVG・Mermaid・PlantUML の4つのフォーマット行が Copy と Download ボタンとともに並んでいる

エクスポートパネル: 上部に画像オプション、下部にフォーマットごとの Copy/Download 行。

画像オプション PNG / SVG のみ

これら2つのチェックボックスと1つのトグルは、PNG と SVG のエクスポートにのみ適用されます — Mermaid、PlantUML、Excel ワークブックには影響しません。

  • Join-table labels(⇢)— デフォルトでオン。オフにすると、エクスポートした画像から 「join テーブル経由」を示す小さなエッジラベルを除外します。
  • ✓ root badges — デフォルトでオフ。オンにすると、エクスポートした画像から Auto-expand の起点を示すチェックマークバッジを除外します。
  • Names: Both / Phys. / Log. — ツールバーにあるライブビュー自体の名前表示モードとは 独立しています(ビューアガイド参照)。自分は物理名で見ながら、 ステークホルダー向けの資料には論理名だけをエクスポートする、といった使い方ができます。

ライブのハイライト検索は、PNG と SVG のどちらのエクスポートにも引き継がれます (常に取り除かれるテーブル/エッジの選択状態とは異なります)— ハイライトされた図をそのまま ドキュメントに貼り付けられるようにするためです。

PNG

図をまず SVG として描画し、オフスクリーンの <canvas> に読み込んでから、 最大2倍のスケールでラスタライズします — canvas のサイズが約8000pxを超えそうな場合は (それより下に)クランプされます。ブラウザは canvas サイズの上限をそれよりずっと低く設定していることが多く、 超えると toBlob() がサイレントに失敗するためです。Copy は直接クリップボードに 書き込み、ブラウザが画像をクリップボードに書き込めない場合は自動的にファイルダウンロードにフォールバック します。Download は常にファイルを保存します。

SVG

Copy は生の SVG マークアップをテキストとしてコピーします(失敗した場合はダウンロードに フォールバック)。Download.svg ファイルを保存します。エクスポートされる SVG は、ライブビューの現在のダーク/ライト設定に関わらず、常にライトカラーパレットを使用します。

Mermaid

現在表示されているものをすべてカバーする erDiagram ブロックを生成します — フォーカス、非表示、除外の各状態がすべて反映されるため、必ずしもスキーマ全体になるとは限りません。 各テーブルはカラム名・型・PK/FK マーカーを列挙するエンティティブロックになり、各エッジは Mermaid の 鳥の足記法(crow's-foot)を使った関連の行になり、最初の association の名前がラベルとして付きます。 カラムのコメント、null 許可、デフォルト値、論理名は Mermaid の出力には含まれません — 含まれるのは 名前・型・キーマーカーのみです。

PlantUML

Mermaid と同じ範囲・制限(現在表示中のテーブルのみ、カラムコメントなし)ですが、エンティティの マークアップは異なります: 主キーのカラムが区切り線の上に先頭でリストされ、null 非許可のカラムには * が付き、外部キーのカラムには <<FK>> が付き、テーブルに論理名が あれば物理名の横に全角括弧で表示されます。

Excel ワークブック

--excel FILE.xlsx は、外部のスプレッドシートライブラリを一切使わずにワークブックを 書き出します。

  • 概要シート — テーブルごとに1行: #Table(そのテーブル 自身のシートへのハイパーリンク付き)、CommentColumns(カラム数)、 Indexes(インデックス数)、Missing schema
  • テーブルごとのシート — テーブル名とコメント、続いてカラムの表(#ColumnTypeNullableDefaultKeyPK/FK/空欄、ExtraComment)、インデックスがあれば Indexes セクション(名前、カラム、unique の有無)、association があれば Associations セクション(種類、名前、参照先、そしてその出所: DB FK / inferred / manual / code)。

--excel-template FILE.xlsx を使うと、erdscope 自体のコードに触れることなく、ワークブックの 色・フォント・罫線を5セル契約を通じて再スタイルできます: テンプレートの最初のワークシート の A 列、1〜5行目に、それぞれ Title / Header / Data / Data (alternate row) / Section のスタイルを 設定しておく必要があります。読み取られるのは各セルのスタイル(フォント、塗りつぶし、罫線)だけで、 セルのテキスト内容は関係ありません。契約セルが欠けている場合は、その1つのロールだけ erdscope 組み込みの スタイルにフォールバックし、stderr に警告が出力されます。.xlsx としてまったく開けない ファイルだけがハードエラーになります。

このリポジトリには excel-template.xlsxgen_excel_template.py によって生成)が、すぐに編集できる出発点として同梱されています — そのStylesシートには、5つの契約セルが erdscope 標準のスタイルであらかじめ設定されており、 B 列には各ロールの平易な説明があります。

注意 --excel-template--excel なしでは効果がありません — スタイル対象となる --excel を指定せずにテンプレートを渡した場合、erdscope は stderr に警告を出力し、それ以外は 無視します。

トラブルシューティング / FAQ #

日本語(またはマルチバイト)のコメントが文字化けする

erdscope は PyMySQL 経路でも mysql CLI フォールバック経路でも、明示的に utf8mb4 で接続します — サーバーやセッションのデフォルト文字セットには頼りません。それでも コメントが化けている場合、最も可能性が高いのは、データベースに書き込まれた時点ですでに壊れていた というケースです(例えば以前に utf8mb4 でない接続経由でインポートされた場合など)— erdscope のバグだと判断する前に、utf8mb4 であることが確実なクライアントで、データベース内の コメントを直接確認してみてください。

PyMySQL / psycopg がインストールされていない場合はどうなりますか?

erdscope は代わりにデータベース自身の CLI にシェルアウトします — MySQL なら mysql、 PostgreSQL なら psql(クエリを COPY … TO STDOUT でラップします。このエスケープ 済みテキスト形式のおかげで、自由記述のコメントが出力を壊すことがありません)。どちらも PATH 上にある必要があります。パスワードはこの場合も MYSQL_PWD / PGPASSWORD 環境変数 経由で渡され、CLI 引数として渡されることはありません。この2つの経路は、バイト単位で同一の HTML を生成 します。ドライバと CLI のどちらも利用できない場合は、どちらかをインストールするよう促す明確な エラーが表示されます — erdscope がここでサイレントに失敗することはありません。

VIEW が図に表示されないのはなぜですか?

これは仕様です — erdscope は実際にストレージに裏付けられたテーブルのみを読み込みます: MySQL では TABLE_TYPE = 'BASE TABLE'、PostgreSQL では通常のテーブルとパーティション親テーブルのみ (VIEW も個々のパーティションも対象外)です。これにより、図は実際にストレージに裏付けられたスキーマに 絞り込まれます。

--infer-fk がデフォルトでオフなのはなぜですか?

単なる *_id というカラム名は推測にすぎず、それを裏付けるもの(実際の association や DB FK 制約)が何もない場合、間違っている可能性があるためです。このフラグをオンにしても、その推測が 遡って昇格するわけではありません — カラム一覧の「FK」バッジと PK/FK カラム表示モードは、あくまで実際の association だけに基づいており、推測によるエッジは常に見た目でも区別されます(薄い点線になります。 エッジの種類参照)。検証済みの関連と同じ見た目になることはありません。

--table-map はどんなときに必要ですか?

これは Rails 専用の抜け道で、erdscope の静的解析ではモデルの実際のテーブルを特定できない、まれな ケースのためのものです — 最も多いのは、アプリ自身にはソースがなく、gem から提供される concern モジュールの中に self.table_name = ... の代入がある場合です。 --table-map 'Widget=crm_widgets'(繰り返し指定可、カンマ区切りリストも可)を渡すことで 明示的に上書きできます。この上書きは、そのモデルを指す他のモデルの association も修正するため、 右ペインのリンクは正しいテーブルに解決されます。

Auto-expand がオンなのに関連テーブルが表示されません

Auto-expand は、チェック済み/フォーカス中の起点から BFS(幅優先探索)でたどり着けるテーブルだけを 引き込みます。この探索が途中で止まる正当な理由がいくつかあります — 順に確認してみてください。

  • Direction(方向)フィルタ(Deps/Dependents)が、実際の関連の向きと一致していない可能性があります。
  • 対象のテーブルが禁止(Ban)🚫)されている可能性があります — 禁止されたテーブルは、単なる通過点としてであっても Auto-expand が決して越えません。
  • Depth(深度)の上限が、そのホップ数に対して浅すぎる可能性があります。
  • ノードの ボタンでそのテーブルを引き込んだ場合、それは意図的に新しい Auto-expand の起点にはならないため、そこからさらに自動的に広がることはありません。
  • 生成時に --only/--exclude でそもそも図の対象外になっている場合、そのテーブルは単純に図のどこにも存在しません。

拡張 #

パース以降のすべて — HTML/JS ビューア、レイアウト、すべてのエクスポート形式 — は、erd.py 自身のモジュール docstring に記載されている、単一の中間表現(IR)を消費します。

tables = {
  "table_name": {
    "primary_key": "id" | None,
    "comment"?: str,
    "schema_missing"?: bool,        # model exists but no DB table
    "columns": [{"name","type","nullable","primary",
                 "sql_type"?, "default"?, "extra"?, "comment"?}],
    "indexes": [{"name","columns":[...],"unique":bool}],
    "associations": [{"type": has_many|belongs_to|has_one|has_and_belongs_to_many,
                      "name", "target",
                      "through"?, "foreign_key"?, "polymorphic"?,
                      "db_fk"?, "inferred"?}],
  }
}

新しいソースデータベースへの対応は、この同じ形を生成するパーサーを1つ追加するだけです。 parse_postgres() は、そのパターンの実例です — pg_catalog のクエリ結果を、 MySQL アダプタの IR ビルダーが受け取るのとまったく同じ行の形に整形します。そのため PK の検出、 unique インデックスによる 1:1 昇格、インデックスの組み立てはコードを複製せず共有されています — アダプタ全体は、4つのクエリと接続処理だけで成り立っています。SQL 型の短縮表にはすでに両エンジン 由来の型名(character varyingbigserialjsonbbyteainet など)が含まれているため、さらに別のエンジンに対応する場合も、 基本的にはそのカタログを同じ5カラムの行の形にマッピングするだけで済みます。