如何在SQLAlchemy中定义复合主键

48

我正在尝试使用SQLAlchemy与MySQL创建一个具有复合主键的表映射,但我不确定我是否做得正确。现有的表已定义为具有复合主键。

以下是映射类定义:

class table1(Base):
    __tablename__ = 'table1'

    col1 = Column(String, primary_key=True)
    col2 = Column(String, primary_key=True)
    col3 = Column(String)

    def __init__ = (self, col1, col2, col3):
        self.col1 = col1
        self.col2 = col2
        self.col3 = col3

这与数据库中已有的记录匹配

如果我将其添加到会话中并添加到表中的记录,然后使用数据进行操作,则会出现MySQL错误(1062重复项)。

session.add(a)
b = session.query(table1)
for instance in b:
    print(instance.col1, instance.col2)

如果我正在使用只有一个键的表格,那么我会得到以下错误:

New instance <table2 at 0x2f204d0> with identity key 
(<class '__main__.table2'>,('test',)) conflicts with 
persistent instance <table2 at 0x2f88770>

我是否错误地定义了复合主键?如果没有,那么我在下面做错了什么导致我收到MySQL错误而不是Python/SQLAlchemy错误?


1
我不是很确定,我理解你在做什么。如果该值已经存在,则需要查询它,而不是创建新值:a = session.query(table1).filter(table1.col1 == 'test').filter(table1.col2 == 'test').one()。如果这对你来说不清楚,那么我强烈建议你参考文档中提供的教程。如果我对你的问题有误解,请详细说明。 - javex
你正在使用哪个版本的SQLAlchemy? - Spencer Bates
目前提供的信息不足以了解正在发生的情况。如何创建一个最小、完整和可验证的示例 看起来,使用复合键和非复合键都试图添加一个已经在表中存在的关键子行值的行,但是关键字声明表示给定的关键子行值只能在表中出现一次,因此会出现错误消息。当我写这篇文章时,这个问题有一个来自TerrenceBrannon的悬赏,他最好发布一个新问题,这样他们就可以从自己的情况中提供足够的细节。 - philipxy
1个回答

36

我同意这个问题不够明确。但是你可以使用以下内容作为指南。这将从MySQL的test数据库中的trial1表进行选择。注释掉的部分提供了另一种设置主键约束的方式。

from sqlalchemy import String, create_engine, MetaData, Column
from sqlalchemy.ext.declarative import declarative_base
# from sqlalchemy.schema import PrimaryKeyConstraint
from sqlalchemy.orm import sessionmaker

engine = create_engine('mysql+pymysql://root:root@127.0.0.1/test')
metadata = MetaData(bind=engine)
Base = declarative_base(metadata=metadata)


class TableClassName(Base):
    __tablename__ = 'table1'

    col1 = Column(String, primary_key=True)
    col2 = Column(String, primary_key=True)
    col3 = Column(String)

    # __table_args__ = (
    #     PrimaryKeyConstraint(
    #         col1,
    #         col2),
    #     {})

Session = sessionmaker(bind=engine)
session = Session()

b = session.query(TableClassName)
for instance in b:
   print(instance.col1, instance.col2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接