メインコンテンツまでスキップ

リレーションシップの編集

リレーションシップはキャンバスのコンテキストメニュー、キャンバスツールバー、クイック検索、またはショートカットで作成します。編集を始めるを参照してください。
このページでは、作成したリレーションシップに対してできること、Map Columns でリレーションシップの終点を子テーブルにすでにあるカラムにする方法、リレーションシップが追加する外部キーカラムの名前の付け方を説明します。

削除​

リレーションシップのコンテキストメニューから削除できます。

コンテキストメニューから products と reviews の間のリレーションシップを削除

リレーションシップはテーブルやメモのようには選択しないため、ショートカットはありません。選択している対象を削除する Delete と Backspace が、リレーションシップだけを単独で削除することはありません。テーブルとメモの削除を参照してください。
リレーションシップは接続している対象とともに削除されます。テーブルを削除するとそのテーブルにつながるリレーションシップがすべて削除され、カラムを削除するとそのカラムを使うリレーションシップがすべて削除されます。

種類の変更​

リレーションシップのコンテキストメニューの Relationship Type から変更できます。
次の 4 つの種類から選択でき、現在の種類にはチェックが付きます。

  • Zero One
  • Zero N
  • One Only
  • One N

コンテキストメニューからリレーションシップの種類を Zero N から One Only、One N へ順に変更

これはリレーションシップの作成時に選ぶ 4 つの種類と同じで、それぞれにショートカットがあります。編集を始めるを参照してください。

ON DELETE と ON UPDATE​

リレーションシップのコンテキストメニューで、Relationship Type と Map Columns の間にある On Delete と On Update から設定します。
どちらにも同じ 6 つの項目があり、現在の項目にはチェックが付きます。

  • Not set
  • NO ACTION
  • CASCADE
  • SET NULL
  • SET DEFAULT
  • RESTRICT

Not set は句を書き出さないため、データベース自体の既定の動作が適用されます。新しいリレーションシップは、通常どおり作成した場合も Map Columns で作成した場合も、ON DELETE と ON UPDATE のどちらも Not set で始まり、後から Not set を選ぶとアクションが解除されます。
2 つは互いに独立しており、一方を変更してももう一方はそのままです。
設定した内容はコネクタに表示されます。コネクタの読み方を参照してください。
テーブルと一緒にコピーして貼り付けたリレーションシップや、テーブルと一緒に複製したリレーションシップは両方のアクションを保持し、Schema SQL、DBML、AML を読み込むと、ファイルで宣言されているアクションが取り込まれます。ファイルの読み込みと書き出しを参照してください。

コンテキストメニューから orders と order_items の間のリレーションシップに ON DELETE CASCADE と ON UPDATE RESTRICT を設定し、ラベルが D U と表示された後、マウスを重ねて両方を確認する様子

どのアクションも、データベースにかかわらず選択できます。
選択しているデータベースの Schema SQL が書き出さないアクションには、not in MySQL のような淡い色の注記が横に付きます。Not set に注記が付くことはなく、データベースを切り替えると注記も更新されます。
注記の付いたアクションもリレーションシップには保存されます。コネクタに表示され、JSON、DBML、AML にも保持されますが、そのデータベースの Schema SQL ではその句が省かれるため、データベースの既定の動作が適用されます。

Schema SQL が書き出すアクションは次のとおりで、それ以外は省かれます。

データベースON DELETEON UPDATE
DatabricksNO ACTIONNO ACTION
MSSQLNO ACTION、CASCADE、SET NULL、SET DEFAULTNO ACTION、CASCADE、SET NULL、SET DEFAULT
MariaDBNO ACTION、CASCADE、SET NULL、RESTRICTNO ACTION、CASCADE、SET NULL、RESTRICT
MySQLNO ACTION、CASCADE、SET NULL、RESTRICTNO ACTION、CASCADE、SET NULL、RESTRICT
OracleCASCADE、SET NULLなし
PostgreSQL5 つすべて5 つすべて
SnowflakeNO ACTIONNO ACTION
SQLite5 つすべて5 つすべて

