agentsclimarketplace

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.

Install
npx -y skills add ComeOnOliver/skillshub --skill database-migration

Assembled 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에 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ 단계 μΆ”κ°€
  • λ‘€λ°± 슀크립트 μ€€λΉ„
  • ν”„λ‘œλ•μ…˜ λ°±μ—… μžλ™ν™”

References

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.