Alembic – Die Verwendung zusammengesetzter Primärschlüssel führt zu einer falschen Tabellendefinition in MySQL
P粉183077097
2023-07-24 22:17:01
<p>Ich habe mehrere „versionierte“ SQLAlchemy-Datenbankmodelle, die zusammengesetzte Primärschlüssel verwenden, die durch die Kombination eines automatisch inkrementierenden Ganzzahlfelds („id“) und eines Datums-/Uhrzeitfelds („record_valid_from“) erreicht werden. Ich versuche, dieses Modell in einem lokalen Docker-Container gegen eine MySQL-Datenbank auszuführen. </p><p>Die Modelldefinition lautet ungefähr wie folgt:</p><p><br /></p>
<pre class="brush:php;toolbar:false;">from sqlalchemy.orm import (DeclarativeBase, Mapped)
Klasse 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 # Dies ist eine Python-Methode, die datetime.now() zurückgibt.
)
aktiv: Mapped[bool] = mapped_column(Boolean, default=True,
comment="TRUE wenn neueste Version, andernfalls FALSE"
)
... # einige weitere Felder und Logik</pre>
<p>Andere Modelle sehen ähnlich aus, es gibt jedoch unterschiedliche Beziehungen zwischen ihnen. </p><p>Bei Verwendung von Alembic zum automatischen Generieren von Migrationsskripten (alembic revision --autogenerate -m "init Database") scheint der generierte Python-Code ungültige SQL-Anweisungen zu erzeugen. </p><p> Genauer gesagt bin ich auf Folgendes gestoßen: </p><p><br /></p>
<pre class="brush:php;toolbar:false;">(pymysql.err.OperationalError) (1075, 'Falsche Tabellendefinition; es kann nur eine automatische Spalte geben und diese muss als Schlüssel definiert werden')< ;/pre>
<p>Hier ist der Migrationscode (Hinweis: Ich habe ihn vereinfacht): </p>
<pre class="brush:php;toolbar:false;">def upgrade() ->
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)</pre>
<p>Hat jemand eine ähnliche Situation erlebt? Oder wissen Sie, wie Sie dieses Problem lösen können? </p><p>Ich habe Folgendes versucht: </p><p><br /></p>
<ul>
<li>Rufen Sie op.create_primary_key nach dem Erstellen der Tabelle auf (siehe: https://alembic.sqlalchemy.org/en/latest/ops.html#alembic.operations.Operations.create_primary_key). Ergebnis: sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1068, „Mehrere Primärschlüssel definiert“).<code></code></li>
<li>sa.PrimaryKeyConstraint entfernen und op.create_primary_key direkt aufrufen. Ergebnis:
<ul>
<li>Die Migration war erfolgreich und verlief normal. </li>
<li>Der Versuch, ein neues ORM-Modell zu erstellen, führte zu folgendem Fehler: sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1364, „Feld ‚id‘ hat keinen Standardwert“). <code></code></li>
</ul>
</li>
</ul><p><br /></p>
我花了几个小时解决了这个问题,并且自己修复了它。对于遇到类似问题的人,这是答案:
实际上,主键字段在PrimaryKeyConstraint中的顺序是有影响的。我的问题是通过改变顺序来解决的,而不是使用sa.PrimaryKeyConstraint('record_valid_from', 'id'),我改成了sa.PrimaryKeyConstraint("id", "record_valid_from")。
希望这可以帮到你。