Snowflake の Schema SQL は、省いたアクションごとに、そのアクションを示すコメントも書き出します。参照アクションを参照してください。

コード生成の ORM の対象がどのアクションを出力するかは、選択しているデータベースだけでなく対象によっても変わります。コード生成を参照してください。

Map Columns​

Map Columns は、親テーブルのキーと子テーブルのカラムを、キーのカラム 1 つにつき 1 行で対応付けます。
各行は、子テーブルにすでにあるカラムを使うか、新しい外部キーカラムを追加するため、リレーションシップの終点をすでにあるカラムにできます。

members から orders へ Zero N のリレーションシップを作成し、Map to existing columns を選んで、id を既存の member_id カラムに対応付ける様子

開き方は 2 つあります。

  • リレーションシップの作成中に、子テーブルの横にある Map to existing columns から開きます。リレーションシップの作成を参照してください。この場合、Map を押すと作成中の種類のリレーションシップが追加されます。
  • 既存のリレーションシップのカラムを変更するために、リレーションシップのコンテキストメニューの Map Columns から開きます。この場合、Save を押すと変更が書き込まれます。読み取り専用のエディタでは、この項目は表示されません。

ダイアログのサブタイトルには、users → posts · One N のように 2 つのテーブルとリレーションシップの種類が表示されます。種類はここに表示されるだけで、変更はできません。種類の変更を使ってください。

References では、リレーションシップが参照するキーを選びます。カラムがテーブルの順に並ぶ Primary Key に続いて、Unique が付いた各カラムの Unique: <column> が並びます。選択肢が 2 つ以上ある場合にだけ表示されます。
ここではユニークインデックスはキーに数えず、1 つで主キー全体になっている Unique のカラムが 2 回並ぶことはありません。
別のキーを選ぶと行が作り直されます。選んでいたカラムが子テーブルにまだある限り、行はその選択を保持します。

Referenced column と Foreign key column の見出しの下で、各行にはキーのカラムとそのデータ型、そのカラムと対応付ける子テーブルのカラムのリストが表示されます。

  • Pick a column は行を空のままにします。
  • New column: <name> は新しい外部キーカラムを追加します。表示される名前は実際に付けられる名前で、外部キーカラムの名前で説明するとおりに付けられ、子テーブルのカラムと、新しいカラムを追加するほかの行に対して番号が付きます。名前のないキーのように、名前が空になる場合は表示されません。
  • 子テーブルのすべてのカラムが <name> (<data type>) として並びます。ほかの行が選んでいるカラムは <name> (<data type>) · in use と表示されて選べないため、2 つの行が同じカラムを使うことはありません。ほかのリレーションシップがすでに使っているカラムは選べるため、共有の tenant_id のようなカラムを複数のリレーションシップで使えます。

Map の場合、行が最初から埋まっているのは、その行で新しい外部キーカラムを追加したときに _2 などの番号が付く前の名前と、大文字と小文字を区別せずに一致する子テーブルのカラムがちょうど 1 つだけある場合です。たとえば users の id に対しては users_id、member_id に対しては member_id です。Bracket が既定の None の間は、スキーマ修飾されたテーブル名のテーブル部分から作った名前も一致の対象になるため、public.users の id は public.users_id または users_id と対応付けられます。Unique のキーでは、キーのカラム自体の名前も対象になるため、vin は vin と対応付けられます。それ以外の行は Pick a column で始まります。
Save の場合、各行はリレーションシップが現在使っているカラムで始まります。どちらの場合も、References で別のキーを選ぶと、そのキーの空の行が同じ名前で埋められます。

