Alembic -复合主键导致MySQL的表定义不正确

oyxsuwqo  于 2023-08-02  发布在  Mysql
关注(0)|答案(1)|浏览(104)

我有多个“版本化”数据库SQLALchemy模型,它们通过组合自动增量int字段(“id”)和datetime字段(“record_valid_from”)来使用复合主键。我尝试在本地Docker容器中运行MySQL数据库设置。
模型定义如下所示:

from sqlalchemy.orm import (DeclarativeBase, Mapped)

class classA(DeclarativeBase):
    id: Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
    record_valid_from: Mapped[datetime] = mapped_column(DateTime,
        primary_key=True,
        default=get_current_timestamp # this is a python method returning datetime.now()
    )
    active: Mapped[bool] = mapped_column(Boolean, default=True,
        comment="TRUE if latest version, FALSE otherwise"
    )
    ... # some more fields and logic

字符串
其他模型看起来很相似,但它们之间存在各种不同的关系。
使用alembic(alembic revision --autogenerate -m "init database")自动生成迁移脚本时,生成的python代码似乎生成了无效的SQL。
更确切地说,我遇到了:

(pymysql.err.OperationalError) (1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key')


下面是迁移代码(注意:我把它简化了一点):

def upgrade() -> None:
    op.create_table('classA',
        sa.Column('name', sa.String(length=100), nullable=False),
        sa.Column('record_valid_from', sa.DateTime(), nullable=False),
        sa.Column('active', sa.Boolean(), nullable=False),
        sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
        sa.PrimaryKeyConstraint('record_valid_from', 'id')
    )
    op.create_index(op.f('ix_classA_id'), 'classA', ['id'], unique=False)


有没有人经历过类似的事情和/或知道如何解决这个问题?
我尝试过的事情:

  • 在创建表后调用op.create_primary_key(请参见:(未显示)。结果:sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1068, 'Multiple primary key defined')
  • 删除sa.PrimaryKeyConstraint,然后直接调用op.create_primary_key。测试结果:
  • 迁移工作正常
  • 尝试创建新的ORM模型会导致:sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1364, "Field 'id' doesn't have a default value")
nhaq1z21

nhaq1z211#

我在这个问题上花了几个小时,自己解决了。对于任何有类似问题的人,这里有答案:
PrimaryKeyConstraint中包含主键字段的顺序实际上很重要。我的问题通过恢复顺序解决了,我将sa.PrimaryKeyConstraint('record_valid_from', 'id')改为sa.PrimaryKeyConstraint("id", "record_valid_from")
希望这能帮上忙。

相关问题