Trình tạo sơ đồ ER Mermaid
Sơ đồ thực thể - liên kết cho thấy các bảng, các cột của chúng và cách chúng nối với nhau. Nó hợp khi chủ đề là lược đồ cơ sở dữ liệu và những câu hỏi đáng quan tâm xoay quanh khóa và bội số — một-nhiều, tùy chọn, hay thông qua một bảng trung gian. Với các kiểu có hành vi và kế thừa thì sơ đồ lớp tốt hơn.
Lược đồ đơn hàng đã chuẩn hóa với bảng trung gian
Phần đáng chú ý là `}o--||` ở dòng đơn hàng: đó là cách diễn đạt trung thực một liên kết nhiều-nhiều, thông qua bảng trung gian có cột riêng, thay vì giả vờ rằng hai bảng nối thẳng với nhau. Việc lưu giá ngay trên dòng chứ không chỉ trên sản phẩm đúng là loại quyết định mà sơ đồ nên phơi bày. Cũng để ý mọi nhãn liên kết đều nằm trong dấu nháy: với tiếng Việt đó không phải tùy chọn.
erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"
DON_HANG ||--|{ DONG_DON_HANG : "gồm có"
SAN_PHAM ||--o{ DONG_DON_HANG : "xuất hiện trong"
KHACH_HANG ||--o{ DIA_CHI : "giao đến"
DON_HANG ||--o| HOA_DON : "được xuất cho"
KHACH_HANG {
int id PK
string email UK "lưu ở dạng chữ thường"
string ho_ten
string so_dien_thoai
datetime ngay_tao
}
DON_HANG {
int id PK
int khach_hang_id FK
string trang_thai
decimal tong_tien
}
DONG_DON_HANG {
int don_hang_id PK, FK
int san_pham_id PK, FK
int so_luong
decimal don_gia "giá tại thời điểm đặt hàng"
}
SAN_PHAM {
int id PK
string ma_hang UK
string ten_san_pham
}
DIA_CHI {
int id PK
int khach_hang_id FK
string phuong_xa
}
HOA_DON {
int id PK
string so_hoa_don UK
decimal tien_thue
}Ví dụ có giải thích
1. Hai thực thể và một liên kết
Mọi liên kết ER đều đòi một nhãn sau dấu hai chấm — khác với cạnh của lưu đồ, nó không phải tùy chọn. Đọc lên như một câu: KHACH_HANG đặt DON_HANG.
erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"2. Thêm các cột
Mỗi dòng thuộc tính là `kiểu tên` và cả hai phần đều bắt buộc. `PK`, `FK` và `UK` đánh dấu khóa; chuỗi trong dấu nháy ở cuối là ghi chú cho cột.
erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"
KHACH_HANG {
int id PK
string email UK
string ho_ten
}
DON_HANG {
int id PK
int khach_hang_id FK
datetime ngay_dat "theo giờ UTC"
}3. Bội số nói lên điều gì đó
Hai ký hiệu gần một thực thể nhất chính là bội số của nó. Ví dụ này nói rằng một đơn hàng phải có ít nhất một dòng, nhưng một khách hàng có thể chưa có đơn hàng nào: một ràng buộc thật mà lược đồ nên bắt buộc và sơ đồ nên cho thấy.
erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"
DON_HANG ||--|{ DONG_DON_HANG : "gồm có"
DONG_DON_HANG }o--|| SAN_PHAM : "tham chiếu tới"4. Nhiều-nhiều thông qua bảng trung gian
Mermaid vẽ được liên kết nhiều-nhiều trực tiếp, nhưng trong lược đồ thật gần như không bao giờ có: bên dưới luôn là một bảng trung gian. Vẽ nó ra thì trung thực hơn và chừa chỗ cho những cột thuộc về chính mối liên kết đó.
erDiagram
HOC_VIEN ||--o{ DANG_KY : "ghi danh vào"
KHOA_HOC ||--o{ DANG_KY : "được mở qua"
DANG_KY {
int hoc_vien_id PK, FK
int khoa_hoc_id PK, FK
datetime ngay_dang_ky
string diem "để trống cho tới khi thi"
}
HOC_VIEN {
int id PK
string ho_ten
}
KHOA_HOC {
int id PK
string ma_khoa UK
}5. Liên kết tự tham chiếu
Một bảng có thể liên kết với chính nó: cây quản lý, cây danh mục, chuỗi bình luận. Nhãn liên kết ở đây quan trọng hơn bình thường, vì cả hai đầu đều là cùng một thực thể.
erDiagram
NHAN_VIEN ||--o{ NHAN_VIEN : "quản lý"
NHAN_VIEN {
int id PK
int quan_ly_id FK "để trống với ban giám đốc"
string ho_ten
string chuc_danh
}Tóm tắt cú pháp sơ đồ ER
Bội số viết bằng hai ký hiệu ở mỗi đầu liên kết và đọc từ trong ra ngoài. Cặp bên trái mô tả thực thể bên trái, cặp bên phải mô tả thực thể bên phải.
| Cú pháp | Ý nghĩa |
|---|---|
| erDiagram | Mở sơ đồ. Phân biệt hoa thường: `erdiagram` không chạy. |
| A ||--o{ B : "nhãn" | Liên kết. Nhãn là bắt buộc. |
| || | Đúng một. |
| o| | Không hoặc một. |
| }| | Một hoặc nhiều. |
| }o | Không hoặc nhiều. |
| -- | Liên kết định danh — đường liền. |
| .. | Liên kết không định danh — đường đứt. |
| A { ... } | Khối thuộc tính của thực thể A. |
| int id PK | Thuộc tính: kiểu trước, tên sau, rồi tới ký hiệu khóa nếu có. |
| PK / FK / UK | Khóa chính, khóa ngoại, khóa duy nhất. |
| int id PK, FK | Nhiều ký hiệu khóa, ngăn nhau bằng dấu phẩy. |
| string email "ghi chú" | Chuỗi trong dấu nháy ở cuối là ghi chú cho cột. |
| A ||--o{ B : "thuộc về" | Dấu nháy là BẮT BUỘC ngay khi nhãn có khoảng trắng. Không có nó, nhãn bị cắt ở khoảng trắng đầu tiên và mỗi chữ còn lại biến thành một thực thể ma. |
Sáu lỗi làm hỏng sơ đồ ER
ER có ngữ pháp chặt nhất trong sáu loại: thứ lọt được ở sơ đồ khác thì ở đây bị từ chối thẳng. Nhưng nó cũng có một lỗi im lặng mà người viết tiếng Việt đặc biệt dễ mắc. Tất cả đều dựng lại trên Mermaid 11.12.2.
Bạn thấy gì
Vẽ được, nhãn bị cắt cụt, và trong sơ đồ xuất hiện những thực thể bạn không hề viết
Vì sao
Nhãn liên kết có khoảng trắng mà không có dấu nháy. Đây là lỗi gây phiền nhất với tiếng Việt, vì tiếng Việt viết rời từng âm tiết nên hầu như mọi động từ quan hệ đều nhiều chữ: «đặt hàng», «thuộc về», «xuất hiện trong». Đã đo: `KHACH_HANG ||--o{ DON_HANG : đặt hàng` không báo lỗi nào, rút nhãn còn «đặt» và tạo ra một thực thể rỗng tên «hàng». Với ba chữ thì sinh ra hai thực thể ma. Hai bảng vẽ thành bốn hình chữ nhật và không có gì cảnh báo bạn — ngoài việc viewBox nhảy từ 128 lên 398 pixel.
Cách sửa
Đặt dấu nháy quanh mọi nhãn có khoảng trắng. Với tiếng Việt điều đó gần như luôn đúng; coi nó là quy tắc thì dễ hơn là cân nhắc từng lần.
erDiagram
KHACH_HANG ||--o{ DON_HANG : đặt hàngerDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt hàng"Bạn thấy gì
Parse error, kết thúc bằng: Expecting 'COLON', 'STYLE_SEPARATOR', got 'NEWLINE'
Vì sao
Liên kết không có nhãn. Khác với cạnh của lưu đồ, dấu hai chấm và nhãn là bắt buộc: thiếu chúng thì dòng đơn giản là kết thúc quá sớm.
Cách sửa
Thêm dấu hai chấm và một cụm động từ, đặt trong dấu nháy nếu có khoảng trắng.
erDiagram
KHACH_HANG ||--o{ DON_HANGerDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"Bạn thấy gì
Parse error, kết thúc bằng: got 'UNICODE_TEXT'
Vì sao
Ký hiệu bội số không hợp lệ. Chỉ có `||`, `o|`, `}|` và `}o` là đúng (cùng dạng đối xứng của chúng); mọi thứ khác đều đổ. `oo` là lỗi gõ kinh điển, xuất phát từ giả định rằng ký pháp này đối xứng.
Cách sửa
Dùng một trong bốn cặp. `||--o{` — đúng một tới không hoặc nhiều — bao được phần lớn khóa ngoại.
erDiagram
KHACH_HANG ||--oo{ DON_HANG : "đặt"erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"Bạn thấy gì
Parse error, kết thúc bằng: Expecting 'ATTRIBUTE_WORD', got 'BLOCK_STOP'
Vì sao
Một thuộc tính có tên nhưng không có kiểu. Thuộc tính ER viết theo dạng `kiểu tên`, và kiểu không phải tùy chọn — điều này làm những người quen với cơ sở dữ liệu không lược đồ bất ngờ.
Cách sửa
Cho mỗi thuộc tính một kiểu. Cứ đặt ra nếu lược đồ thật không có: `string`, `int`, `json`.
erDiagram
KHACH_HANG {
email
}erDiagram
KHACH_HANG {
string email
}Bạn thấy gì
Parse error, kết thúc bằng: Expecting 'NON_IDENTIFYING', 'IDENTIFYING', got 'UNICODE_TEXT'
Vì sao
Đường nối giữa hai ký hiệu bội số bị sai. Nó phải dài đúng hai ký tự: `--` cho liên kết định danh hoặc `..` cho liên kết không định danh. Một dấu gạch ngang đơn không phải dạng rút gọn của `--`, đó là lỗi cú pháp.
Cách sửa
Viết `--` hoặc `..` giữa hai cặp bội số.
erDiagram
KHACH_HANG ||-o{ DON_HANG : "đặt"erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"Bạn thấy gì
Bội số vẽ ra được, nhưng lại mô tả ràng buộc ngược lại
Vì sao
Hai ký hiệu gần một thực thể nhất thuộc về đúng thực thể đó, và đọc ngược chúng thì rất dễ. `KHACH_HANG ||--o{ DON_HANG` nói rằng một khách hàng có không hoặc nhiều đơn hàng. Lật thành `KHACH_HANG }o--|| DON_HANG` là bạn đang khẳng định mỗi khách hàng thuộc về đúng một đơn hàng, điều chẳng có nghĩa gì — và nó vẽ ra không một lời phản đối.
Cách sửa
Đọc từ trong ra ngoài: những ký hiệu chạm vào KHACH_HANG mô tả có bao nhiêu khách hàng, chứ không phải bao nhiêu đơn hàng.
erDiagram
KHACH_HANG }o--|| DON_HANG : "đặt"erDiagram
KHACH_HANG ||--o{ DON_HANG : "đặt"Ghi chú về việc vẽ
Đo trên Mermaid 11.12.2, đúng phiên bản trang này dùng.
Bố cục do các liên kết quyết định, không phải do số lượng thực thể
Một chuỗi thực thể nối lần lượt vào nhau sẽ vẽ thành một cột cao: bốn mươi thực thể cho viewBox khoảng 116×7315, so với 116×470 khi có ba. Nhưng cũng bốn mươi thực thể ấy mà cùng nối vào một bảng trung tâm thì cho ra thứ rộng hơn và thấp hơn rất nhiều. Đây là loại sơ đồ duy nhất ở đây mà hình dạng dữ liệu của bạn làm thay đổi hình dạng bức tranh nhiều hơn là kích thước của nó, nên một lược đồ không vừa khung thường được chữa bằng cách đổi xem vẽ những liên kết nào chứ không phải bao nhiêu liên kết.
Với tiếng Việt, gần như nhãn nào cũng cần dấu nháy
Điều này đáng nhắc lại vì đây là lỗi im lặng tốn kém nhất trên trang này. Nhãn liên kết tiếng Anh có thể chỉ một chữ — places, contains, references — nên trong tài liệu tiếng Anh dấu nháy trông như đồ trang trí. Tiếng Việt viết rời từng âm tiết, nên gần như nhãn nào cũng nhiều chữ và không có dấu nháy thì rã ra. Quy tắc thực dụng: luôn đặt nhãn trong dấu nháy rồi thôi không nghĩ về nó nữa.
Tên thực thể phân biệt hoa thường; hãy chọn một cách viết rồi giữ nguyên
`KHACH_HANG` và `khach_hang` là hai thực thể khác nhau, và nhắc tới cả hai trong một sơ đồ sẽ cho ra hai hình chữ nhật mà không cảnh báo gì. Mermaid không ép quy ước viết hoa, nhưng nên theo nó chính vì nó làm lộ ra tham chiếu viết thường do sơ ý. Dấu tiếng Việt dùng được trong tên thực thể, nhưng vì tên thực thể là định danh nên khoảng trắng thì không: hãy chọn dấu gạch dưới như `DONG_DON_HANG` hoặc viết liền, rồi giữ nguyên cách đó trong cả lược đồ.
Ngữ pháp chặt nhất trong sáu loại
Nhãn liên kết là bắt buộc, kiểu thuộc tính cũng vậy, và các ký hiệu bội số tạo thành một tập đóng. So với Gantt, nơi gần như thứ gì cũng vẽ ra và lỗi thì im lặng, ER đổ sớm và đổ ồn ào. Đó là một ưu điểm: nếu một sơ đồ ER đã vẽ ra được thì khá nhiều khả năng nó đúng là sơ đồ bạn định vẽ — trừ ngoại lệ rõ ràng là nhãn thiếu dấu nháy.
Nhãn là HTML, nên việc xuất PNG phải vẽ lại
Bảng thuộc tính của các thực thể được vẽ bên trong một `<foreignObject>` trong SVG, nên trình duyệt không thể chuyển thẳng chúng thành ảnh raster trên canvas. Chức năng xuất PNG của trang này trước đây lặng lẽ trả về tệp SVG; giờ nó vẽ lại sơ đồ bằng nhãn văn bản SVG thuần trước và cho ra tệp PNG đúng, đủ kích thước, với kiểu chữ chỉ khác đi rất khẽ.
Khi nào nên dùng loại sơ đồ khác
Nếu bạn cần kế thừa, giao diện hay phương thức thì đây là loại sơ đồ sai: ER không có khái niệm nào trong số đó. Hãy dùng sơ đồ lớp và chấp nhận rằng nó mô hình hóa mã nguồn của bạn chứ không phải các bảng của bạn.
Nếu lược đồ lớn, một sơ đồ ER vẽ trọn vẹn sẽ thành tấm áp phích dán tường không ai đọc. Hãy vẽ năm cái bảng liên quan tới điều bạn đang giải thích lúc đó và để phần còn lại ngoài khung; sơ đồ là một lập luận chứ không phải một bản kiểm kê.
Còn nếu câu hỏi thật sự là dữ liệu chảy giữa các hệ thống thế nào chứ không phải nó được lưu ra sao, thì một lưu đồ với mỗi hệ thống một nhóm con sẽ trả lời được, còn sơ đồ ER thì không.
Các loại sơ đồ khác
Viết bởi Dominik Malsch · Cập nhật lần cuối: