简体   繁体   English

如何在SQLAlchemy中设置复杂条件组合外键

[英]How to set up complex condition composite foreign key in SQLAlchemy

Here's my ORM entity class. 这是我的ORM实体类。 The primary key is composite cause 'id_string' may be the same for different users (identified by uid). 主键是复合原因,因为“ id_string”对于不同的用户可能是相同的(由uid标识)。 One thing I understood from Postgres SQL error when creating a table based on this class ( 根据此类创建表时,我从Postgres SQL错误中了解到一件事(

ProgrammingError: (ProgrammingError) there is no unique constraint matching given keys for referenced table "sync_entities"

) is that I need to add something to parent_id_string's ForeignKey() argument. )是我需要在parent_id_string的ForeignKey()参数中添加一些内容。 And that something is, I think, the current record's uid. 我认为这是当前记录的uid。

Do you suggest to try using different primary key (autoincrementing integer) or there is some other way? 您是否建议尝试使用其他主键(自动递增整数)或其他方法?

class SyncEntity(Base):
    __tablename__ = 'sync_entities'
    __table_args__ = (ForeignKeyConstraint(['uid'], ['users.uid'], ondelete='CASCADE'), {})

    uid = Column(BigInteger, primary_key=True)

    id_string = Column(String, primary_key=True)
    parent_id_string = Column(String, ForeignKey('sync_entities.id_string'))
    children = relation('SyncEntity',
                        primaryjoin=('sync_entities.c.id_string==sync_entities.c.parent_id_string'),
                        backref=backref('parent', \
                                        remote_side=[id_string]))

    # old_parent_id = ...
    version = Column(BigInteger)
    mtime = Column(BigInteger)
    ctime = Column(BigInteger)
    name = Column(String)
    non_unique_name = Column(String)
    sync_timestamp = Column(BigInteger)
    server_defined_unique_tag = Column(String)
    position_in_parent = Column(BigInteger)

    insert_after_item_id = Column(String, ForeignKey('sync_entities.id_string'))
    insert_after = relation('SyncEntity',
                            primaryjoin=('sync_entities.c.id_string==sync_entities.c.insert_after_item_id'),
                            remote_side=[id_string])

    deleted = Column(Boolean)
    originator_cache_guid = Column(String)
    originator_client_item_id = Column(String)
    specifics = Column(LargeBinary)
    folder = Column(Boolean)
    client_defined_unique_tag = Column(String)
    ordinal_in_parent = Column(LargeBinary)

You know, primary key being an auto-incremented integer is usually the best approach. 您知道,主键是一个自动递增的整数通常是最好的方法。 Any values that seem to be unique in system, may turn out to be duplicated in future. 系统中似乎唯一的任何值都可能会在将来重复。 If you relied on their uniqueness you're in deep trouble. 如果您依赖于它们的独特性,那么您将陷入困境。

However, if there is a reason to require certain pair (or triple) of values in each row to be unique, just add constraint to your table, but use auto-increment integer as primary key. 但是,如果有理由要求每行中的某些值对(或三对值)是唯一的,则只需向表中添加约束,但可以使用自动递增整数作为主键。 Then if requirements change, you can alter/remove/relax your unique constraint without making changes elsewhere. 然后,如果需求发生变化,您可以更改/删除/放松唯一约束,而无需在其他地方进行更改。

Also - if you're using simple integer keys, your joins are simpler and can be performed faster by DBMS. 另外-如果您使用的是简单的整数键,则连接会更简单,并且DBMS可以更快地执行。

I think I came up with a good idea. 我想我想到了一个好主意。 Just need to create complex foreign key constructs in the __ tableargs __ member like (parent_id_string, uid) and (insert_after_item_id, uid), modifying the primaryjoin statements accordingly. 只需在__ tableargs __成员中创建复杂的外键构造,例如(parent_id_string,uid)和(insert_after_item_id,uid),并相应地修改primaryjoin语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM