บทที่ 2: การออกแบบ Prisma Schema
ศึกษาการออกแบบฐานข้อมูลด้วย Prisma Schema Language แบบมืออาชีพ! 🏗️
🧠 ทำไมต้องออกแบบ Schema ให้ดี?
• 🏗️ Foundation ที่แข็งแรง: Schema ที่ดีเป็นรากฐานของแอปพลิเคชันที่ยืนยาว
• ⚡ Performance: Index และ relation ที่ถูกต้องทำให้ query เร็วขึ้น
• 🔒 Data Integrity: Constraints และ validation ป้องกันข้อมูลผิดพลาด
• 🚀 Scalability: Schema ที่ยืดหยุ่นรองรับการเติบโตในอนาคต
📊 ประเภทของ Fields ใน Prisma
String Types
String
ข้อความทั่วไป
name String
String?
ข้อความที่อาจเป็น null
nickname String?
String @unique
ข้อความที่ไม่ซ้ำ
email String @unique
Number Types
Int
จำนวนเต็ม
age Int
Float
จำนวนทศนิยม
price Float
BigInt
จำนวนเต็มขนาดใหญ่
views BigInt
Date & Boolean
DateTime
วันที่และเวลา
createdAt DateTime @default(now())
Boolean
true หรือ false
isPublished Boolean @default(false)
Special Types
Json
ข้อมูล JSON
metadata Json?
Bytes
ข้อมูล binary
avatar Bytes?
🛠️ ขั้นตอนการออกแบบ Schema
วางแผนและวิเคราะห์ข้อมูล (Data Planning)
วิเคราะห์ business requirements และออกแบบโครงสร้างข้อมูลก่อนเขียนโค้ด - ขั้นตอนสำคัญที่จะกำหนดความสำเร็จของโปรเจค
📋 ขั้นตอนย่อย:
ระบุ entities หลัก (Users, Posts, Categories)
กำหนด attributes ของแต่ละ entity
วิเคราะห์ relationships ระหว่าง entities
วางแผน data validation และ constraints
💻 ตัวอย่างโค้ด:
// ตัวอย่างการวางแผน - ระบบบล็อก /* Business Requirements: - ผู้ใช้สามารถสร้างบัญชีและล็อกอิน - ผู้ใช้เขียนโพสต์ได้หลายโพสต์ - โพสต์สามารถมีหลายแท็ก - ผู้ใช้คอมเมนต์โพสต์ได้ - ผู้ใช้มีโปรไฟล์ส่วนตัว Entity Analysis: 1. User (ผู้ใช้) - id, email, name, password - has one Profile - has many Posts - has many Comments 2. Profile (โปรไฟล์) - id, bio, avatar, userId - belongs to one User 3. Post (โพสต์) - id, title, content, authorId - belongs to one User (author) - has many Comments - has many Tags (many-to-many) 4. Comment (คอมเมนต์) - id, content, postId, authorId - belongs to one Post - belongs to one User (author) 5. Tag (แท็ก) - id, name, color - belongs to many Posts */
💡 เทคนิคและคำแนะนำ:
สร้าง Database Schema (Schema Definition)
กำหนด Relations และ Constraints
Generate Client และ Testing
Optimization และ Advanced Features
ขั้นตอนสุดท้าย🔗 ประเภทของ Relations
One-to-Many (1:M)
ผู้ใช้หนึ่งคนมีหลายโพสต์
💻 ตัวอย่างโค้ด:
model User {
id Int @id @default(autoincrement())
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
authorId Int
author User @relation(fields: [authorId], references: [id])
}Many-to-Many (M:M)
โพสต์หนึ่งโพสต์มีหลาย tags, tag หนึ่งตัวอยู่ในหลายโพสต์
💻 ตัวอย่างโค้ด:
model Post {
id Int @id @default(autoincrement())
title String
tags Tag[]
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
posts Post[]
}One-to-One (1:1)
ผู้ใช้หนึ่งคนมีโปรไฟล์เพียงหนึ่งโปรไฟล์
💻 ตัวอย่างโค้ด:
model User {
id Int @id @default(autoincrement())
email String @unique
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
bio String?
userId Int @unique
user User @relation(fields: [userId], references: [id])
}⭐ Best Practices
📝 การตั้งชื่อ Models และ Fields
ใช้ PascalCase สำหรับ Models และ camelCase สำหรับ fields
ตัวอย่าง:
🔑 Primary Keys และ IDs
ใช้ @id และ @default(autoincrement()) สำหรับ primary key
ตัวอย่าง:
📅 Timestamps
เพิ่ม createdAt และ updatedAt ให้ทุก Model
ตัวอย่าง:
🔍 Indexes และ Performance
เพิ่ม index สำหรับ fields ที่ใช้ query บ่อย
ตัวอย่าง:
💻 ตัวอย่าง Schema ตามสถานการณ์จริง
Schema สำหรับระบบบล็อก
Schema ที่ครอบคลุม Users, Posts, Comments, Tags และ Profiles พร้อม relations ทั้งหมด
// prisma/schema.prisma - Schema สำหรับระบบบล็อกง่ายๆ
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql" // หรือ mysql, sqlite
url = env("DATABASE_URL")
}
// Model สำหรับผู้ใช้
model User {
id Int @id @default(autoincrement())
email String @unique
name String
role Role @default(USER)
profile Profile?
posts Post[]
comments Comment[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users") // ชื่อ table ในฐานข้อมูล
}
// Model สำหรับโปรไฟล์ผู้ใช้
model Profile {
id Int @id @default(autoincrement())
bio String?
avatar String?
userId Int @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("profiles")
}
// Model สำหรับโพสต์
model Post {
id Int @id @default(autoincrement())
title String
content String?
slug String @unique
published Boolean @default(false)
publishedAt DateTime?
authorId Int
author User @relation(fields: [authorId], references: [id])
comments Comment[]
tags Tag[]
views Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("posts")
@@index([authorId])
@@index([published])
}
// Model สำหรับคอมเมนต์
model Comment {
id Int @id @default(autoincrement())
content String
postId Int
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
authorId Int
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
@@map("comments")
@@index([postId])
@@index([authorId])
}
// Model สำหรับแท็ก
model Tag {
id Int @id @default(autoincrement())
name String @unique
color String @default("#3B82F6")
posts Post[]
@@map("tags")
}
// Enum สำหรับบทบาทผู้ใช้
enum Role {
USER
ADMIN
MODERATOR
}📋 อ้างอิงเร็ว: Attributes ที่ใช้บ่อย
| Attribute | การใช้งาน | ตัวอย่าง |
|---|---|---|
| @id | กำหนด Primary Key | id Int @id @default(autoincrement()) |
| @unique | กำหนดให้ค่าไม่ซ้ำ | email String @unique |
| @default() | กำหนดค่าเริ่มต้น | createdAt DateTime @default(now()) |
| @relation | กำหนด Foreign Key | author User @relation(fields: [authorId], references: [id]) |
| @@index | สร้าง Database Index | @@index([email, status]) |
| @@map | กำหนดชื่อ Table | @@map("users") |