選んだカラムのデータ型が、親のカラムが外部キーに与えるデータ型と異なる場合は、行の下に注記が表示されます。
リレーションシップのデータ型同期がオンで、親のカラムにデータ型がある場合は、対応付けによって書き込まれる型を示す <column> becomes <type> と表示されます。それ以外の場合は Types differ: <parent type> and <child type> と表示され、カラムは自身の型を保持します。

妨げになるものがある間は Map または Save が無効のままになり、行の下の 1 行でその理由が示されます。

  • Pick a foreign key column for every referenced column: 空の行が残っています。
  • At least one column must reference a different column: 自己参照のリレーションシップで、すべての行が自身の親のカラムを選んでいます。
  • These columns are already linked by another relationship: 同じ 2 つのテーブルの間にあるほかのリレーションシップが、まったく同じカラムをつないでいます。
  • <parent> has no key to reference: Map の場合に、親テーブルに主キーも Unique のカラムもありません。

Save は、対応付けがリレーションシップの現在の対応付けと異なるものになるまでは無効のままです。
Save の場合、行のカラムがテーブルからなくなると、その行は (removed) と表示されます。子テーブルの別のカラムを選ぶか、親のカラムがなくなった場合は References でキーを選んでください。Map の場合、選んでいたカラムが削除された行は Pick a column に戻ります。

親側のカラムが親テーブルのいずれかのキーとちょうど一致しないリレーションシップでは、References の最後に追加の選択肢 Current columns (not a key) が付き、それを選んだ状態で開きます。この選択肢はそれらのカラムをそのまま保持します。親テーブルにキーがまったくない場合は、これが唯一の選択肢になり、References は表示されません。
この場合に表示される The referenced columns are not a key of <parent>、または親テーブルにキーがまったくない場合の <parent> has no key to reference の行はエラーではなくお知らせです。Save は使えるため、参照先はそのままで子テーブルのカラムを変更できます。
長さが異なるなどの理由で 2 つのカラムのリストを対応付けられないリレーションシップでは、(invalid) の行が表示され、References でキーを選ぶか、親テーブルにキーがない場合は主キーか Unique のカラムを追加するまで、Save は無効のままです。

ダイアログは開いている間、共同編集者やコーディングエージェントによる編集も含めてダイアグラムの変更に追従し、選んだ内容は保持します。
その間にリレーションシップのカラムや、開いたときのキーが変わると、This relationship changed while the dialog was open の行が追加されます。

Map と Save が書き込む内容は次のとおりです。

  • Map は、On Delete と On Update を Not set にしてリレーションシップを追加します。Save はリレーションシップのカラムだけを変更して親側を References で選んだキーに向け、種類と ON DELETE、ON UPDATE はそのまま保持します。
  • New column の行は、リレーションシップを作成したときと同じように、子テーブルの最後にカラムを追加します。そのカラムは NOT NULL で、キーに基づいて名前が付けられ、キーのデータ型、既定値、コメントを引き継ぎます。識別リレーションシップを参照してください。
  • 選んだカラムの名前が変わることはなく、Not Null、主キー、Unique、既定値、コメントもそのままです。データ型が変わるのは、Relationship DataType Sync がオンで、親のカラムにデータ型がある場合だけです。その場合、カラムは親のカラムが外部キーに与える型(serial のキーでは、新しいカラムと同じく整数型)になり、その変更は同期と同じようにリレーションシップをたどって伝わります。
  • 対応付けで使われなくなったカラムは子テーブルに残り、ほかのリレーションシップがまだその終点になっていない限り、外部キーとしての印は外れます。
  • 1 回の Map または Save が書き込むものは、新しいカラムや型の変更も含めて、Undo の 1 ステップです。

リレーションシップが識別リレーションシップかどうかと、親側の端の描き方は、ほかのリレーションシップと同じように、対応付けた子テーブルのカラムから決まります。子テーブルの主キーのカラムに対応付けるとすぐに識別リレーションシップになり、NULL を許可するカラムに対応付けると親側の端に丸が付きます。コネクタの読み方を参照してください。
Schema SQL の外部キーは、選んだキーを参照します。Unique のキーでは REFERENCES vehicle (vin) のようになります。

共同編集者やコーディングエージェントが先に同じ変更をしたため、Map または Save を押した時点でダイアグラムにすでにその対応付けがある場合は、何も書き込まれません。
ダイアグラムが変わって対応付けが合わなくなった場合は、何も書き込まれず、Couldn't map columns: the diagram changed のトーストが表示されます。

Cancel、x ボタン、Escape、またはダイアログの外側の暗くなった部分のクリックで、何も書き込まずに閉じます。
検索と置換やクイック検索を開いたとき、ERD タブから離れたとき、エディタが読み取り専用になったときも閉じます。
開いている間にどちらかのテーブルやリレーションシップが削除されると、Map Columns closed: the relationship was removed のようなトーストを表示して閉じます。
開いている間は、キャンバスのショートカット、Undo と Redo、コピーと貼り付けは何もしません。

コーディングエージェントには Map Columns のツールはありません。リレーションシップを対応付け直すには、外部キーカラムを残す erd_remove_relationship でリレーションシップを削除し、erd_link_columns で既存のカラムに作り直します。どちらも 1 つの erd_batch の中で行います。ツールを参照してください。

N:M リレーションシップ​

エディタは物理モデルをベースにしているため、N:M リレーションシップは下図のようにマッピングテーブルで表現します。

⌘ + ⌥ + 2 で products、続いて tags から空の product_tags テーブルへリレーションシップを作成し、product_id、続いて tag_id を追加する様子

product_tags の product_id と tag_id のように、マッピングテーブルにキーのカラムがすでにある場合は、Map to existing columns で各リレーションシップを作成し、新しいカラムを追加する代わりにそれらのカラムを選びます。Map Columnsを参照してください。それらがマッピングテーブルの主キーであれば、各リレーションシップはすぐに識別リレーションシップになります。

GraphQL、DBML、AML を読み込むと、マッピングテーブルは自動で作成されます。
多対多の宣言は <left>_<right> という名前のテーブルとして読み込まれ、Junction table inferred from <left> <-> <right> というコメントが付き、識別リレーションシップで両側に接続されます。
ファイルの読み込みと書き出しを参照してください。

識別リレーションシップ​

子テーブルをクリックするか Create new columns でリレーションシップを作成すると、親テーブルの主キーが NOT NULL の外部キーカラムとして子テーブルにコピーされるため、作成した直後は非識別リレーションシップです。
コピーされたカラムはキーのデータ型、既定値、コメントを引き継ぎますが、Unique と Auto Increment は引き継がず、名前は外部キーカラムの名前で説明するとおりに付けられます。
データ型については serial のキーが例外で、そのコピーには serial が格納する整数型が使われます。どのデータベースでも、smallserial と serial2 は smallint、serial4 は integer、bigserial と serial8 は bigint になります。単独の serial は、PostgreSQL では integer、MySQL と MariaDB では bigint unsigned になり、それ以外のデータベースでは serial のままです。
大文字と小文字を区別せずに型名全体が一致する場合だけが対象のため、serial(4) は書かれているとおりにコピーされます。大文字で書かれた型からは大文字の型ができ、PostgreSQL では SERIAL は INTEGER になります。保存したダイアグラムですでに serial 型になっている外部キーカラムは、その型を保持します。
リレーションシップを識別リレーションシップにするには、子テーブルのその外部キーカラムを主キーに設定します。すべてを選択して Alt + K (Windows/Linux) または ⌥ + K (Mac) を 1 回押すか、テーブルのコンテキストメニューの Primary Key を選びます。この項目は、2 つ以上のカラムを選択している間は Primary Key on selected columns と表示されます。カラムの主キーを参照してください。

Alt + K で product_id を主キーに設定・解除し、コネクタが実線と破線に切り替わる様子

この状態はエディタが自動で同期します。
子側のカラムがすべて主キーである間は識別リレーションシップとなり、いずれかが主キーでなくなった時点で非識別リレーションシップに変わります。

外部キーカラムの名前​

リレーションシップを作成すると、追加される各外部キーカラムには、そのカラムのコピー元である親のキーに基づいて名前が付けられます。

  • id、ID、uuid のような 1 語のキー名には、前に親テーブルの名前とアンダースコアが付きます。products の id は products_id になります。
  • member_id、userId、UserID のような複数語のキー名は、そのまま使われます。
  • 大文字と小文字を区別せずにテーブル自体の名前と一致する 1 語のキー名も、そのまま使われます。currency の currency は currency のままです。テーブルの名前を含んでいるだけのキーには、やはり接頭辞が付きます。user の username は user_username になります。

名前が文字と数字だけでできていて、大文字と小文字の切り替わりがない場合、その名前は 1 語です。
それ以外の文字は名前を区切るため、_id、order no、order-no は複数語です。
camelCase と同じように読む、大文字と小文字の切り替わりも名前を区切ります。小文字の後に大文字が続く場合(userId)、大文字 2 つの後に小文字が続く場合(IDCard、IDs)、ハングル、仮名、漢字のような大文字と小文字の区別がない文字が、区別がある文字と隣り合う場合(회원ID)です。
数字は語を区切らないため、id2 と SHA256 は 1 語です。大文字か小文字のどちらか一方だけで書かれた複合語も 1 語です。members の memberid は members_memberid になります。

テーブル名は、前後の空白を除いて書かれているとおりに使われます。大文字と小文字、途中の空白、ドットはそのまま残り、単数形にはされず、コード生成の Table Name Case と Column Name Case も影響しません。キーが ID の Users からは Users_ID ができます。
複合キーの各カラムには、それぞれ個別に名前が付けられます。キーが(tenant_id、id)の orders では、tenant_id と orders_id が追加されます。

子テーブルにすでにある名前と大文字と小文字を区別せずに一致する名前には、_2、_3 のように番号が付き、空いている最初の番号が使われます。
キーが id の users から同じテーブルへの 2 つ目のリレーションシップでは users_id_2 が追加され、キーが member_id の members の自己参照では member_id_2 が追加されます。
1 つの複合キーのカラムどうしも同じように番号が付けられ、そのまま使われる名前が先にその名前を確保します。キーが(id、user_id)の user では、user_id に対して user_id、id に対して user_id_2 が追加されます。

親テーブルに名前がない場合、キー名はそのまま使われ、重複したときはほかの名前と同じように番号が付きます。
名前のないキーからは、名前のない外部キーカラムができます。
主キーのない親にエディタが追加する主キーもこれに当たります。ただし、子テーブルをクリックする前にその主キーに名前を付けた場合は除きます。

名前はリレーションシップを作成した時点で決まります。後から親テーブルやそのキーの名前を変更しても、外部キーカラムの名前は変わりません。
Map Columns の New column の行にも同じ規則で名前が付けられ、選ぶ前からリストにその名前が表示されます。
読み込み、貼り付け、複製、または既存のカラムを対応付ける Map Columns によって、カラムがすでにそろった状態で入ってくるリレーションシップは、それらのカラムの名前をそのまま保持します。
コーディングエージェントが erd_add_relationship でリレーションシップを追加した場合も、同じ名前とデータ型になります。ツールを参照してください。

コネクタの読み方​

  • 識別リレーションシップは実線、非識別リレーションシップは破線で描画します。
  • 子側の端には、リレーションシップの種類に応じたカーディナリティ記号が付きます。Zero One は丸と棒、Zero N は丸と鳥の足、One Only は 2 本の棒、One N は棒と鳥の足です。
  • 親側の端は、外部キーカラムのいずれかが NULL を許可する場合は Zero One と同じ丸と棒、すべて NOT NULL の場合は One Only と同じ 2 本の棒になります。
  • コネクタにマウスを重ねると、そのコネクタと、それがつなぐ両方のテーブルのカラムが強調表示されます。

3 本のコネクタに順にマウスを重ね、それぞれがつなぐカラムとともに強調表示される様子

ON DELETE または ON UPDATEを設定したリレーションシップには、子側の端の横に D:C U:R のようなラベルが付きます。D: の後に ON DELETE のアクション、続いて U: の後に ON UPDATE のアクションが、それぞれ設定されている場合にだけ表示されます。
アクションは erwin の記法にならって省略されます。CASCADE は C、RESTRICT は R、SET NULL は SN、SET DEFAULT は SD、NO ACTION は NA です。どちらも設定していないリレーションシップにはラベルがありません。
ラベルは子テーブルから離れた側に置かれます。コネクタがそのテーブルの左右の辺から出る場合は線の上、上下の辺から出る場合は線の右に置かれ、カーディナリティ記号とは重なりません。
ラベルはキャンバスの背景色の小さな箱の上にコネクタと同じ色で描画され、コネクタと一緒に強調表示されます。ラベルはすべてのコネクタより上に描画されるため、ラベルと交差する線はラベルの下を通ります。
ラベルは、選択しているデータベースが何を書き出すかにかかわらず、リレーションシップに保存されているアクションを表示します。そのため、MySQL でも ON DELETE SET DEFAULT は D:SD と表示されます。

いずれかのアクションを設定したコネクタにマウスを重ねると、ON DELETE CASCADE や ON UPDATE RESTRICT のように句を省略せずに 1 行ずつ示すツールチップも表示されます。
ツールチップはラベルが非表示の間も表示されます。

ERD キャンバスのコネクタを非表示にするには Relationship の表示オプションを、ラベルだけを非表示にするには既定でオンになっている Referential Actions の表示オプションを使います。テーブルの表示オプションを参照してください。
テーブルが名前だけの表示に折りたたまれる 70% 以下では、ラベルは描画されません。
画像の書き出しは常に 100% で描画されるため、表示オプションで非表示にしていない限り、キャンバスの拡大・縮小にかかわらずラベルも描画されます。Background がオフの場合は、各ラベルの後ろの箱も透明になります。
Visualization タブの Flow モードは、Relationship がオフでもコネクタを描画します。各コネクタは同じ端の記号を持つ 1 本のなめらかな灰色の実線の曲線として描かれるため、このページで説明する破線、ラベル、ツールチップ、直交する経路は ERD キャンバスにのみ当てはまります。テーブルから自分自身へのリレーションシップは、Flow でもテーブルの右上の角を回る曲線になります。コネクタの経路を参照してください。

コネクタの経路​

コネクタは直交する経路で描画します。
経路は両端の間にあるテーブルを横切らずに迂回し、角は丸められます。
各端は曲がる前に短くまっすぐテーブルから出るため、少しだけ離れた 2 つのテーブルでコネクタの端の位置がそろっている場合は、回り道ではなく 1 本の直線で結ばれます。
テーブルの同じ辺から出る経路は、互いに重ならないように別々の通り道へ分けられます。
迂回するのはテーブルだけです。コネクタはメモやテーブルグループの枠を横切ることがあり、テーブルグループより上、テーブルとメモより下に描画されます。

テーブルから自分自身へのリレーションシップは、テーブルの右上の角を回る 1 本の曲線として描画され、親側の端では上の辺から出て、子側の端では右の辺に入ります。
同じテーブルにさらに自己参照があると、最初の曲線の外側に入れ子になるため、曲線どうしやテーブルと交差することはありません。

設定する項目はありません。
キャンバス上の要素が移動したりサイズが変わったりするたびに経路を自動で再計算するため、手作業で調整する必要はありません。

members テーブルを下へドラッグして戻す間、orders からのコネクタが categories の右側を通る経路と左側を回る経路の間で切り替わり、すべての角が丸められている様子