dbdiff

dbdiffv0.2.2

数据库结构比较 CLI

比较数据库结构,生成迁移 SQL。

比较两个数据库,或将数据库与 SQL 结构文件比较。审查表、列和索引的变更,也可在 CI 中检测结构差异。

Rust · MIT · 最近更新

产品示例dbdiff
$ dbdiff postgres://prod/app --schema schema.sql

~ orders
  + paid_at       timestamptz
  + idx_paid_at   INDEX
  - payment_date  varchar(32)

$ dbdiff … --ci
# exit 0: match · exit 1: drift

dbdiff

审阅结构变更

数据库与结构文件

使用数据库连接字符串或仓库中的 SQL 文件作为比较来源。

可供审查的迁移 SQL

查看表、列和索引的差异,在执行前审查生成的 SQL 与锁操作警告。

退出码与 JSON

CI 模式通过退出码报告漂移,JSON 输出方便接入自己的自动化流程。

数据库结构比较 CLI

从对比到审阅

  1. 选择两个来源

    指定需要比较的环境或 SQL 结构文件。

  2. 审查迁移

    保存结果,检查破坏性或锁定操作,再按既有部署流程执行。

01 / 安装

安装

cargo install dbdiff

02 / README

仓库文档

比较数据库结构或数据库与 SQL 文件的差异,生成迁移 SQL,并在 CI 中检测结构变更。

配置说明、使用示例和 API 参考。

README ↗
阅读文档

以下为仓库的原始文档,未作翻译;上方的示例与入门说明已本地化。

banner

CI Latest release Rust 1.88 or newer MIT license

Compare database schemas. See what changed. Generate SQL you can review.
PostgreSQL · MySQL / MariaDB · SQLite · SQL files · JSON snapshots

Try the demo · Install · CLI guide · Website · Contribute

See it in action

Animated terminal demo of real schema differences and CI exit codes

Static preview. Excerpts from the offline demo below, captured from the actual CLI. The full run also verifies JSON output, migration files, rollback SQL, and preview behavior.

  • Find drift before a deploy: compare current and desired schemas from files or live databases.
  • Review the migration: see generated SQL, destructive-operation warnings, and a rollback plan.
  • Gate your pipeline: machine-readable reports and explicit exit codes for drift and blocking operations.
  • Work offline: compare SQL files or export a JSON snapshot for later review.

dbdiff generates migration SQL; it does not execute that SQL against your database.

Try the demo

No database server, credentials, or Docker required. From a checkout:

git clone https://github.com/rekurt/dbdiff.git
cd dbdiff
cargo build --locked
python3 examples/demo/run.py --bin target/debug/dbdiff

Requires Rust 1.88+ and Python 3.9+. On Windows, use python and target/debug/dbdiff.exe.

The demo replaces a free-form payment date with a timestamp, adds an index, and introduces soft deletion. It verifies four changes and the CI exit codes 1 → 3 → 0, then saves the transcript, JSON report, forward migration, and rollback under target/demo/.

Or, with dbdiff installed, run the comparison directly:

dbdiff examples/demo/before.sql examples/demo/after.sql
Expected diff (excerpt)
~ table: orders
  + column  paid_at              timestamp
  - column  payment_date         text
  + index   idx_orders_paid_at ON orders(paid_at)

~ table: users
  + column  deleted_at           timestamp

The full output includes unchanged columns, migration SQL, warnings, a summary, and next steps.

See the demo walkthrough for individual commands and how to regenerate the animation.

Install

Release binaries

Download the archive for your platform from Releases, extract it, and put dbdiff (or dbdiff.exe) on your PATH.

Platform Archive target
Linux x86_64 x86_64-unknown-linux-gnu or x86_64-unknown-linux-musl
Linux ARM64 aarch64-unknown-linux-gnu
macOS Intel x86_64-apple-darwin
macOS Apple Silicon aarch64-apple-darwin
Windows x86_64 x86_64-pc-windows-msvc
Build from source
cargo install --git https://github.com/rekurt/dbdiff --locked

All three database backends are enabled by default. For a smaller build:

cargo install --git https://github.com/rekurt/dbdiff --locked \
  --no-default-features --features postgres,sqlite

Source builds require Rust 1.88+ and the platform's build tools; PostgreSQL/MySQL builds may also require TLS development libraries. See CONTRIBUTING.md.

Everyday usage

Compare current → desired

The first source is the current schema. The second source is the desired schema. Forward SQL changes the first to match the second.

