~/VibeHandbook
PDF ฟรี

บท 14 · 03

พื้นฐานการออกแบบสคีมา

สคีมา (schema) คือพิมพ์เขียวของข้อมูลของคุณ ว่ามีตารางอะไรบ้าง แต่ละตารางมีคอลัมน์อะไร และตารางเหล่านั้นสัมพันธ์กันอย่างไร การออกแบบสคีมาที่ดีส่วนใหญ่เป็นเรื่องของสามัญสำนึกบวกกับนิสัยไม่กี่อย่าง

  • หนึ่งตารางต่อ "สิ่งของ" หนึ่งชนิด ผู้ใช้ โพสต์ คำสั่งซื้อ — แต่ละอย่างมีตารางของตัวเอง
  • ทุกแถวต้องมี ID ที่ไม่ซ้ำกัน (primary key)
  • เชื่อมตารางด้วย foreign key ไม่ใช่ด้วยการคัดลอกข้อมูลไปมา
  • เลือกชนิดข้อมูลที่ตรงกับความเป็นจริง เงินคือ decimal ไม่ใช่ float วันที่คือ timestamp ไม่ใช่ข้อความ
  • อย่าเก็บข้อมูลซ้ำซ้อน ถ้าอีเมลของผู้ใช้อยู่ในห้าตาราง สุดท้ายคุณจะมีอีเมลห้าอันที่ไม่ตรงกัน

นี่คือสคีมาง่าย ๆ สำหรับบล็อก แบบที่ AI จะสร้างให้คุณได้

CREATE TABLE users (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email       TEXT NOT NULL UNIQUE,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE posts (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    author_id   UUID NOT NULL REFERENCES users(id),
    title       TEXT NOT NULL,
    body        TEXT NOT NULL,
    published   BOOLEAN NOT NULL DEFAULT false,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_posts_author ON posts(author_id);

บรรทัด author_id ... REFERENCES users(id) นั้นคือ foreign key มันเชื่อมโยงแต่ละโพสต์กลับไปยังผู้ใช้จริงเพียงคนเดียว ดังนั้นฐานข้อมูลเองจะปฏิเสธการเก็บโพสต์ที่ไม่มีเจ้าของที่ถูกต้อง

   users                          posts
   ┌─────────────┐                ┌─────────────┐
   │ id  (PK) ◀──┼────────────────┤ author_id   │  (FK → users.id)
   │ email       │   one user      │ id  (PK)    │
   │ created_at  │   has many      │ title       │
   └─────────────┘   posts         │ body        │
                                   │ published   │
        1  ────────────────────▶  *└─────────────┘
       (one)                    (many)

สังเกต REFERENCES (foreign key ที่ผูกโพสต์เข้ากับผู้ใช้จริง) และเงื่อนไข NOT NULL กับ UNIQUE สิ่งเหล่านี้คือรั้วกั้นที่ฐานข้อมูลบังคับใช้ให้คุณ เพื่อไม่ให้ข้อมูลเสียแอบเล็ดลอดเข้ามาได้ แม้ว่าโค้ดของคุณจะมีบั๊กก็ตาม

เงื่อนไขที่ควรเพิ่มอย่างตั้งใจคือสิ่งที่จะเกิดขึ้นเมื่อฝั่ง "พ่อแม่" หายไป โดยค่าเริ่มต้น การลบผู้ใช้ที่ยังมีโพสต์อ้างอิงถึงอยู่จะล้มเหลว — ซึ่งมักจะเป็นสิ่งที่คุณต้องการอยู่แล้ว แต่คุณสามารถกำหนดให้ชัดเจนได้ REFERENCES users(id) ON DELETE CASCADE จะลบโพสต์ไปด้วย ในขณะที่ ON DELETE RESTRICT จะบล็อกการลบไว้ การเลือกด้วยความตั้งใจดีกว่าการมาค้นพบค่าเริ่มต้นแบบเจ็บ ๆ ในระบบจริง สัญชาตญาณแบบ "ให้ฐานข้อมูลปกป้องคุณ" แบบเดียวกันนี้ใช้ได้กับเงื่อนไข CHECK (CHECK (price >= 0)) — มันปฏิเสธข้อมูลที่ไม่สมเหตุสมผลตั้งแต่ต้นทาง แทนที่จะไว้ใจให้ทุกเส้นทางของโค้ดตรวจสอบเอง

อยากได้แบบออฟไลน์?

ดาวน์โหลดหนังสือทั้งเล่มเป็น PDF หรือ EPUB — ฟรี