Database migration
Skill ComeOnOliver/skillshub/skills/aiskillstore/marketplace/doyajin174/database-migration
π§ The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.
npx -y skills add ComeOnOliver/skillshub --skill database-migrationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Manage database schema changes with version control. Use when modifying DB schema, adding tables/columns, or setting up new projects. Covers Prisma, Drizzle, and migration best practices.
The file declares its own license as MIT. That is the authorβs claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.3 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it
Database Migration
λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§ λ³κ²½μ λ²μ κ΄λ¦¬νλ μ€ν¬μ λλ€.
Core Principle
"DB μ€ν€λ§λ μ½λμ²λΌ λ²μ κ΄λ¦¬νλ€." "μλμΌλ‘ ALTER TABLE μΉλ μκ°, νμ μ΄ λ§κ°μ§λ€."
Rules
| κ·μΉ | μν | μ€λͺ |
|---|---|---|
| λ§μ΄κ·Έλ μ΄μ νμΌ μμ± | π΄ νμ | μλ SQL μ€ν κΈμ§ |
| λ‘€λ°± κ°λ₯ | π΄ νμ | down migration νμ |
| μμ°¨ μ€ν | π΄ νμ | λ§μ΄κ·Έλ μ΄μ μμ 보μ₯ |
| νλ‘λμ λ°±μ | π΄ νμ | λ§μ΄κ·Έλ μ΄μ μ λ°±μ |
Prisma (κΆμ₯)
μ΄κΈ° μ€μ
# Prisma μ€μΉ
npm install prisma @prisma/client
# μ΄κΈ°ν
npx prisma init
# .envμ DATABASE_URL μ€μ
# DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
μ€ν€λ§ μ μ
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
λ§μ΄κ·Έλ μ΄μ μν¬νλ‘μ°
# 1. μ€ν€λ§ λ³κ²½ ν λ§μ΄κ·Έλ μ΄μ
μμ±
npx prisma migrate dev --name add_user_table
# 2. λ§μ΄κ·Έλ μ΄μ
νμΌ νμΈ
ls prisma/migrations/
# 3. νλ‘λμ
λ°°ν¬
npx prisma migrate deploy
# 4. ν΄λΌμ΄μΈνΈ μ¬μμ±
npx prisma generate
λ§μ΄κ·Έλ μ΄μ νμΌ κ΅¬μ‘°
prisma/
βββ schema.prisma
βββ migrations/
βββ 20240101000000_init/
β βββ migration.sql
βββ 20240102000000_add_user_table/
β βββ migration.sql
βββ migration_lock.toml
λ§μ΄κ·Έλ μ΄μ λͺ λ Ήμ΄
# κ°λ°: λ§μ΄κ·Έλ μ΄μ
μμ± + μ μ©
npx prisma migrate dev --name <migration_name>
# νλ‘λμ
: λ§μ΄κ·Έλ μ΄μ
λ§ μ μ©
npx prisma migrate deploy
# μν νμΈ
npx prisma migrate status
# 리μ
(β οΈ κ°λ°μ©λ§)
npx prisma migrate reset
Drizzle ORM
μ΄κΈ° μ€μ
# Drizzle μ€μΉ
npm install drizzle-orm postgres
npm install -D drizzle-kit
μ€ν€λ§ μ μ
// src/db/schema.ts
import { pgTable, serial, text, timestamp, boolean, integer } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: text('email').notNull().unique(),
name: text('name'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
published: boolean('published').default(false),
authorId: integer('author_id').references(() => users.id),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
drizzle.config.ts
import type { Config } from 'drizzle-kit';
export default {
schema: './src/db/schema.ts',
out: './drizzle',
driver: 'pg',
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
} satisfies Config;
λ§μ΄κ·Έλ μ΄μ λͺ λ Ήμ΄
# λ§μ΄κ·Έλ μ΄μ
μμ±
npx drizzle-kit generate:pg
# λ§μ΄κ·Έλ μ΄μ
μ μ©
npx drizzle-kit push:pg
# μ€ν€λ§ μκ°ν
npx drizzle-kit studio
λ§μ΄κ·Έλ μ΄μ Best Practices
1. μμ λ¨μλ‘ λ§μ΄κ·Έλ μ΄μ
-- β BAD: ν λ²μ λ§μ λ³κ²½
-- migration: big_refactor
ALTER TABLE users ADD COLUMN age INT;
ALTER TABLE users ADD COLUMN address TEXT;
ALTER TABLE users DROP COLUMN old_field;
CREATE TABLE new_table (...);
DROP TABLE old_table;
-- β
GOOD: μμ λ¨μλ‘ λΆλ¦¬
-- migration: add_user_age
ALTER TABLE users ADD COLUMN age INT;
-- migration: add_user_address
ALTER TABLE users ADD COLUMN address TEXT;
2. μμ ν μ»¬λΌ μΆκ°
-- β BAD: NOT NULL without default (κΈ°μ‘΄ λ°μ΄ν° λ¬Έμ )
ALTER TABLE users ADD COLUMN status TEXT NOT NULL;
-- β
GOOD: default κ° ν¬ν¨
ALTER TABLE users ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
-- λλ nullableλ‘ μΆκ° ν λμ€μ λ§μ΄κ·Έλ μ΄μ
ALTER TABLE users ADD COLUMN status TEXT;
UPDATE users SET status = 'active' WHERE status IS NULL;
ALTER TABLE users ALTER COLUMN status SET NOT NULL;
3. μμ ν μ»¬λΌ μμ
-- β BAD: λ°λ‘ μμ
ALTER TABLE users DROP COLUMN old_field;
-- β
GOOD: λ¨κ³μ μμ
-- Step 1: μ½λμμ μ»¬λΌ μ¬μ© μ κ±°
-- Step 2: λ°°ν¬ ν μμ ν νμΈ
-- Step 3: λ§μ΄κ·Έλ μ΄μ
μΌλ‘ μ»¬λΌ μμ
4. μΈλ±μ€ μΆκ°
-- β BAD: ν° ν
μ΄λΈμ λκΈ° μΈλ±μ€ μμ± (λ½ λ°μ)
CREATE INDEX idx_users_email ON users(email);
-- β
GOOD: CONCURRENTLY μ¬μ© (PostgreSQL)
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
λ‘€λ°± μ λ΅
Prisma λ‘€λ°±
# λ§μ§λ§ λ§μ΄κ·Έλ μ΄μ
λ‘€λ°±
npx prisma migrate resolve --rolled-back <migration_name>
# λλ νΉμ μμ μΌλ‘ 볡ꡬ
npx prisma migrate reset # β οΈ κ°λ°μ©λ§!
μλ λ‘€λ°± μ€ν¬λ¦½νΈ
-- migrations/20240102_add_status/down.sql
ALTER TABLE users DROP COLUMN status;
CI/CD ν΅ν©
GitHub Actions
# .github/workflows/migrate.yml
name: Database Migration
on:
push:
branches: [main]
paths:
- 'prisma/**'
jobs:
migrate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
λ§μ΄κ·Έλ μ΄μ κ²μ¦
# PRμμ λ§μ΄κ·Έλ μ΄μ
μ ν¨μ± κ²μ¬
jobs:
validate-migration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Run migrations on test DB
run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://postgres:test@localhost:5432/test
νλ‘λμ 체ν¬λ¦¬μ€νΈ
λ§μ΄κ·Έλ μ΄μ μ
- λ°μ΄ν°λ² μ΄μ€ λ°±μ μλ£
- λ§μ΄κ·Έλ μ΄μ SQL 리뷰 μλ£
- ν μ€νΈ νκ²½μμ κ²μ¦ μλ£
- λ‘€λ°± κ³ν μ€λΉ
- μ μ§λ³΄μ μλ¦Ό (νμμ)
λ§μ΄κ·Έλ μ΄μ μ€
- λͺ¨λν°λ§ λμ보λ νμΈ
- μλ¬ λ‘κ·Έ λͺ¨λν°λ§
- λ½ νμμμ νμΈ
λ§μ΄κ·Έλ μ΄μ ν
- μ ν리μΌμ΄μ μ μ λμ νμΈ
- λ°μ΄ν° λ¬΄κ²°μ± νμΈ
- μ±λ₯ μ ν μ¬λΆ νμΈ
Workflow
κ°λ° μ
1. μ€ν€λ§ νμΌ μμ (schema.prisma)
2. npx prisma migrate dev --name <description>
3. μμ±λ SQL νμΈ
4. Git μ»€λ° (μ€ν€λ§ + λ§μ΄κ·Έλ μ΄μ
νμΌ)
λ°°ν¬ μ
1. PR λ¨Έμ§
2. CIμμ npx prisma migrate deploy μ€ν
3. νλ‘λμ
νμΈ
4. (λ¬Έμ μ) λ‘€λ°± μ€ν
Checklist
- λ§μ΄κ·Έλ μ΄μ λꡬ μ€μ (Prisma/Drizzle)
- λ§μ΄κ·Έλ μ΄μ νμΌ Git μΆμ
- CI/CDμ λ§μ΄κ·Έλ μ΄μ λ¨κ³ μΆκ°
- λ‘€λ°± μ€ν¬λ¦½νΈ μ€λΉ
- νλ‘λμ λ°±μ μλν