# Two live PostgreSQL databases
dbdiff "$CURRENT_DSN" "$DESIRED_DSN"

# Live database versus a complete desired schema file
dbdiff "$CURRENT_DSN" --schema schema.sql

# MySQL / MariaDB (both variables contain mysql:// or mariadb:// DSNs)
dbdiff "$MYSQL_CURRENT_DSN" "$MYSQL_DESIRED_DSN"

# SQLite database versus a schema file
dbdiff app.db --schema schema.sql

# Two SQL files, fully offline
dbdiff current.sql desired.sql

A schema file should describe the complete desired structure with CREATE statements, rather than an incremental ALTER migration. Compare like-for-like database backends; a SQL file can be used on either side. SQL-file-only comparisons generate PostgreSQL-style migration SQL.

Preview, then save
# Preview only: this does not create migration.sql
dbdiff current.sql desired.sql --out migration.sql

# Explicitly save the forward migration
dbdiff current.sql desired.sql --emit migration.sql

# Equivalent write command
dbdiff current.sql desired.sql --out migration.sql --write

# Save a separate rollback plan
dbdiff current.sql desired.sql --direction down --emit rollback.sql

Review generated SQL before applying it. A rollback restores schema definitions; it cannot recover data lost through a dropped column or table.

Reports and offline snapshots
dbdiff current.sql desired.sql --format json > drift.json
dbdiff current.sql desired.sql --format yaml > drift.yml
dbdiff current.sql desired.sql --format sql > migration.sql

# Capture a database schema, then compare the snapshot offline
dbdiff snapshot "$CURRENT_DSN" --out current.json
dbdiff current.json desired.json

For connectivity checks, table listing, completions, PostgreSQL concurrent indexes, and configuration options, see the CLI guide or dbdiff --help.

Use it in CI

dbdiff current.sql desired.sql --ci --format json > drift-report.json
Exit code Meaning
0 No schema drift (or successful comparison without --ci)
1 Drift detected with --ci
2 Invalid arguments, load/connection failure, or another error
3 Blocking operations detected with --ci --fail-on-blocking

Use --format ci for a compact text report. --format json and --format yaml provide structured reports. Add --fail-on-blocking to distinguish changes classified as blocking by dbdiff.

A file-based GitHub Actions example, requiring no database secrets:

name: Schema drift
on: [pull_request]
permissions:
  contents: read
jobs:
  schema:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - name: Install dbdiff
        run: cargo install --git https://github.com/rekurt/dbdiff --tag v0.2.2 --locked
      - name: Compare schemas
        run: dbdiff current.sql desired.sql --ci --format json > drift-report.json
      - name: Upload report
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: schema-drift-report
          path: drift-report.json

Replace current.sql and desired.sql with your project's schemas. For live comparisons, supply DSNs through CI secrets. When running under GitHub Actions, CI mode also emits annotations.

Configuration

Run dbdiff init to create .dbdiff.yml, or use --config path/to/config.yml:

ignore:
  tables:
    - _migrations
    - schema_version
  columns:
    - "*.created_at"
    - "sessions.*"

protected:
  tables:
    - payments
  columns:
    - "*.id"

output:
  format: pretty
  color: true

Ignored objects are filtered from both sources. Protected rules reject drops of listed tables or matching columns. See configuration details.

Capabilities and limits

Area Coverage
Tables Add, remove; experimental rename detection
Columns Add, remove, type/default/nullability changes; experimental renames
Indexes Add, remove, changed definitions
Constraints Primary keys, unique, foreign keys, checks
PostgreSQL objects Views, enums, sequences when available from live schemas or snapshots
Migration plans Forward, rollback, or both; warnings and optional explanations
  • PostgreSQL, MySQL/MariaDB, and SQLite loaders are included by default. Backend-specific DDL has different capabilities; review each generated plan.
  • SQL files are parsed as schema definitions. Views, enums, and sequences are excluded from comparisons involving .sql files; use JSON snapshots to preserve those objects.
  • SQLite cannot perform every ALTER operation directly; generated plans can include warnings or unsupported-operation comments.
  • Rename detection is experimental and opt-in (--detect-renames).
  • Blocking classifications are review aids, not a guarantee about execution time, lock duration, or data preservation.

Development and community

cargo test --locked
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
python3 examples/demo/run.py --bin target/debug/dbdiff

Contributing · Architecture · Changelog · Report a bug · Request a feature · Security policy · Code of conduct

MIT © Nikita. See LICENSE.

dbdiff

比较你的数据库结构

安装 dbdiff →