Biểu đồ ER
Biểu đồ quan hệ thực thể (viết tắt là biểu đồ ER) mô tả những sự vật có liên quan đến nhau trong một lĩnh vực tri thức cụ thể. Một biểu đồ ER cơ bản gồm các loại thực thể (dùng để phân loại những sự vật được quan tâm), và chỉ định các quan hệ có thể tồn tại giữa các thực thể (là các thực thể của những loại thực thể này),Xin lưu ý rằng trong thực tế sử dụng biểu đồ ER, gần như luôn gọi 'loại thực thể' một cách ngắn gọn là 'thực thể'. Ví dụ, 'loại thực thể CUSTOMER' thường được gọi trực tiếp là 'thực thể CUSTOMER'. Cách làm này rất phổ biến, do đó không khuyến nghị dùng cách khác, nhưng về mặt kỹ thuật, thực thể là thực thể trừu tượng của loại thực thể, và biểu đồ ER hiển thị chính những thực thể trừu tượng này cùng quan hệ giữa chúng. Đây là lý do vì sao thực thể luôn được đặt tên bằng danh từ số ít.
Sao chép
Nhúng
---
title: Order example
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
Tên thực thể thường được viết hoa, mặc dù không có tiêu chuẩn được công nhận cho việc này, và cú pháp Mermaid cũng không bắt buộc.
Quan hệ giữa các thực thể được biểu diễn bằng đường có ký hiệu điểm mút thể hiện bản số. Mermaid sử dụng ký hiệu chân quạ phổ biến nhất, chân quạ trực quan thể hiện rằng thực thể mà nó kết nối có thể có nhiều thực thể.
Biểu đồ ER có thể dùng cho nhiều mục đích, từ mô hình logic trừu tượng không chứa bất kỳ chi tiết triển khai nào, đến mô hình vật lý của bảng cơ sở dữ liệu quan hệ. Việc bao gồm định nghĩa thuộc tính trên biểu đồ ER giúp hiểu mục đích và ý nghĩa của thực thể; những định nghĩa thuộc tính này không cần phải đầy đủ, thường chỉ một phần nhỏ thuộc tính là đủ. Mermaid cho phép định nghĩa chúng theo kiểu và tên.
Sao chép
Nhúng
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
Khi bao gồm thuộc tính trên biểu đồ ER, bạn phải quyết định có đưa khóa ngoại vào làm thuộc tính hay không, điều này có thể phụ thuộc vào mức độ bạn muốn biểu diễn cấu trúc bảng quan hệ. Nếu biểu đồ của bạn là mô hình logic và không nhằm ngụ ý việc triển khai quan hệ, thì tốt nhất không nên bao gồm các thuộc tính này, vì quan hệ liên kết đã truyền đạt cách các thực thể liên kết với nhau. Ví dụ, cấu trúc dữ liệu JSON có thể dùng mảng để thực hiện quan hệ một-nhiều mà không cần thuộc tính khóa ngoại. Tương tự, ngôn ngữ lập trình hướng đối tượng có thể dùng con trỏ hoặc tham chiếu tới tập hợp. Ngay cả với những mô hình nhằm triển khai quan hệ, cũng có thể cho rằng việc bao gồm thuộc tính khóa ngoại sẽ lặp lại thông tin mà quan hệ thể hiện, và không tăng thêm ý nghĩa cho thực thể.
Cú pháp
Thực thể và quan hệ
Cú pháp Mermaid của biểu đồ ER tương thích với PlantUML, và mở rộng chức năng dùng để đánh dấu quan hệ. Mỗi câu lệnh bao gồm những nội dung sau:
Sao chép
Nhúng
<first-entity> [<relationship> <second-entity> : <relationship-label>]
- first-entity là tên của thực thể thứ nhất. Tên hỗ trợ bất kỳ ký tự Unicode nào, nếu được bao bằng dấu ngoặc kép thì có thể chứa dấu cách.
- relationship mô tả mối quan hệ tương hỗ giữa hai thực thể.
- second-entity là tên của thực thể còn lại.
- relationship-label mô tả quan hệ từ góc nhìn của thực thể thứ nhất.
Ví dụ:
Sao chép
Nhúng
PROPERTY ||--|{ ROOM : contains
Khai báo này có thể được hiểu là: một thuộc tính chứa một hoặc nhiều phòng, còn một phòng chỉ thuộc về một thuộc tính. Nhãn ở đây được xét từ góc nhìn của thực thể thứ nhất: một thuộc tính chứa một phòng, nhưng một phòng không chứa thuộc tính. Từ góc nhìn của thực thể thứ hai, nhãn tương đương thường dễ suy ra.
Chỉ phần first-entity là bắt buộc. Điều này cho phép hiển thị thực thể không có quan hệ, rất hữu ích khi xây dựng biểu đồ theo cách lặp. Nếu chỉ định các phần khác của câu lệnh, thì tất cả các phần đều bắt buộc.
Văn bản Unicode
Tên thực thể, quan hệ và thuộc tính đều hỗ trợ văn bản unicode.
Sao chép
Nhúng
erDiagram
"This ❤ Unicode"
Cú pháp quan hệ
Phần quan hệ của mỗi câu lệnh có thể được tách thành ba phần nhỏ:
- Bản số của thực thể thứ nhất so với thực thể thứ hai
- Quan hệ này có cấp cho thực thể con khả năng nhận diện hay không
- Bản số của thực thể thứ hai so với thực thể thứ nhất
Bản số là một thuộc tính dùng để mô tả số lượng phần tử mà một thực thể khác có thể liên kết với thực thể liên quan. Trong ví dụ trên, một PROPERTY có thể liên kết với một hoặc nhiều thực thể ROOM, còn một ROOM chỉ có thể liên kết với một PROPERTY. Mỗi ký hiệu bản số có hai ký tự, ký tự ngoài cùng biểu thị giá trị lớn nhất, ký tự trong cùng biểu thị giá trị nhỏ nhất. Bảng dưới đây tóm tắt các khả năng của bản số:
| Giá trị (trái) | Giá trị (phải) | Ý nghĩa |
|---|---|---|
| |o | o| | Không hoặc một |
| || | || | Đúng một |
| }o | o{ | Không hoặc nhiều (không giới hạn) |
| }| | |{ | Một hoặc nhiều (không giới hạn) |
| Giá trị (trái) | Giá trị (phải) | Ý nghĩa |
|---|---|---|
| one or zero | one or zero | Không hoặc một |
| zero or one | zero or one | Không hoặc một |
| one or more | one or more | Một hoặc nhiều |
| one or many | one or many | Một hoặc nhiều |
| many(1) | many(1) | Một hoặc nhiều |
| 1+ | 1+ | Một hoặc nhiều |
| zero or more | zero or more | Không hoặc nhiều |
| zero or many | zero or many | Không hoặc nhiều |
| many(0) | many(0) | Không hoặc nhiều |
| 0+ | 0+ | Không hoặc nhiều |
| only one | only one | Đúng một |
| 1 | 1 | Đúng một |
Nhận diện
Quan hệ có thể được chia thành quan hệ nhận diện và không nhận diện, lần lượt được kết xuất bằng nét liền hoặc nét đứt. Điều này quan trọng khi một thực thể không thể tồn tại độc lập nếu thiếu thực thể kia. Ví dụ, một công ty cung cấp bảo hiểm cho người lái xe có thể cần lưu dữ liệu NAMED-DRIVER. Khi mô hình hóa, trước tiên chúng ta có thể nhận thấy rằng một CAR có thể được nhiều PERSON lái, và một PERSON có thể lái nhiều CAR, cả hai đều có thể tồn tại mà không cần bên kia, do đó đây là quan hệ không nhận diện, chúng ta có thể chỉ định trong Mermaid là: PERSON }|..|{ CAR : "driver". Xin lưu ý hai dấu chấm ở giữa quan hệ, điều này sẽ khiến một đường nét đứt được vẽ giữa hai thực thể. Tuy nhiên, khi quan hệ nhiều-nhiều này được phân giải thành hai quan hệ một-nhiều, chúng ta nhận thấy rằng nếu không có PERSON và CAR thì NAMED-DRIVER không thể tồn tại. Những quan hệ này trở thành quan hệ nhận diện, và sẽ được biểu diễn bằng dấu gạch nối, tương ứng với một đường nét liền:
| Giá trị | Bí danh |
|---|---|
| -- | Nhận diện |
| .. | Không nhận diện |
| Giá trị | 别名为 |
|---|---|
| to | Nhận diện |
| optionally to | Không nhận diện |
Sao chép
Nhúng
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o..o{ NAMED-DRIVER : is
Sao chép
Nhúng
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o--o{ NAMED-DRIVER : is
Thuộc tính
Có thể định nghĩa thuộc tính cho thực thể bằng cách chỉ định tên thực thể, theo sau là một khối chứa nhiều type name, trong đó khối được bao quanh bởi một dấu ngoặc nhọn {}. Thuộc tính sẽ hiển thị bên trong khung thực thể, ví dụ:
Sao chép
Nhúng
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
Giá trị type phải bắt đầu bằng ký tự chữ cái, và có thể chứa số, dấu gạch nối, dấu gạch dưới, dấu ngoặc đơn và dấu ngoặc vuông. Giá trị name tuân theo định dạng tương tự type, nhưng cũng có thể bắt đầu bằng dấu hoa thị, như một tùy chọn khác để chỉ ra thuộc tính là khóa chính. Ngoài ra, không có giới hạn nào khác, cũng không có tập hợp kiểu dữ liệu hợp lệ ngầm định.
Bí danh thực thể
Có thể dùng dấu ngoặc vuông để thêm bí danh cho thực thể. Nếu cung cấp bí danh, biểu đồ sẽ hiển thị bí danh thay vì tên thực thể; bí danh tuân theo tất cả các quy tắc giống như tên thực thể.
Sao chép
Nhúng
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
Khóa thuộc tính và chú thích
Thuộc tính cũng có thể định nghĩa khóa hoặc chú thích. Khóa có thể là khóa chính (PK), khóa ngoại (FK) hoặc khóa duy nhất (UK). Để chỉ định nhiều ràng buộc khóa trên một thuộc tính, hãy phân tách chúng bằng dấu phẩy (ví dụ, PK, FK). Chú thích được định nghĩa bằng dấu ngoặc kép ở cuối thuộc tính, chú thích không được chứa ký tự dấu ngoặc kép.
Sao chép
Nhúng
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber PK
string make
string model
string[] parts
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string driversLicense PK "The license #"
string(99) firstName "Only 99 characters are allowed"
string lastName
string phone UK
int age
}
NAMED-DRIVER {
string carRegistrationNumber PK, FK
string driverLicence PK, FK
}
MANUFACTURER ||--o{ CAR : makes
Hướng
Câu lệnh hướng khai báo hướng của biểu đồ.
TB khai báo hướng của biểu đồ là từ trên xuống dưới, BT có thể đảo ngược nó thành từ dưới lên trên.
Sao chép
Nhúng
erDiagram
direction TB
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
LR khai báo hướng của biểu đồ là từ trái sang phải, RL có thể đảo ngược nó thành từ phải sang trái.
Sao chép
Nhúng
erDiagram
direction LR
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
Đặt kiểu cho nút
Có thể áp dụng kiểu cụ thể cho nút, ví dụ viền đậm hơn hoặc màu nền khác.
Sao chép
Nhúng
erDiagram
id1||--||id2 : label
style id1 fill:pink,stroke:yellow,stroke-width:4px
style id2 fill:#69d,stroke:#f96,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
Cũng có thể gắn kiểu vào danh sách nút trong một câu lệnh:
Sao chép
Nhúng
style nodeId1,nodeId2 styleList
Lớp
Thay vì định nghĩa kiểu mỗi lần, tiện hơn là định nghĩa một lớp kiểu và gắn lớp đó vào các nút cần giao diện khác biệt.
Định nghĩa lớp như ví dụ dưới đây:
Sao chép
Nhúng
classDef className fill:pink,stroke:#333,stroke-width:4px
Cũng có thể định nghĩa nhiều lớp trong một câu lệnh:
Sao chép
Nhúng
classDef firstClassName,secondClassName font-size:12pt
Cú pháp gắn lớp vào nút như sau:
Sao chép
Nhúng
class nodeId1 className
Cũng có thể gắn một lớp vào danh sách nút trong một câu lệnh:
Sao chép
Nhúng
class nodeId1,nodeId2 className
Cũng có thể gắn nhiều lớp cùng lúc:
Sao chép
Nhúng
class nodeId1,nodeId2 className1,className2
Cách đơn giản để thêm lớp là dùng toán tử ::: để gắn tên lớp vào nút, như sau:
Sao chép
Nhúng
erDiagram
direction TB
CAR:::someclass {
string registrationNumber
string make
string model
}
PERSON:::someclass {
string firstName
string lastName
int age
}
HOUSE:::someclass
classDef someclass fill:#f96
Có thể dùng cú pháp sau để khai báo quan hệ giữa các thực thể:
Sao chép
Nhúng
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef foobar stroke:#00f
Tương tự câu lệnh class, cú pháp viết tắt cũng có thể áp dụng nhiều lớp cùng lúc:
Sao chép
Nhúng
nodeId:::className1,className2
Lớp mặc định
Nếu một lớp được đặt tên là default, nó sẽ được gán cho tất cả các lớp không có định nghĩa lớp cụ thể.
Sao chép
Nhúng
classDef default fill:pink,stroke:#333,stroke-width:4px;
Lưu ý: các kiểu tùy chỉnh đến từ câu lệnh kiểu hoặc lớp khác có quyền ưu tiên, và ghi đè kiểu mặc định. (Ví dụ, lớp default đặt nền màu hồng cho nút, nhưng nếu áp dụng lớp blue, sẽ cung cấp màu nền xanh lam cho nút đó.)
Sao chép
Nhúng
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef default fill:pink,stroke-width:4px
classDef foo stroke:#f90
classDef bar stroke:#ff0
classDef foobar stroke:#69f
Cấu hình
Bố cục
Bố cục của biểu đồ được xử lý bởi render(), bố cục mặc định là bố cục ELK, phù hợp với các biểu đồ lớn và phức tạp hơn.
Để chuyển sang bố cục Dagre cổ điển, bạn có thể đặt nó trong config của YAML frontmatter
Sao chép
Nhúng
---
config:
layout: dagre
---
Nội dung mã Mermaid như sau:
Sao chép
Nhúng
---
title: Order example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses