【问题标题】:Alembic: IntegrityError: "column contains null values" when adding non-nullable columnAlembic:IntegrityError:添加不可为空的列时“列包含空值”
【发布时间】:2016-02-15 19:11:03
【问题描述】:

我正在向现有表中添加一列。这个新列是nullable=False

op.add_column('mytable', sa.Column('mycolumn', sa.String(), nullable=False))

当我运行迁移时,它会抱怨:

sqlalchemy.exc.IntegrityError: column "mycolumn" contains null values

【问题讨论】:

    标签: python sqlalchemy alembic


    【解决方案1】:

    这是因为您现有的数据对该新列没有任何价值,即null。从而导致所述错误。添加不可为空的列时,您必须决定为现有数据赋予什么值


    好的,那么现有数据应该只有这个新列的“lorem ipsum”。但是我该怎么做呢?我无法更新,因为该列还没有。

    使用server_default 参数:

    op.add_column('mytable', sa.Column(
        'mycolumn', 
        sa.String(), 
        nullable=False, 
        server_default='lorem ipsum', #  <---  add this
    ))
    

    但是,但是,我不希望它有默认值

    之后使用op.alter_column('mytable', 'mycolumn', server_default=None)删除它

    例如你的upgrade() 函数是:

    def upgrade():
        op.add_column('mytable', sa.Column('mycolumn', sa.String(), nullable=False, server_default='lorem ipsum'))
        op.alter_column('mytable', 'mycolumn', server_default=None)
    

    【讨论】:

    • @Steve 使用 'True''False' 而不是 TrueFalse
    • 同样重要的是要注意所有值都应该作为字符串传递(即使是整数!)因为 server_default 是特定的 SQL 文本,可以在“CREATE TABLE”的“DEFAULT”部分中指定“ 陈述。就我而言,我必须指定 op.add_column( "project", sa.Column("tenant_id", sa.Integer(), nullable=False, server_default="1"), ) 才能使其工作(我的 id 是整数)
    • 如果bool 的默认值类型使用sa.sql.expression.false()sa.sql.expression.true(),如下所示:op.add_column('table', sa.Column('col_name', sa.Boolean(), nullable=False, server_default=sa.sql.expression.false()))
    【解决方案2】:

    @Ron 的答案的另一种选择是做相反的事情,并修改数据添加约束:

    def upgrade():
        op.add_column('my_table', sa.Column('my_column', sa.String()))
        op.execute('UPDATE my_table SET my_column=my_other_column')
        op.alter_column('my_table', 'my_column', nullable=False)
    

    对我来说似乎更简洁、更强大,但您正在编写 SQL :-)。

    【讨论】:

    • 当使用 MySQL 后端时,最后一行应该是 op.alter_column('my_table', 'my_column', existing_type=sa.String(), nullable=False),否则你会得到一个alembic。 util.exc.CommandError(更多关于here
    • 这不是取决于您正在运行 UPDATE 的表的大小吗?想象一个有 1M 记录的生产表...:/
    【解决方案3】:

    它正确地告诉您,数据库中存在(或将存在)该列的 NULL 值。答案是在更改列定义之前编辑迁移文件以更新列:

    from sqlalchemy.sql import table, column
    
    def upgrade():
        op.add_column('role', sa.Column('role_name', sa.String(length=30), nullable=True))
        role = table('role', column('role_name'))       
        op.execute(role.update().values(role_name=''))       
        op.alter_column('role', 'role_name', nullable=False)       
    

    【讨论】:

    • 与其他答案相比,这是一种更简洁的方法。
    猜你喜欢
    • 1970-01-01
    • 2016-06-27
    • 2013-08-26
    • 1970-01-01
    • 2022-01-16
    • 2016-09-11
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    相关资源
    最近更新 更多