Alembic は、SQLAlchemy 用のマイグレーション(データベースの構造の変更を、履歴つきのスクリプトで管理する)ツールです。 モデル(Python のクラス)を変えたら、alembic revision --autogenerate で差分のスクリプトを作り、alembic upgrade head でデータベースに当てます。

pip install alembic
alembic init migrations                            # 1. 初期化
# migrations/env.py に target_metadata を設定      # 2. モデルとつなぐ
alembic revision --autogenerate -m "create users"  # 3. 差分からスクリプトを作る
alembic upgrade head                               # 4. 最新まで当てる
alembic downgrade -1                               # 5. 1つ戻す

autogenerate は、すべての変更を見つけるわけではありません。 手元で試した結果です。

モデルの変更 autogenerate の結果 対応
テーブル・列の追加・削除 検出 そのまま使える
型の変更(String(200) → String(300)) 検出(compare_type は既定で有効) そのまま使える
インデックスの追加 検出 そのまま使える
列名の変更 「列の削除+列の追加」になる(データが消える) op.alter_column(new_column_name=...) を手で書く
テーブル名の変更 「テーブルの削除+作成」になる op.rename_table を手で書く
server_default の変更 検出しない(compare_server_default=True で検出) 設定を足す
名前付きの CHECK 制約 検出しない(プラグインで検出) autogenerate_plugins に足す
PostgreSQL の Enum に値を追加 検出しない ALTER TYPE ... ADD VALUE を手で書く
データが入ったテーブルに NOT NULL 列 スクリプトは作られるが、upgrade で失敗 3段階に分けて書く

確認環境:Alembic 1.20.0・SQLAlchemy 2.1.4・psycopg 3.3.6(pip で導入)、Python 3.11、PostgreSQL 16.15(Ubuntu 24.04 の apt パッケージ)。SQLite(3.45.1)でも batch モードを試しました。この記事のスクリプトとログは、実際にコマンドを実行して出たものです。検出の範囲は Alembic の公式ドキュメント「Auto Generating Migrations」でも確かめました(確認日 2026年10月13日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Alembicの使い方|SQLAlchemyのマイグレーション手順」

1. インストールと alembic init

pip install alembic "psycopg[binary]"    # PostgreSQL のドライバも入れる
alembic list_templates
Available templates:

pyproject_async - pyproject configuration, with an async dbapi.
multidb - Rudimentary multi-database configuration.
generic - Generic single-database configuration.
pyproject - pyproject configuration, based on the generic configuration.
async - Generic single-database configuration with an async dbapi.

既定の generic テンプレートで初期化します。

alembic init migrations
Creating directory …/migrations ...  done
Creating directory …/migrations/versions ...  done
Generating …/migrations/script.py.mako ...  done
Generating …/migrations/README ...  done
Generating …/migrations/env.py ...  done
Generating …/alembic.ini ...  done
Please edit configuration/connection/logging settings in …/alembic.ini before proceeding.
ファイル 役割
alembic.ini 設定(script_location・sqlalchemy.url・ログ・post_write_hooks)
migrations/env.py 接続とモデルのつなぎ込み。ここを編集する
migrations/script.py.mako 新しいスクリプトのひな形
migrations/versions/ マイグレーションのスクリプトが入る

設定を pyproject.toml の [tool.alembic] に書きたいときは alembic init -t pyproject migrations、非同期のドライバ(asyncpg など)を使うときは -t async を選びます。

2. モデルと env.py をつなぐ

SQLAlchemy 2.0 の書き方(DeclarativeBase・Mapped)のモデルです。MetaData に naming_convention(制約の名前の付け方)を渡しておくと、制約に必ず名前が付き、あとで削除・変更するスクリプトが安定します。

# app/models.py
from datetime import datetime

from sqlalchemy import ForeignKey, MetaData, String, func
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship

NAMING_CONVENTION = {
    "ix": "ix_%(column_0_label)s",
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s",
}


class Base(DeclarativeBase):
    metadata = MetaData(naming_convention=NAMING_CONVENTION)


class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(String(255), unique=True)
    name: Mapped[str] = mapped_column(String(100))
    created_at: Mapped[datetime] = mapped_column(server_default=func.now())

    posts: Mapped[list["Post"]] = relationship(back_populates="user")


class Post(Base):
    __tablename__ = "posts"

    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    title: Mapped[str] = mapped_column(String(200))

    user: Mapped[User] = relationship(back_populates="posts")

migrations/env.py は、次の2か所を変えます。

# migrations/env.py(変えた部分)
import os

from alembic import context

from app.models import Base

config = context.config

# 接続先は環境変数から(alembic.ini にパスワードを書かない)
if os.environ.get("DATABASE_URL"):
    config.set_main_option("sqlalchemy.url", os.environ["DATABASE_URL"])

# autogenerate が比べる相手(モデルの MetaData)
target_metadata = Base.metadata
export DATABASE_URL="postgresql+psycopg://app:****@localhost/appdb"

alembic.ini には既定で prepend_sys_path = . があり、alembic.ini のあるディレクトリから app.models を import できます。target_metadata = None のままだと、autogenerate はモデルを見ないので、差分を作れません。 モデルが複数のファイルに分かれているときは、すべてのモデルが import された状態の Base.metadata を渡します。

3. revision --autogenerate で最初のスクリプトを作る

alembic revision --autogenerate -m "create users and posts"
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare.tables] Detected added table 'users'
INFO  [alembic.autogenerate.compare.tables] Detected added table 'posts'
Generating …/migrations/versions/0da4d0d75970_create_users_and_posts.py ...  done

できたスクリプトです。

"""create users and posts

Revision ID: 0da4d0d75970
Revises: 
Create Date: 2026-10-13 16:14:52.988509

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '0da4d0d75970'
down_revision: Union[str, Sequence[str], None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('email', sa.String(length=255), nullable=False),
    sa.Column('name', sa.String(length=100), nullable=False),
    sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False),
    sa.PrimaryKeyConstraint('id', name=op.f('pk_users')),
    sa.UniqueConstraint('email', name=op.f('uq_users_email'))
    )
    op.create_table('posts',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('title', sa.String(length=200), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_posts_user_id_users')),
    sa.PrimaryKeyConstraint('id', name=op.f('pk_posts'))
    )
    # ### end Alembic commands ###


def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('posts')
    op.drop_table('users')
    # ### end Alembic commands ###
項目 意味
revision このスクリプトの ID
down_revision 1つ前の ID(最初は None)。この鎖で順番が決まる
upgrade() 進めるときの処理
downgrade() 戻すときの処理
op.f('pk_users') naming_convention で決めた名前を、そのまま使う印

Mapped[str] は NOT NULL、Mapped[str | None] は NULL 可として出力されました。制約の名前が pk_users・uq_users_email・fk_posts_user_id_users と、naming_convention どおりになっています。

4. upgrade・current・history

alembic upgrade head
INFO  [alembic.runtime.migration] Running upgrade  -> 0da4d0d75970, create users and posts
alembic current
# 0da4d0d75970 (head)

データベースには、テーブルのほかに alembic_version というテーブルができ、いまの版の ID が1行入りました。

 version_num  
--------------
 0da4d0d75970

psql の \d posts では、制約とインデックスが naming_convention の名前で作られていました。

Indexes:
    "pk_posts" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fk_posts_user_id_users" FOREIGN KEY (user_id) REFERENCES users(id)

5. モデルを変えて2つ目のスクリプトを作る

モデルを3か所変えました。

    bio: Mapped[str | None] = mapped_column(String(500))                    # 列の追加
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True)  # インデックス
    title: Mapped[str] = mapped_column(String(300))                         # 200 → 300

スクリプトを作る前に、alembic check でモデルとデータベースの差を確かめられます。

$ alembic check
INFO  [alembic.autogenerate.compare.types] Detected type change from VARCHAR(length=200) to String(length=300) on 'posts.title'
INFO  [alembic.autogenerate.compare.constraints] Detected added index 'ix_posts_user_id' on '('user_id',)'
INFO  [alembic.autogenerate.compare.tables] Detected added column 'users.bio'
FAILED: New upgrade operations detected: [...]

差があると終了コードが 255、無いと No new upgrade operations detected. で 0 でした。CI で「モデルを変えたのにスクリプトを作り忘れた」を見つけるのに使えます。

alembic revision --autogenerate -m "add bio and index"
def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.alter_column('posts', 'title',
               existing_type=sa.VARCHAR(length=200),
               type_=sa.String(length=300),
               existing_nullable=False)
    op.create_index(op.f('ix_posts_user_id'), 'posts', ['user_id'], unique=False)
    op.add_column('users', sa.Column('bio', sa.String(length=500), nullable=True))
    # ### end Alembic commands ###


def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('users', 'bio')
    op.drop_index(op.f('ix_posts_user_id'), table_name='posts')
    op.alter_column('posts', 'title',
               existing_type=sa.String(length=300),
               type_=sa.VARCHAR(length=200),
               existing_nullable=False)
    # ### end Alembic commands ###

型の変更(compare_type)は、Alembic 1.12.0 から既定で検出されます。 ドキュメントにも「Changed in version 1.12.0: The default value of compare_type has been changed to True」とあります。

6. autogenerate で検出されない変更と直し方

列名の変更:削除+追加になる

name を display_name に変えて alembic check を実行すると、次のように出ました。

INFO  [alembic.autogenerate.compare.tables] Detected added column 'users.display_name'
INFO  [alembic.autogenerate.compare.tables] Detected removed column 'users.name'

このまま upgrade すると、name 列のデータが消えます。 Alembic には「名前が変わった」ことは分からないためです。中身が空のスクリプトを作って、手で書きます。

alembic revision -m "rename users.name to display_name"
def upgrade() -> None:
    op.alter_column("users", "name", new_column_name="display_name")


def downgrade() -> None:
    op.alter_column("users", "display_name", new_column_name="name")

2行入れた状態で upgrade すると、データは残ったまま列名だけが変わり、そのあとの alembic check は No new upgrade operations detected. でした。

 id |     email     | display_name 
----+---------------+--------------
  1 | a@example.com | Aoki
  2 | b@example.com | Baba

テーブル名の変更も同じです。 __tablename__ を posts から articles に変えると、Detected added table 'articles'・Detected removed table 'posts' になりました。op.rename_table("posts", "articles") を手で書きます。

server_default の変更:既定では検出しない

server_default=func.now() を func.statement_timestamp() に変えても、alembic check は No new upgrade operations detected. でした。env.py の context.configure に compare_server_default=True を足すと、detected server default on column 'users.created_at' と検出されました。

context.configure(
    connection=connection,
    target_metadata=target_metadata,
    compare_server_default=True,
)

ドキュメントでも、server default の比較は「既定では無効(compare_server_default で有効)」とされています。有効にしたら、生成されたスクリプトを必ず読み、意図しない差分が入っていないかを確かめます。

名前付きの CHECK 制約:プラグインを足す

CheckConstraint("length(title) > 0", name="title_not_empty") を足しても、既定では検出されませんでした。Alembic 1.19.0 で加わった alembic.ext.checkconstraint_byname プラグインを有効にすると、検出されました(1.19.2 から既定では無効)。

context.configure(
    connection=connection,
    target_metadata=target_metadata,
    autogenerate_plugins=[
        "alembic.autogenerate.*",
        "alembic.ext.checkconstraint_byname",
    ],
)
def upgrade() -> None:
    op.create_check_constraint(op.f('ck_posts_title_not_empty'), 'posts', 'length(title) > 0')


def downgrade() -> None:
    op.drop_constraint(op.f('ck_posts_title_not_empty'), 'posts', type_='check')

名前で比べる仕組みなので、名前の無い制約は検出できません。 naming_convention を設定しておく理由の1つです。

PostgreSQL の Enum:型の作成と値の追加

Enum("public", "private", name="visibility") の列を既存のテーブルに足すと、autogenerate は op.add_column(... sa.Enum(...) ...) を作りました。これをそのまま upgrade すると、PostgreSQL で失敗しました。

sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedObject) type "visibility" does not exist
[SQL: ALTER TABLE posts ADD COLUMN visibility visibility DEFAULT 'public' NOT NULL]

create_table と違い、add_column では Enum の型が作られなかったためです。型を先に作り、downgrade で型も消すように直すと、upgrade・downgrade とも通りました。

def upgrade() -> None:
    visibility = sa.Enum("public", "private", name="visibility")
    visibility.create(op.get_bind(), checkfirst=True)   # 型を先に作る
    op.add_column("posts", sa.Column("visibility", visibility, server_default="public", nullable=False))


def downgrade() -> None:
    op.drop_column("posts", "visibility")
    sa.Enum(name="visibility").drop(op.get_bind(), checkfirst=True)   # 型も消す

さらに、モデルの Enum に "draft" を足しても、alembic check は No new upgrade operations detected. でした。値の追加は手で書きます。

def upgrade() -> None:
    op.execute("ALTER TYPE visibility ADD VALUE IF NOT EXISTS 'draft'")

upgrade 後、enum_range(null::visibility) は {public,private,draft} になりました。PostgreSQL の Enum から値を消す SQL は無いので、downgrade は型の作り直しが必要になります。

データが入ったテーブルに NOT NULL の列を足す

status: Mapped[str] = mapped_column(String(20))(NOT NULL)を足すと、autogenerate は op.add_column('users', sa.Column('status', sa.String(length=20), nullable=False)) を作りました。2行入ったテーブルに upgrade すると、失敗しました。

psycopg.errors.NotNullViolation: column "status" of relation "users" contains null values

PostgreSQL は DDL もトランザクションに入るため、失敗したスクリプトは丸ごと取り消され、alembic current は1つ前の版のままでした(ログの Will assume transactional DDL. がその印です)。3段階に書き直して通しました。

def upgrade() -> None:
    # 1. NULL を許して追加 → 2. 既存の行を埋める → 3. NOT NULL にする
    op.add_column("users", sa.Column("status", sa.String(length=20), nullable=True))
    op.execute("UPDATE users SET status = 'active' WHERE status IS NULL")
    op.alter_column("users", "status", nullable=False)

既定値で埋めてよい列なら、server_default="active" を付けて1回で追加する方法もあります。NOT NULL のエラーは、関連記事「not-null constraintの直し方|PostgreSQL」で扱っています。

7. downgrade と履歴

alembic history
8f854eccb59f -> 7f79a5e74a3e (head), add users.status
f35e707d34d6 -> 8f854eccb59f, rename users.name to display_name
0b973d64061f -> f35e707d34d6, add title check
0da4d0d75970 -> 0b973d64061f, add bio and index
<base> -> 0da4d0d75970, create users and posts
$ alembic downgrade -1
INFO  [alembic.runtime.migration] Running downgrade 7f79a5e74a3e -> 8f854eccb59f, add users.status

$ alembic downgrade 0b973d64061f
INFO  [alembic.runtime.migration] Running downgrade 8f854eccb59f -> f35e707d34d6, rename users.name to display_name
INFO  [alembic.runtime.migration] Running downgrade f35e707d34d6 -> 0b973d64061f, add title check

$ alembic downgrade base
INFO  [alembic.runtime.migration] Running downgrade 0b973d64061f -> 0da4d0d75970, add bio and index
INFO  [alembic.runtime.migration] Running downgrade 0da4d0d75970 -> , create users and posts

downgrade base のあと、データベースに残ったのは alembic_version テーブルだけでした。

コマンド早見表

コマンド 内容
alembic upgrade head 最新まで進める
alembic upgrade +1 / alembic downgrade -1 1つ進める/戻す
alembic upgrade <ID> / alembic downgrade <ID> 指定の版まで
alembic downgrade base すべて戻す
alembic current いまの版
alembic history 履歴(--verbose で詳しく)
alembic heads 最新の版(複数あれば分岐している)
alembic check モデルとの差があれば失敗(CI 向け)
alembic stamp head スクリプトを動かさずに、版だけ記録する
alembic upgrade A:B --sql SQL を出力するだけ(オフライン)
alembic merge heads -m "..." 分かれた head をまとめる

stamp は、Base.metadata.create_all() で作った既存のデータベースに Alembic を入れるときに使います。alembic stamp head を実行すると Running stamp_revision -> ebf3a21358f7 と表示され、テーブルには触れずに alembic_version だけが書き換わりました。

SQL だけを出す(DBA にレビューしてもらうとき)

alembic upgrade 0da4d0d75970:0b973d64061f --sql
BEGIN;

-- Running upgrade 0da4d0d75970 -> 0b973d64061f

ALTER TABLE posts ALTER COLUMN title TYPE VARCHAR(300);

CREATE INDEX ix_posts_user_id ON posts (user_id);

ALTER TABLE users ADD COLUMN bio VARCHAR(500);

UPDATE alembic_version SET version_num='0b973d64061f' WHERE alembic_version.version_num = '0da4d0d75970';

COMMIT;

本番に流す SQL を事前に確かめたり、DB に直接つなげない環境で手で流したりするときに使えます。ALTER TABLE の書き方は、関連記事「ALTER TABLEでカラム追加・型変更|MySQL・PostgreSQL比較」で扱っています。

8. 複数の head(ブランチで同時にスクリプトを作った)

2人が同じ版から別々にスクリプトを作ると、head が2つになります。再現すると次のようになりました。

$ alembic heads
aaaa00000001 (head)
bbbb00000002 (head)

$ alembic upgrade head
FAILED: Multiple head revisions are present for given argument 'head'; please specify a specific target revision, '<branchname>@head' to narrow to a specific head, or 'heads' for all heads

alembic merge heads で、2つを親に持つスクリプトを作ってまとめます。

alembic merge heads -m "merge feature a and b"
# 生成されたスクリプト(抜粋)
"""merge feature a and b

Revises: aaaa00000001, bbbb00000002
"""
down_revision: Union[str, Sequence[str], None] = ('aaaa00000001', 'bbbb00000002')
$ alembic upgrade head
INFO  [alembic.runtime.migration] Running upgrade 7f79a5e74a3e -> bbbb00000002, feature b
INFO  [alembic.runtime.migration] Running upgrade 7f79a5e74a3e -> aaaa00000001, feature a
INFO  [alembic.runtime.migration] Running upgrade aaaa00000001, bbbb00000002 -> ebf3a21358f7, merge feature a and b

$ alembic heads
ebf3a21358f7 (head)

2つのスクリプトが同じテーブルを変えていないかは、merge の前に読んで確かめます。CI で alembic heads の行数が1行かを確かめておくと、マージ前に気づけます。

9. SQLite では batch モード(render_as_batch)

SQLite の ALTER TABLE は、制約の追加などに対応していません。SQLite のデータベースで、code 列に UNIQUE を付けて memo 列を消す変更を autogenerate すると、upgrade で次のエラーになりました。

NotImplementedError: No support for ALTER of constraints in SQLite dialect. Please refer to the batch mode feature which allows for SQLite migrations using a copy-and-move strategy.

env.py の context.configure に render_as_batch=True を足すと、autogenerate が batch_alter_table の形で出力します。

context.configure(
    connection=connection,
    target_metadata=target_metadata,
    render_as_batch=True,  # SQLite 向け:テーブルを作り直す方式で ALTER する
)
def upgrade() -> None:
    with op.batch_alter_table('items', schema=None) as batch_op:
        batch_op.create_unique_constraint(batch_op.f('uq_items_code'), ['code'])
        batch_op.drop_column('memo')

この形では upgrade が通り、テーブルは次の定義に作り直されました。downgrade も通りました。

CREATE TABLE "items" (
    id INTEGER NOT NULL, 
    code VARCHAR(20) NOT NULL, 
    CONSTRAINT pk_items PRIMARY KEY (id), 
    CONSTRAINT uq_items_code UNIQUE (code)
)

SQLite の使い方は、関連記事「SQLiteの使い方|コマンド早見表とPython連携を実行例で解説」で扱っています。

10. 運用のチェックリスト

確かめること 方法
生成されたスクリプトを読んだか 列名・テーブル名の変更が「削除+追加」になっていないか
downgrade も動くか 開発環境で upgrade head → downgrade -1 → upgrade head
モデルとスクリプトがそろっているか CI で alembic check
head が1つか CI で alembic heads
本番の SQL を確かめたか alembic upgrade A:B --sql
大きなテーブルのロック 列の追加・インデックス作成がテーブルをロックしないか(PostgreSQL なら CREATE INDEX CONCURRENTLY を検討)
接続情報を ini に書いていないか env.py で環境変数から読む

生成されたスクリプトを Ruff などで整えたいときは、alembic.ini の [post_write_hooks] を使えます。テンプレートには ruff.options = check --fix REVISION_SCRIPT_FILENAME の例がコメントで入っていました。Ruff の使い方は、関連記事「Ruffの使い方|pyproject.toml設定とルール一覧」で扱っています。

よくある質問

Q. Base.metadata.create_all() と Alembic はどう使い分けますか。 A. create_all() は「無いテーブルを作る」だけで、列の追加や変更はできません。本番のように、データを残したまま構造を変えていくデータベースは Alembic で管理し、テスト用の使い捨てのデータベースだけ create_all() を使う形がよく使われます。モデルの書き方は、関連記事「SQLAlchemy 2.0の使い方|CRUD・リレーションを動くコードで解説」で扱っています。

Q. autogenerate で Detected sequence named 'users_id_seq' ... assuming SERIAL and omitting と出ます。 A. PostgreSQL の SERIAL の列が持つシーケンスを、Alembic が「SERIAL の一部」と判断して比較から外したという INFO のメッセージです。差分ではありません。

Q. 制約の名前はどう決めればよいですか。 A. この記事の naming_convention は、pk_テーブル名・uq_テーブル名_列名・fk_テーブル名_列名_参照先 の形です。命名の考え方は、関連記事「DB命名規則一覧|テーブル名・カラム名・インデックス名・制約名」で扱っています。

Q. FastAPI のアプリで使えますか。 A. 同じ手順で使えます。モデルの Base.metadata を env.py の target_metadata に渡し、起動前に alembic upgrade head を実行します。FastAPI の作り方は、関連記事「FastAPI入門|uvで作るCRUD API完成コードと実行結果」で扱っています。

まとめ

  • init → env.py に target_metadata → revision --autogenerate → upgrade head が基本の流れ
  • naming_convention を最初に決める。制約に名前が付き、downgrade や CHECK の検出が安定する
  • 列名・テーブル名の変更は「削除+追加」になるので、alter_column(new_column_name=...)・rename_table を手で書く
  • server_default は compare_server_default=True、CHECK はプラグイン、Enum の値は手で書く
  • データ入りのテーブルに NOT NULL 列は 追加 → UPDATE → NOT NULL の3段階
  • CI で alembic check(差があれば 255)と alembic heads を確かめる

参考・出典

確認日はいずれも 2026年10月13日です。

  • Alembic ドキュメント「Tutorial」:https://alembic.sqlalchemy.org/en/latest/tutorial.html
  • Alembic ドキュメント「Auto Generating Migrations」:https://alembic.sqlalchemy.org/en/latest/autogenerate.html
  • Alembic ドキュメント「The Importance of Naming Constraints」:https://alembic.sqlalchemy.org/en/latest/naming.html
  • Alembic ドキュメント「Running "Batch" Migrations for SQLite and Other Databases」:https://alembic.sqlalchemy.org/en/latest/batch.html
  • Alembic ドキュメント「Working with Branches」:https://alembic.sqlalchemy.org/en/latest/branches.html
  • Alembic ドキュメント「Operation Reference」:https://alembic.sqlalchemy.org/en/latest/ops.html
  • alembic(PyPI):https://pypi.org/project/alembic/

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Alembicの使い方|SQLAlchemyのマイグレーション手順」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?