当前位置:首页 > 文章列表 > 文章 > python教程 > Alembic 在 SQLite 中怎么批量修改列约束

Alembic 在 SQLite 中怎么批量修改列约束

来源:17golang原创 2026-11-11 07:46:44 0浏览 收藏

在 SQLite 中用 Alembic 修改列约束,核心不是手写一条不存在的 ALTER COLUMN,而是把变更放进 op.batch_alter_table()。对需要重建的操作,Alembic 会按新结构创建临时表、复制旧数据、替换旧表。这样可以把“改 nullable”和“增加 CHECK”写成可审查的迁移脚本。

官方地址:https://alembic.sqlalchemy.org/

下面只讨论表结构迁移,不把业务数据清洗混进迁移脚本。假设 user_account.email 允许为空,现在要改成必填,并给 age 加上非负约束。

先判断:为什么 SQLite 要用 batch 模式

SQLite 的 ALTER TABLE 主要覆盖重命名表、重命名列、添加列和删除列;修改已有列的约束通常不能直接套用其他数据库的写法。Alembic 的 batch 模式把一组单表操作集中起来,在 SQLite 上采用“新表 + INSERT ... SELECT + 替换”的方式完成迁移。

因此,batch_alter_table 不是单纯的语法糖。它明确告诉迁移工具:这些变化要以表结构为整体处理。默认 recreate="auto" 会在 SQLite 遇到需要重建的操作时启用重建;为了让迁移意图更直观,也可以显式写成 recreate="always"。

Alembic batch 模式把迁移操作、SQLite 临时表和约束结构连接起来的静态说明图
图1:batch 迁移的结构说明图,展示迁移脚本、约束定义与 SQLite 重建对象的关系,不是运行截图。

用一个 batch 块批量修改列约束

修改已有列时,建议同时写出 existing_type 和 existing_nullable。它们让 Alembic 在反射旧表和生成新表时有明确的旧结构信息,尤其适合类型、默认值和可空性一起变化的场景。

from alembic import op
import sqlalchemy as sa

def upgrade():
    # SQLite 需要按新表结构重建,统一承载多个约束变化
    with op.batch_alter_table("user_account", recreate="always") as batch_op:
        # 先声明旧类型和旧可空性,避免迁移信息不完整
        batch_op.alter_column(
            "email",
            existing_type=sa.String(length=255),
            existing_nullable=True,
            nullable=False,
        )
        # CHECK 约束要有稳定名称,后续才能精确删除或调整
        batch_op.create_check_constraint(
            "ck_user_account_age_nonnegative",
            sa.text("age >= 0"),
        )

def downgrade():
    # 回滚时恢复可空性,并删除同名 CHECK 约束
    with op.batch_alter_table("user_account", recreate="always") as batch_op:
        batch_op.drop_constraint(
            "ck_user_account_age_nonnegative", type_="check"
        )
        batch_op.alter_column(
            "email",
            existing_type=sa.String(length=255),
            existing_nullable=False,
            nullable=True,
        )

这里的“批量”指同一个表的多项结构变化被一次 batch 操作处理,不是把多张表塞进一个上下文。迁移前必须确认现有行没有 NULL 邮箱,也没有负年龄;否则新表的约束会让数据复制阶段失败。

类型、默认值和约束名称要写完整

如果同时改类型或服务端默认值,继续补齐 existing_server_default、type_ 等旧值信息。不要只写 nullable=False 就假设 Alembic 能推断所有旧元数据;反射结果、方言和命名约定都会影响重建表的最终定义。

SQLite 反射出的部分约束可能没有名字。需要删除或替换 CHECK、外键时,优先在模型和迁移中建立命名约定,或者在 batch 上提供 naming_convention。没有稳定名称时,drop_constraint() 很难准确定位目标。

from alembic import op
import sqlalchemy as sa

def upgrade():
    # 命名约定帮助反射后的无名约束获得可操作的名字
    convention = {
        "ck": "ck_%(table_name)s_%(constraint_name)s",
    }
    with op.batch_alter_table(
        "user_account",
        recreate="always",
        naming_convention=convention,
    ) as batch_op:
        # 类型变化时保留旧类型,避免生成的 CREATE TABLE 缺少上下文
        batch_op.alter_column(
            "age",
            existing_type=sa.Integer(),
            type_=sa.SmallInteger(),
            existing_nullable=True,
        )

如果约束表达式依赖旧列名、索引或外键,先把依赖关系列出来,再决定是否拆成多个迁移。不要把数据回填、删除脏数据和结构替换混在同一个示例里,这些属于不同的发布风险。

SQLite 表重建前后列约束、索引和外键关系的静态说明图
图2:约束生命周期说明图,强调旧表元数据、目标约束和新表结构之间的绑定关系,不是运行截图。

让 autogenerate 生成 batch 结构

项目使用自动生成时,在 Alembic 的 env.py 配置 render_as_batch=True:

context.configure(
    connection=connection,
    target_metadata=target_metadata,
    # 让自动生成的单表变化使用 batch 代码形态
    render_as_batch=True,
)

自动生成的结果仍然需要人工调整,特别是新约束的名称、旧类型和已有数据是否满足目标条件。batch 上下文默认只在 SQLite 需要时执行重建;如果显式使用 recreate="always",其他数据库也会走复制替换路径,不能无条件照搬。

发布前的四项检查

  • 数据兼容:新 NOT NULL 或 CHECK 是否会拒绝已有行。
  • 对象依赖:索引、触发器、视图和外键是否会随表重建正确恢复。
  • 锁与空间:复制整表会产生额外 I/O、临时空间和写锁,生产库要安排窗口。
  • 回滚路径:downgrade() 是否使用同一个约束名,并能恢复旧的 nullable/type。

记住这个判断:只要修改的是 SQLite 不擅长直接 ALTER 的列约束,就优先用命名清晰的 batch_alter_table,把旧结构、目标结构和数据兼容条件写在迁移代码附近。

常见问题

只改 nullable 也要 recreate 吗? 通常要。SQLite 的列约束变化属于需要新表定义的操作,使用 batch 能让 Alembic 统一处理。

为什么一定要给 CHECK 起名字? 因为后续删除或调整约束需要稳定标识;无名约束在反射和回滚时不容易精确匹配。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python ast.NodeTransformer 修改语法树后怎么补齐位置信息Python ast.NodeTransformer 修改语法树后怎么补齐位置信息
上一篇
Python ast.NodeTransformer 修改语法树后怎么补齐位置信息
Alembic 迁移脚本怎么执行带参数的 SQL
下一篇
Alembic 迁移脚本怎么执行带参数的 SQL
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    977次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    983次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1099次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1070次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    908次使用