那个令人头疼的 Alembic NotNullViolation 错误(以及如何应对)

发布: (2025年12月29日 GMT+8 00:40)
3 min read
原文: Dev.to

Source: Dev.to

发生了什么?

想象一下,你有一个名为 organizations 的表,里面存放着宝贵的数据。你决定添加一个名为 plan 的新列。

如果把它设为 NOT NULL,每一行都必须有值。但表里已经有数据了,PostgreSQL 会拒绝这次更改:

向已有数据的表添加 NOT NULL 列而不提供默认值,基本上就像让人填写一份事先没有发给他们的调查问卷。他们不知道该怎么回答,于是就慌了。

快速解决方案:添加默认值

op.add_column(
    'organizations',
    sa.Column('plan', sa.String(), nullable=False, server_default='free')
)
  • 已有行会自动得到值 'free'
  • 迁移完成后,如果你愿意,可以移除默认值。

更可控的做法:先可为空,再填充值

# 1. 将列添加为可为空
op.add_column(
    'organizations',
    sa.Column('plan', sa.String(), nullable=True)
)
UPDATE organizations SET plan = 'free' WHERE plan IS NULL;
# 3. 将列改为 NOT NULL
op.alter_column('organizations', 'plan', nullable=False)
  • 这样可以在强制 NOT NULL 约束之前,对每行应用自定义逻辑。

迁移前的手动准备

  1. 手动更新表(例如使用 UPDATE 语句)。
  2. 运行将列添加为 NOT NULL 的 Alembic 迁移。

旧行已经准备好,PostgreSQL 就不会再抛出错误。


向已有行的表中添加 NOT NULL 列,就像在拥挤的派对上增设新规则:如果你不提供方案,必然会有人不满。务必考虑已有数据——给 PostgreSQL 设置默认值、更新旧行,或两者兼顾。

Alembic 错误看起来很吓人,但其实它们只是数据库在说:
“嘿,我太爱你的数据了,不能让它坏掉。我们一起把事情做好吧。”

Back to Blog

相关文章

阅读更多 »