ตัวแก้ไขไดอะแกรม ER Mermaid
ไดอะแกรมเอนทิตี-ความสัมพันธ์แสดงตาราง คอลัมน์ของตาราง และวิธีที่ตารางเชื่อมถึงกัน เหมาะเมื่อแก่นของเรื่องคือสคีมาของฐานข้อมูล และคำถามที่น่าสนใจเกี่ยวกับคีย์และพหุภาพ เช่น หนึ่งต่อกลุ่ม เลือกได้ หรือผ่านตารางเชื่อม ส่วนชนิดข้อมูลที่มีพฤติกรรมและการสืบทอด ไดอะแกรมคลาสเหมาะกว่า
สคีมาคำสั่งซื้อที่ทำให้เป็นบรรทัดฐานพร้อมตารางเชื่อม
ส่วนที่น่าสังเกตคือ `}o--||` ตรงรายการสินค้า เพราะนั่นคือวิธีบอกความสัมพันธ์แบบกลุ่มต่อกลุ่มอย่างซื่อตรง คือผ่านตารางเชื่อมที่มีคอลัมน์ของตัวเอง แทนที่จะแกล้งทำเป็นว่าสองตารางเชื่อมกันตรง ๆ การเก็บราคาไว้ที่รายการ ไม่ใช่แค่ที่สินค้า คือการตัดสินใจแบบที่ไดอะแกรมควรทำให้เห็น สังเกตด้วยว่าชื่อเอนทิตีเป็นอักษรไทยได้ ไดอะแกรม ER ยอมรับอักษรไทยในตำแหน่งนี้
erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"
คำสั่งซื้อ ||--|{ รายการสินค้า : "ประกอบด้วย"
สินค้า ||--o{ รายการสินค้า : "ปรากฏใน"
ลูกค้า ||--o{ ที่อยู่ : "จัดส่งไปที่"
คำสั่งซื้อ ||--o| ใบกำกับภาษี : "ออกให้กับ"
ลูกค้า {
int รหัส PK
string อีเมล UK "เก็บเป็นตัวพิมพ์เล็ก"
string ชื่อ
string เลขผู้เสียภาษี
datetime วันที่สร้าง
}
คำสั่งซื้อ {
int รหัส PK
int รหัสลูกค้า FK
string สถานะ
decimal ยอดรวม
}
รายการสินค้า {
int รหัสคำสั่งซื้อ PK, FK
int รหัสสินค้า PK, FK
int จำนวน
decimal ราคา "ราคา ณ เวลาที่สั่งซื้อ"
}
สินค้า {
int รหัส PK
string รหัสสินค้า UK
string ชื่อ
}
ที่อยู่ {
int รหัส PK
int รหัสลูกค้า FK
string รหัสไปรษณีย์
}
ใบกำกับภาษี {
int รหัส PK
string เลขที่ใบกำกับ UK
decimal ภาษีมูลค่าเพิ่ม
}ตัวอย่างพร้อมคำอธิบาย
1. สองเอนทิตีกับหนึ่งความสัมพันธ์
ทุกความสัมพันธ์ใน ER ต้องมีป้ายกำกับหลังทวิภาค ต่างจากเส้นเชื่อมของผังงานตรงที่มันไม่ใช่ของเลือกได้ อ่านออกมาเป็นประโยคได้เลยว่า ลูกค้าสั่งซื้อคำสั่งซื้อ
erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"2. เพิ่มคอลัมน์
บรรทัดคุณลักษณะแต่ละบรรทัดอยู่ในรูป `ชนิด ชื่อ` และทั้งสองส่วนเป็นสิ่งบังคับ ส่วน `PK`, `FK` และ `UK` ใช้ทำเครื่องหมายคีย์ ข้อความในเครื่องหมายคำพูดตอนท้ายคือหมายเหตุของคอลัมน์
erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"
ลูกค้า {
int รหัส PK
string อีเมล UK
string ชื่อ
}
คำสั่งซื้อ {
int รหัส PK
int รหัสลูกค้า FK
datetime วันที่สั่ง "เวลา UTC"
}3. พหุภาพที่บอกอะไรบางอย่าง
สัญลักษณ์สองตัวที่อยู่ใกล้เอนทิตีที่สุดคือพหุภาพของเอนทิตีนั้น ตัวอย่างนี้บอกว่าคำสั่งซื้อหนึ่งต้องมีรายการอย่างน้อยหนึ่งรายการ แต่ลูกค้าอาจยังไม่มีคำสั่งซื้อเลยก็ได้ นี่คือข้อจำกัดจริงที่สคีมาควรบังคับและไดอะแกรมควรแสดง
erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"
คำสั่งซื้อ ||--|{ รายการสินค้า : "ประกอบด้วย"
รายการสินค้า }o--|| สินค้า : "อ้างถึง"4. กลุ่มต่อกลุ่มผ่านตารางเชื่อม
Mermaid วาดความสัมพันธ์กลุ่มต่อกลุ่มแบบตรง ๆ ได้ แต่ในสคีมาจริงแทบไม่มีแบบนั้น เพราะข้างใต้ย่อมมีตารางเชื่อมอยู่ การวาดมันออกมาซื่อตรงกว่าและเปิดที่ให้คอลัมน์ที่เป็นของความสัมพันธ์เอง
erDiagram
นักเรียน ||--o{ การลงทะเบียน : "ลงทะเบียนใน"
รายวิชา ||--o{ การลงทะเบียน : "เปิดสอนผ่าน"
การลงทะเบียน {
int รหัสนักเรียน PK, FK
int รหัสรายวิชา PK, FK
datetime วันที่ลงทะเบียน
string เกรด "ว่างไว้จนกว่าจะสอบ"
}
นักเรียน {
int รหัส PK
string ชื่อ
}
รายวิชา {
int รหัส PK
string รหัสวิชา UK
}5. ความสัมพันธ์กับตัวเอง
ตารางหนึ่งอาจมีความสัมพันธ์กับตัวเองได้ เช่น สายบังคับบัญชา ต้นไม้หมวดหมู่ หรือสายความคิดเห็น ป้ายกำกับของความสัมพันธ์ที่นี่สำคัญกว่าปกติ เพราะปลายทั้งสองข้างคือเอนทิตีเดียวกัน
erDiagram
พนักงาน ||--o{ พนักงาน : "ดูแล"
พนักงาน {
int รหัส PK
int รหัสหัวหน้า FK "ว่างไว้สำหรับผู้บริหารสูงสุด"
string ชื่อ
string ตำแหน่ง
}สรุปไวยากรณ์ไดอะแกรม ER
พหุภาพเขียนด้วยสัญลักษณ์สองตัวที่ปลายแต่ละข้างของความสัมพันธ์ และอ่านจากด้านในออกด้านนอก คู่ทางซ้ายอธิบายเอนทิตีทางซ้าย คู่ทางขวาอธิบายเอนทิตีทางขวา
| ไวยากรณ์ | ความหมาย |
|---|---|
| erDiagram | เปิดไดอะแกรม แยกตัวพิมพ์ใหญ่เล็ก `erdiagram` ใช้ไม่ได้ |
| A ||--o{ B : "ป้ายกำกับ" | ความสัมพันธ์ ป้ายกำกับเป็นสิ่งบังคับ |
| || | หนึ่งพอดี |
| o| | ศูนย์หรือหนึ่ง |
| }| | หนึ่งหรือมากกว่า |
| }o | ศูนย์หรือมากกว่า |
| -- | ความสัมพันธ์แบบระบุตัวตน — เส้นทึบ |
| .. | ความสัมพันธ์แบบไม่ระบุตัวตน — เส้นประ |
| A { ... } | บล็อกคุณลักษณะของเอนทิตี A |
| int รหัส PK | คุณลักษณะ ชนิดมาก่อน ตามด้วยชื่อ แล้วจึงเป็นเครื่องหมายคีย์ถ้ามี |
| PK / FK / UK | คีย์หลัก คีย์นอก คีย์เอกลักษณ์ |
| int รหัส PK, FK | เครื่องหมายคีย์หลายตัว คั่นด้วยจุลภาค |
| string อีเมล "หมายเหตุ" | ข้อความในเครื่องหมายคำพูดตอนท้ายคือหมายเหตุของคอลัมน์ |
| A ||--o{ B : "เป็นของ" | เครื่องหมายคำพูดเป็นสิ่งบังคับทันทีที่ป้ายกำกับมีช่องว่าง ถ้าไม่มี ป้ายกำกับจะถูกตัดที่ช่องว่างแรกและทุกคำที่เหลือจะกลายเป็นเอนทิตีผี |
หกข้อผิดพลาดที่ทำให้ไดอะแกรม ER พัง
ในบรรดาหกประเภท ER มีไวยากรณ์เข้มงวดที่สุด สิ่งที่ผ่านได้ในไดอะแกรมอื่นที่นี่ถูกปฏิเสธตรง ๆ แต่มันก็มีข้อผิดพลาดเงียบข้อหนึ่งที่คนเขียนภาษาไทยตกลงไปได้ง่ายเป็นพิเศษ ทั้งหมดสร้างซ้ำบน Mermaid 11.12.2
สิ่งที่คุณเห็น
แสดงผลได้ ป้ายกำกับถูกตัด และมีเอนทิตีที่คุณไม่ได้เขียนโผล่ขึ้นมา
ทำไม
ป้ายกำกับของความสัมพันธ์มีช่องว่างและไม่มีเครื่องหมายคำพูด ในภาษาไทยเรื่องนี้ทำให้ลำบากที่สุด แม้เราจะไม่เว้นวรรคระหว่างคำ แต่วลีบอกความสัมพันธ์ของเรามักเว้นวรรคคั่นอยู่ดี เช่น «จัดส่งไปที่» ที่เขียนแยกเป็นสองส่วน วัดแล้ว `ลูกค้า ||--o{ คำสั่งซื้อ : สั่งซื้อ สินค้า` ไม่แจ้งข้อผิดพลาดใด ๆ แต่ย่นป้ายกำกับเหลือ «สั่งซื้อ» แล้วสร้างเอนทิตีว่างชื่อ «สินค้า» ขึ้นมา สองตารางจึงถูกวาดเป็นสามกล่องโดยไม่มีอะไรเตือนคุณ
วิธีแก้
ใส่เครื่องหมายคำพูดให้ทุกป้ายกำกับที่มีช่องว่าง ถือเป็นกฎประจำไปเลยจะง่ายกว่าการมาชั่งใจทุกครั้ง
erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : สั่งซื้อ สินค้าerDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ สินค้า"สิ่งที่คุณเห็น
Parse error ที่ลงท้ายด้วย: Expecting 'COLON', 'STYLE_SEPARATOR', got 'NEWLINE'
ทำไม
ความสัมพันธ์ที่ไม่มีป้ายกำกับ ต่างจากเส้นเชื่อมของผังงาน ทวิภาคและป้ายกำกับเป็นสิ่งบังคับ ถ้าไม่มีทั้งสองอย่าง บรรทัดก็จบเร็วเกินไป
วิธีแก้
เติมทวิภาคและวลีกริยาเข้าไป และใส่เครื่องหมายคำพูดถ้ามีช่องว่าง
erDiagram
ลูกค้า ||--o{ คำสั่งซื้อerDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"สิ่งที่คุณเห็น
Parse error ที่ลงท้ายด้วย: got 'UNICODE_TEXT'
ทำไม
โทเคนพหุภาพไม่ถูกต้อง มีเพียง `||`, `o|`, `}|` และ `}o` เท่านั้นที่ถูก (รวมทั้งรูปกลับด้านของมัน) อย่างอื่นล้มหมด ส่วน `oo` เป็นการพิมพ์ผิดที่พบบ่อย เกิดจากการเดาว่าสัญกรณ์นี้สมมาตร
วิธีแก้
ใช้หนึ่งในสี่คู่นั้น `||--o{` คือหนึ่งพอดีต่อศูนย์หรือมากกว่า ซึ่งครอบคลุมคีย์นอกส่วนใหญ่
erDiagram
ลูกค้า ||--oo{ คำสั่งซื้อ : "สั่งซื้อ"erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"สิ่งที่คุณเห็น
Parse error ที่ลงท้ายด้วย: Expecting 'ATTRIBUTE_WORD', got 'BLOCK_STOP'
ทำไม
คุณลักษณะมีชื่อแต่ไม่มีชนิดข้อมูล คุณลักษณะของ ER เขียนในรูป `ชนิด ชื่อ` และชนิดไม่ใช่ของเลือกได้ ซึ่งทำให้คนที่มาจากฐานข้อมูลแบบไม่มีสคีมาแปลกใจ
วิธีแก้
ให้ชนิดข้อมูลกับทุกคุณลักษณะ ถ้าสคีมาจริงไม่มีก็ตั้งขึ้นมาเลย เช่น `string`, `int`, `json`
erDiagram
ลูกค้า {
อีเมล
}erDiagram
ลูกค้า {
string อีเมล
}สิ่งที่คุณเห็น
Parse error ที่ลงท้ายด้วย: Expecting 'NON_IDENTIFYING', 'IDENTIFYING', got 'UNICODE_TEXT'
ทำไม
เส้นระหว่างเครื่องหมายพหุภาพทั้งสองไม่ถูกต้อง มันต้องยาวสองอักขระพอดี คือ `--` สำหรับความสัมพันธ์แบบระบุตัวตน หรือ `..` สำหรับแบบไม่ระบุตัวตน ขีดกลางเดี่ยวไม่ใช่รูปย่อของ `--` แต่เป็นข้อผิดพลาดทางไวยากรณ์
วิธีแก้
เขียน `--` หรือ `..` ระหว่างคู่พหุภาพ
erDiagram
ลูกค้า ||-o{ คำสั่งซื้อ : "สั่งซื้อ"erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"สิ่งที่คุณเห็น
พหุภาพแสดงผลได้ แต่บอกข้อจำกัดกลับด้าน
ทำไม
สัญลักษณ์สองตัวที่อยู่ใกล้เอนทิตีที่สุดเป็นของเอนทิตีนั้นโดยเฉพาะ และการอ่านกลับด้านเกิดขึ้นได้ง่ายมาก `ลูกค้า ||--o{ คำสั่งซื้อ` บอกว่าลูกค้าหนึ่งคนมีคำสั่งซื้อศูนย์รายการหรือมากกว่า พลิกเป็น `ลูกค้า }o--|| คำสั่งซื้อ` แล้วคุณกำลังอ้างว่าลูกค้าทุกคนเป็นของคำสั่งซื้อเพียงหนึ่งรายการ ซึ่งไม่มีเหตุผล และมันแสดงผลออกมาโดยไม่คัดค้านแม้แต่น้อย
วิธีแก้
อ่านจากด้านในออกด้านนอก สัญลักษณ์ที่แตะกับลูกค้าอธิบายว่ามีลูกค้ากี่คน ไม่ใช่มีคำสั่งซื้อกี่รายการ
erDiagram
ลูกค้า }o--|| คำสั่งซื้อ : "สั่งซื้อ"erDiagram
ลูกค้า ||--o{ คำสั่งซื้อ : "สั่งซื้อ"หมายเหตุเรื่องการแสดงผล
วัดบน Mermaid 11.12.2 ซึ่งเป็นรุ่นที่เว็บนี้ใช้
ที่นี่อักษรไทยใช้เป็นชื่อเอนทิตีได้
ควรรู้ไว้เพราะต่างจากผังงานและไดอะแกรมคลาส ชื่อเอนทิตีก็เป็นตัวระบุเช่นกัน แต่อักษรไทยกลับผ่านที่นี่ ทดสอบแล้วว่า `ลูกค้า ||--o{ คำสั่งซื้อ` แสดงผลได้ และตัวระบุที่ออกมาคือ `entity-ลูกค้า` กับ `entity-คำสั่งซื้อ` ชื่อคอลัมน์ก็เป็นภาษาไทยได้เช่นกัน ข้อห้ามมีเพียงช่องว่าง ซึ่งภาษาไทยเลี่ยงได้เองอยู่แล้วเพราะเราเขียนติดกัน
ในภาษาไทย ป้ายกำกับความสัมพันธ์ยังต้องใส่เครื่องหมายคำพูดอยู่ดี
นี่คือจุดที่ต้องระวัง เพราะแม้ภาษาไทยจะไม่เว้นวรรคระหว่างคำ แต่เราเว้นวรรคคั่นวลีเป็นปกติ และป้ายกำกับความสัมพันธ์มักยาวพอที่จะมีการเว้นวรรคแบบนั้น เมื่อไม่มีเครื่องหมายคำพูด ป้ายกำกับจะถูกตัดที่ช่องว่างแรกและส่วนที่เหลือกลายเป็นเอนทิตีผี กฎที่ใช้ได้จริงคือใส่เครื่องหมายคำพูดให้ป้ายกำกับเสมอแล้วเลิกคิดเรื่องนี้ไป
การจัดวางถูกกำหนดโดยความสัมพันธ์ ไม่ใช่จำนวนเอนทิตี
ห่วงโซ่เอนทิตีที่ต่อกันไปเรื่อย ๆ จะถูกวาดเป็นเสาสูง สี่สิบเอนทิตีให้ viewBox ราว 116×7315 เทียบกับ 116×470 เมื่อมีสามตัว แต่สี่สิบเอนทิตีชุดเดียวกันที่ต่อเข้ากับตารางกลางเพียงตารางเดียว จะให้ภาพที่กว้างกว่าและเตี้ยกว่ามาก นี่คือไดอะแกรมประเภทเดียวในเว็บนี้ที่รูปร่างของข้อมูลเปลี่ยนรูปร่างของภาพมากกว่าเปลี่ยนขนาดของมัน สคีมาที่ใส่ไม่ลงจึงมักแก้ได้ด้วยการเปลี่ยนว่าจะวาดความสัมพันธ์ไหน มากกว่าจะวาดกี่เส้น
ไวยากรณ์เข้มงวดที่สุดในหกประเภท
ป้ายกำกับความสัมพันธ์เป็นสิ่งบังคับ ชนิดข้อมูลของคุณลักษณะก็เช่นกัน และโทเคนพหุภาพเป็นชุดปิด เทียบกับแกนต์ที่แทบทุกอย่างแสดงผลได้และข้อผิดพลาดเงียบสนิท ER ล้มเร็วและล้มเสียงดัง นี่เป็นข้อดี เพราะถ้าไดอะแกรม ER แสดงผลออกมาได้ ก็มีโอกาสสูงพอสมควรว่ามันคือไดอะแกรมที่คุณตั้งใจ ยกเว้นกรณีป้ายกำกับที่ไม่มีเครื่องหมายคำพูดซึ่งเป็นข้อยกเว้นชัดเจน
ป้ายกำกับเป็น HTML การส่งออก PNG จึงวาดใหม่
ตารางคุณลักษณะของเอนทิตีถูกวาดภายใน `<foreignObject>` ในไฟล์ SVG เบราว์เซอร์จึงแปลงมันเป็นภาพแรสเตอร์บนแคนวาสโดยตรงไม่ได้ การส่งออก PNG ของเว็บนี้เคยคืนไฟล์ SVG อย่างเงียบ ๆ ตอนนี้มันวาดไดอะแกรมใหม่ด้วยป้ายกำกับข้อความ SVG ล้วนก่อน แล้วให้ไฟล์ PNG ที่ถูกต้องและเต็มขนาด โดยการจัดวางตัวอักษรต่างไปเพียงเล็กน้อยจนแทบสังเกตไม่เห็น
เมื่อใดควรใช้ไดอะแกรมประเภทอื่น
ถ้าคุณต้องการการสืบทอด อินเทอร์เฟซ หรือเมท็อด นี่คือไดอะแกรมที่ผิด เพราะ ER ไม่มีแนวคิดเหล่านั้นเลย ให้ใช้ไดอะแกรมคลาสและยอมรับว่ามันจำลองโค้ดของคุณ ไม่ใช่ตารางของคุณ
ถ้าสคีมาใหญ่ ไดอะแกรม ER ของทั้งระบบจะกลายเป็นโปสเตอร์ติดผนังที่ไม่มีใครอ่าน ให้วาดห้าตารางที่เกี่ยวกับสิ่งที่คุณกำลังอธิบายอยู่ตอนนั้น แล้วปล่อยที่เหลือไว้นอกกรอบ ไดอะแกรมคือข้อโต้แย้ง ไม่ใช่บัญชีรายการ
และถ้าคำถามที่แท้จริงคือข้อมูลไหลระหว่างระบบอย่างไร ไม่ใช่ข้อมูลถูกเก็บอย่างไร สิ่งที่ตอบได้คือผังงานที่มีกลุ่มย่อยหนึ่งกลุ่มต่อหนึ่งระบบ ไม่ใช่ไดอะแกรม ER
ไดอะแกรมประเภทอื่น
เขียนโดย Dominik Malsch · อัปเดตล่าสุด: