DBMLの構文

DBML

モデル設計用のDSLの1つであるDBMLの構文について、公式ドキュメント(英語)を主に自動翻訳を使って日本語にしてみました。

Syntax | DBML
DBML (database markup language) is a simple, readable DSL language designed to define database structures. This page

プロジェクト定義

プロジェクトの全体的な説明をすることができます。

Project project_name {
  database_type: 'PostgreSQL'
  Note: 'Description of the project'
}

スキーマ定義

新しいスキーマは、テーブルまたはEnum型を含む限り定義されます。

例えば、次のコードは、新しいスキーマ core と、その中に配置されたテーブル user を定義します。

Table core.user {
  ...
}

Public スキーマ

デフォルトでは、schema_name を省略したテーブル、リレーションシップ、またはEnum定義は、Public スキーマに属するものと見なされます。

テーブル定義

// table belonged to default "public" schema
Table table_name {
  column_name column_type [column_settings]
}

// table belonged to a schema
Table schema_name.table_name {
  column_name column_type [column_settings]
}
  • (オプション) データベーススキーマのタイトルは schema_name で指定します。省略した場合、schema_name はデフォルトで public になります。
  • データベーステーブルのタイトルは table_name で指定します。
  • 列名は column_name で指定します。
  • 列内のデータの型は column_type で指定します。
  • 単一の単語であれば、すべてのデータ型をサポートします(データ型に含まれるスペースはすべて削除してください)。例: JSON、JSONB、decimal(1,2) など。
  • インデックス、制約、テーブル定義のリストは、中括弧 {} で囲みます。
  • 設定は角括弧 [] で囲みます。
  • 文字列値は、’string’ のように一重引用符で囲みます。
  • column_name は、プレーンテキストで指定することも、”column name” のように二重引用符で囲むこともできます。
ヒント

TablePartial を使用すると、複数のテーブル間で共通のフィールド、設定、インデックスを再利用できます。テーブルに部品データを挿入するには、~partial_name 構文を使用します。

テーブルエイリアス

テーブルにエイリアスを付けて、後で参照に使用することができます。

Table very_long_user_table as U {
  ...
}

Ref: U.id < posts.user_id

テーブルメモ

テーブルにメモを追加し、視覚的な面で参照することができます。

Table users {
  id integer
  status varchar [note: 'status']

  Note: 'Stores user data'
}

テーブル設定

設定はすべて角括弧で定義されます: [設定1: 値1, 設定2: 値2, 設定3, 設定4]

各設定項目は2つの形式を取ります: key: value または keyword。Python 関数のパラメータに似ています。

  • headercolor: <color_code>: テーブルヘッダーの色を変更します。
Table users [headercolor: #3498DB] {
  id integer [primary key]
  username varchar(255) [not null, unique]
}

カラム定義

カラムの設定

各カラムには、次のように角括弧で定義されたオプションの設定を指定できます。

Table buildings {
  ...
  address varchar(255) [unique, not null, note: 'to include unit number']
  id integer [ pk, unique, default: 123, note: 'Number' ]
}

使用できるカラム設定のリスト:

  • note: ‘メモの内容’: カラムにメタデータメモを追加します
  • primary key または pk: カラムを主キーとしてマークします。複合主キーについては、「インデックス」セクションを参照してください
  • null または not null: カラムをnullまたはnot nullとしてマークします。この設定を省略した場合、カラムはデフォルトでnullになります
  • unique: カラムを一意としてマークします
  • default: some_value: カラムのデフォルト値を設定します。以下の「デフォルト値」セクションを参照してください
  • increment: 列を自動インクリメントとしてマークします

注: サポートされていない設定については、設定名を列タイプ名に追加することで回避できます(例:id “bigint unsigned” [pk])。

デフォルト値

デフォルト値は次のように設定できます。

  • 数値が空白で始まる場合: default: 123 または default: 123.456
  • 文字列値が一重引用符で始まる場合: default: ‘何らかの文字列値’
  • 式値がバッククォートで囲まれる場合: default: `now() - interval '5 days'`
  • 論理値 (true/false/null): default: false または default: null
Table users {
  id integer [primary key]
  username varchar(255) [not null, unique]
  full_name varchar(255) [not null]
  gender varchar(1) [not null]
  source varchar(255) [default: 'direct']
  created_at timestamp [default: `now()`]
  rating integer [default: 10]
}

インデックス定義

インデックスを使用すると、ユーザーはデータを素早く見つけてアクセスできます。単一カラムまたは複数カラムのインデックスを定義できます。

Table bookings {
  id integer
  country varchar
  booking_date date
  created_at timestamp

  indexes {
    (id, country) [pk] // composite primary key
    created_at [name: 'created_at_index', note: 'Date']
    booking_date
    (country, booking_date) [unique]
    booking_date [type: hash]
    (`id*2`)
    (`id*3`,`getdate()`)
    (`id*3`,id)
  }
}

インデックス定義には 3 つの種類があります。

  • 単一カラムのインデックス(名前付き):CREATE INDEX created_at_index on users (created_at)
  • 複数カラムのインデックス(複合インデックス):CREATE INDEX on users (created_at, country)
  • 式付きインデックス:CREATE INDEX ON films ( first_name + last_name )
  • (おまけ)式付き複合インデックス:CREATE INDEX ON users ( country, (lower(name)) )

インデックス設定

  • type: インデックスの種類(DB​​に応じてbtree、gin、gist、hash)。現時点では、btreeとhashのみがサポートされています。
  • name: インデックス名
  • unique: ユニークインデックス
  • pk: 主キー

リレーションシップと外部キーの定義

リレーションシップは、スキーマ全体のテーブル間の外部キー制約を定義するために使用されます。

Table posts {
  id integer [primary key]
  user_id integer [ref: > users.id] // many-to-one
}

// or this
Table users {
  id integer [ref: < posts.user_id, ref: < reviews.user_id] // one to many
}

// The space after '<' is optional

リレーションシップには4つのタイプがあります: 1対11対多多対1多対多

  • <: 1対多。 例: users.id < posts.user_id
  • >: 多対1。 例: posts.user_id > users.id
  • -: 1対1。 例: users.id - user_infos.user_id
  • <>: 多対多。 例: authors.id <> books.id

外部キーのnull許容制約と組み合わせると、0対(1/多)または(1/多)対0の関係が自動的に検出されます。次の例をご覧ください。

Table follows {
  following_user_id int [ref: > users.id] // many-to-zero
  followed_user_id int [ref: > users.id, null] // many-to-zero
}

Table posts {
  id int [pk]
  user_id int [ref: > users.id, not null] // many-to-one
}

DBML には、リレーションシップを定義するための 3 つの構文があります。

// Long form
Ref name_optional {
  schema1.table1.column1 < schema2.table2.column2
}

// Short form
Ref name_optional: schema1.table1.column1 < schema2.table2.column2

// Inline form
Table schema2.table2 {
  id integer
  column2 integer [ref: > schema1.table1.column1]
}
メモ

🔵1対1のリレーションシップを定義するときは、カラムが正しい順序でリストされていることを確認してください。

 🟠長い形式と短い形式の場合、2 番目のカラムは外部キーとして扱われます。

  例:users.id - user_infos.user_iduser_infos.user_id will be the foreign key.

 🟠インライン形式では、ref 定義を持つカラムは外部キーとして扱われます。

Table user_infos {
  user_id integer [ref: - users.id]
}

 この例の場合、user_infos.user_id は外部キーになります。

🔵schema_name プレフィックスを省略すると、デフォルトで public スキーマになります。

複合外部キー:

Ref: merchant_periods.(merchant_id, country_code) > merchants.(id, country_code)

スキーマ間のリレーションシップ:

Table core.users {
  id integer [pk]
}

Table blogging.posts {
  id integer [pk]
  user_id integer [ref: > core.users.id]
}

// or this
Ref: blogging.posts.user_id > core.users.id

リレーションシップ設定

// short form
Ref: products.merchant_id > merchants.id [delete: cascade, update: no action, color: #79AD51]

// long form
Ref {
  products.merchant_id > merchants.id [delete: cascade, update: no action, color: #79AD51]
}
  • delete / update: cascade | restrict | set null | set default | no action は参照アクションを定義します。SQLにおける ON DELETE/UPDATE CASCADE/… に似ています。
  • color: <color_code> : リレーションシップの色を変更します。

リレーションシップ設定と名前は、インライン形式のrefではサポートされていません。

多対多リレーションシップ

多対多のリレーションシップを表すには 2 つの方法があります。

  • 1つの多対多リレーションシップ(<>)を使用します。
  • 2つの多対1リレーションシップ(><)を使用します。詳細については、以下を参照してください。

  https://community.dbdiagram.io/t/tutorial-many-to-many-relationships/412

表記方法以外に、これら 2 つのアプローチの主な違いは、SQL に出力するときにリレーションシップが物理設計にどのようにマップされるかです。

Enum定義

Enumを使用すると、特定のカラムに異なる値を定義できます。キャンバス内の列にマウスポインターを合わせると、Enum型の値が表示されます。

// enum belonged to default "public" schema
enum job_status {
  created [note: 'Waiting to be processed']
  running
  done
  failure
}

// enum belonged to a schema
enum v2.job_status {
  ...
}

Table jobs {
  id integer
  status job_status
  status_v2 v2.job_status
}

注: schema_name プレフィックスが省略された場合、デフォルトで public スキーマになります。

Enumの値にスペースやその他の特殊文字が含まれている場合は、二重引用符を使用できます。

enum grade {
  "A+"
  "A"
  "A-"
  "Not Yet Set"
}

Note定義

Noteを使用すると、ユーザーは特定の DBML 要素の説明を記入できます。

Table users {
  id int [pk]
  name varchar

  Note: 'This is a note of this table'
  // or
  Note {
  'This is a note of this table'
  }
}

Noteの値は文字列です。Noteが複数行にわたる場合は、複数行文字列(”’)を使用してNoteを定義できます。

プロジェクトNote

Project DBML {
  Note: '''
  # DBML - Database Markup Language
  DBML (database markup language) is a simple, readable DSL language designed to define database structures.

  ## Benefits

  * It is simple, flexible and highly human-readable
  * It is database agnostic, focusing on the essential database structure definition without worrying about the detailed syntaxes of each database
  * Comes with a free, simple database visualiser at [dbdiagram.io](http://dbdiagram.io)
  '''
}

テーブルNote

Table users {
  id int [pk]
  name varchar

  Note: 'Stores user data'
}

カラムNote

カラムにNoteを追加できるので、ダイアグラムキャンバス内のカラムにマウスを移動したときに簡単に参照できます。

column_name column_type [note: 'replace text here']

例:

Table orders {
  status varchar [
  note: '''
  💸 1 = processing,
  ✔️ 2 = shipped,
  ❌ 3 = cancelled,
  😔 4 = refunded
  ''']
}

テーブルグループNote

TableGroup e_commerce [note: 'Contains tables that are related to e-commerce system'] {
  merchants
  countries

  // or
  Note: 'Contains tables that are related to e-commerce system'
}

付箋

ダイアグラムキャンバスに付箋を追加して、簡単なリマインダーとして使用したり、複雑なアイデアを詳しく説明したりすることができます。

Table jobs {
  ...
}

Note single_line_note {
  'This is a single line note'
}

Note multiple_lines_note {
'''
  This is a multiple lines note
  This string can spans over multiple lines.
'''
}

テーブルグループ

TableGroup を使用すると、ユーザーは関連するテーブルまたは関連付けられたテーブルをグループ化できます。

TableGroup tablegroup_name { // tablegroup is case-insensitive.
  table1
  table2
  table3
}

// example
TableGroup e_commerce1 {
  merchants
  countries
}

テーブルグループメモ

テーブルグループには、その意味と目的を説明するメモを付けることができます。

TableGroup e_commerce [note: 'Contains tables that are related to e-commerce system'] {
  merchants
  countries

  // or
  Note: 'Contains tables that are related to e-commerce system'
}

テーブルグループ設定

各テーブルグループは、角括弧で囲まれたオプションの設定をすることができます: [setting1: value1, setting2: value2, setting3, setting4]

使用できるテーブル グループ設定のリスト:

  • note: ‘メモを追加する文字列’: テーブルグループにメモを追加します。
  • color: <color_code>: テーブルグループの色を変更します。
TableGroup e_commerce [color: #345] {
  merchants
  countries
}

テーブル部品

TablePartialを使用すると、再利用可能なフィールド、設定、インデックスのセットを定義できます。これらの部品を複数のテーブル定義に挿入することで、一貫性を高め、繰り返しを減らすことができます。

構文

テーブル部品を定義するには:

TablePartial partial_name [table_settings] {
  field_name field_type [field_settings]
  indexes {
    (column_name) [index_settings]
  }
}

テーブル部品を使用するには、テーブル定義で ~ プレフィックスを使用してそれを参照 (注入とも呼ばれます) します。

Table table_name {
  ~partial_name
  field_name field_type
  ~another_partial
}

例:

TablePartial base_template [headerColor: #ff0000] {
  id int [pk, not null]
  created_at timestamp [default: `now()`]
  updated_at timestamp [default: `now()`]
}

TablePartial soft_delete_template {
  delete_status boolean [not null]
  deleted_at timestamp [default: `now()`]
}

TablePartial email_index {
  email varchar [unique]

  indexes {
    email [unique]
  }
}

Table users {
  ~base_template
  ~email_index
  name varchar
  ~soft_delete_template
}

上記の結果は次のようになります:

Table users [headerColor: #ff0000] {
  id int [pk, not null]
  created_at timestamp [default: `now()`]
  updated_at timestamp [default: `now()`]
  email varchar [unique]
  name varchar
  delete_status boolean [not null]
  deleted_at timestamp [default: `now()`]

  indexes {
    email [unique]
  }
}

競合解決

複数の部品で同じフィールド、設定、またはインデックスが定義されている場合、DBML は次の優先順位に基づいて競合を解決します。

1. ローカルテーブル定義: テーブル内で直接定義されたフィールド、設定、インデックスは、部品定義のフィールド、設定、インデックスを上書きします。
2. 最後に挿入された部品定義: 部品定義間で競合が発生した場合、最後に挿入された部品定義 (ソース順) が優先されます。

複数行の文字列

複数行の文字列は、3 つの一重引用符 ”’ で囲んで定義されます。

Note: '''
  This is a block string
  This string can spans over multiple lines.
'''

🔵改行: <enter> キー

🔵行継続: \ バックスラッシュ

🔵エスケープ文字:

 🟠\: 二重バックスラッシュを使う \\

 🟠':  \' を使う

🔵ブロック文字列のインデントに使用するスペースの数は、すべての行の先頭のスペースの最小数になります。パーサーは最終出力からインデントスペースの数を自動的に削除します。上記の例の結果は次のようになります。

  This is a block string
  This string can spans over multiple lines.

コメント

1行コメント

// を使用してコードにコメントを記入できるため、後でコードを確認するのが簡単になります。

// order_items refer to items from that order

複数行コメント

/**/ で挟むことで、コード内に複数行にわたるコメントを入れることもできます。

/*
  This is a
  Multi-lines
  comment
*/

構文の一貫性

DBML はデータベース用の標準言語であり、構文は一貫しており、明確で広範な機能を提供します。

  • 中括弧 {}: インデックス、制約、テーブル定義のグループ化
  • 角括弧 []: 設定
  • スラッシュ //: コメント
  • column_name はプレーンテキストで記述
  • 一重引用符 (‘string’): 文字列値
  • 二重引用符 (“column name”): 変数の引用符
  • 三重引用符 (”’複数行文字列”’): 複数行の文字列値
  • バッククォート `: 関数式

  • 2
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました