Alembic - 使用複合主鍵在MySQL中導致表定義不正確的問題
P粉183077097
2023-07-24 22:17:01
<p>我有多個使用複合主鍵的「versioned」資料庫SQLAlchemy模型,透過組合自增整型欄位(「id」)和日期時間欄位(「record_valid_from」)來實現。我正在嘗試在本地的Docker容器中運行這個模型對MySQL資料庫進行設定。 </p><p>模型定義大致如下:</p><p><br /></p>
<pre class="brush:php;toolbar:false;">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</pre>
<p>其他模型看起來類似,它們之間有各種不同的關係。 </p><p>當使用Alembic自動產生遷移腳本(alembic revision --autogenerate -m "init database")時,產生的Python程式碼似乎會產生無效的SQL語句。 </p><p>更具體地說,我遇到了:</p><p><br /></p>
<pre class="brush:php;toolbar:false;">(pymysql.err.OperationalError) (1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key')< ;/pre>
<p>以下是遷移程式碼(注意:我對其進行了簡化):</p>
<pre class="brush:php;toolbar:false;">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)</pre>
<p>有人經歷過類似的情況嗎?或知道如何解決這個問題嗎? </p><p>我試過以下方法:</p><p><br /></p>
<ul>
<li>在建立表格後呼叫op.create_primary_key(請參閱:https://alembic.sqlalchemy.org/en/latest/ops.html#alembic.operations.Operations.create_primary_key)。結果:sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1068, '定義了多個主鍵')。<code></code></li>
<li>移除sa.PrimaryKeyConstraint然後直接呼叫op.create_primary_key。結果:
<ul>
<li>遷移成功正常運作。 </li>
<li>嘗試建立一個新的ORM模型導致了以下錯誤:sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1364, "字段'id'沒有預設值")。 <code></code></li>
</ul>
</li>
</ul><p><br /></p>
我花了幾個小時解決了這個問題,並且自己修復了它。對於遇到類似問題的人,這是答案:
實際上,主鍵欄位在PrimaryKeyConstraint中的順序是有影響的。我的問題是透過改變順序來解決的,而不是使用sa.PrimaryKeyConstraint('record_valid_from', 'id'),我改成了sa.PrimaryKeyConstraint("id", "record_valid_from")。
希望這可以幫到你。