Membuat tabel pertama dengan Drizzle ORM: tipe data PostgreSQL (serial, text, integer, boolean, timestamp, json, uuid, enum), tipe data MySQL & SQLite, column modifiers (notNull, default, unique, primaryKey, references, map), dan foreign key definition.

Setelah di episode 3 kita menyiapkan Drizzle ORM — install, konfigurasi, dan koneksi database — pada episode ini kita masuk ke schema definition: bagaimana mendefinisikan tabel, kolom, dan relasi di Drizzle ORM.
Schema adalah source of truth — setiap tabel, kolom, dan relasi didefinisikan di sini. Schema yang baik menghasilkan type inference yang akurat dan query yang mudah ditulis.
import { pgTable, serial, text, integer, timestamp, boolean } from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
age: integer('age'),
isActive: boolean('is_active').default(true),
createdAt: timestamp('created_at').defaultNow(),
})
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
authorId: integer('author_id').references(() => users.id),
viewCount: integer('view_count').default(0),
publishedAt: timestamp('published_at'),
})| Tipe | Fungsi | Contoh |
|---|---|---|
serial | Auto-increment integer | id primary key |
bigint | Integer 64-bit | ID besar |
integer | Integer 32-bit | age, viewCount |
real / doublePrecision | Floating point | Koordinat |
numeric | Exact decimal | Harga, uang |
text | Text panjang | name, content |
varchar | Text dengan batas | |
boolean | True/false | isActive |
timestamp | Tanggal & waktu | createdAt |
date | Tanggal saja | Birthday |
json / jsonb | JSON data | Metadata |
uuid | UUID | Identifier unik |
enum | Enumerasi | Role, status |
import { mysqlTable, int, varchar, text, datetime, decimal } from 'drizzle-orm/mysql-core'
export const users = mysqlTable('users', {
id: int('id').primaryKey().autoincrement(),
name: varchar('name', { length: 255 }).notNull(),
email: varchar('email', { length: 255 }).notNull(),
age: int('age'),
createdAt: datetime('created_at'),
})import { sqliteTable, integer, text, real } from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
email: text('email').notNull(),
age: integer('age'),
isActive: integer('is_active', { mode: 'boolean' }).default(true),
})text('name').notNull() // Tidak boleh null
integer('age').default(0) // Default value
text('email').unique() // Unique constraint
serial('id').primaryKey() // Primary keyimport { pgTable, integer, text } from 'drizzle-orm/pg-core'
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
authorId: integer('author_id')
.references(() => users.id, { onDelete: 'cascade' }),
})onDelete: 'cascade' berarti jika user dihapus, semua posts-nya juga dihapus.
export const users = pgTable('users', {
id: serial('id').primaryKey(),
fullName: text('full_name').notNull(), // Column di DB: full_name
}).map('full_name') atau cukup pass nama kolom di function: text('full_name').
Tip
Selalu gunakan defaultNow() untuk timestamp created_at dan pertimbangkan defaultNow() untuk updated_at juga. Ini memastikan setiap baris punya timestamp otomatis tanpa harus set manual di setiap insert.
Pada episode 4 ini, kalian telah memahami Schema Definition:
pgTable() / mysqlTable() / sqliteTable() untuk membuat tabel..notNull(), .default(), .unique(), .primaryKey()..references(() => table.id) dengan opsi onDelete.Di episode 5 selanjutnya kita akan mempelajari Insert, Update, Delete & Select Dasar — operasi CRUD pertama dengan Drizzle ORM. Sampai jumpa di episode 5!