slqlalchemy UniqueConstraint VS Index(unique=True)

Bas*_*ond 6 python mysql database sqlalchemy

我正在使用 MySQL(运行 InnoDB),并使用 sqlalchemy 包装了整个东西。现在,我想使用(参见文档)在我的数据库中生成更改

sqlalchemy_utils.functions.create_database(...)
Run Code Online (Sandbox Code Playgroud)

通常,上面的函数会做它应该做的事情。唯一的例外是唯一索引的生成。

说,我定义了一个这样的表:

## ...
# DeclBase = declarative_base()
## ...
class MyTable(DeclBase):
    __tablename__ = 'my_table'

    id = Column(Integer, primary_key=True)
    attr_1 = Column(String(32))
    attr_2 = Column(Integer, nullable=False)
    attr_3 = Column(DateTime)
    attr_4 = Column(
        Integer,
        ForeignKey('other_table.id', onupdate='CASCADE', ondelete='CASCADE'),
        nullable=False
    )

    u_idx = UniqueConstraint(attr_2, attr_3, 'my_table_uidx')
Run Code Online (Sandbox Code Playgroud)

当我调用 create_database 时,我将让 sqlalchemy 使用指定的所有列创建表“my_table”。外键也设置得很好,但在数据库端找不到唯一索引。然后我尝试使用 Index(unique=True) 代替。所以代替

u_idx = UniqueConstraint(attr_2, attr_3, 'my_table_uidx')
Run Code Online (Sandbox Code Playgroud)

我放

u_idx_1 = Index('my_table_uidx', attr_2, attr_3, unique=True)
Run Code Online (Sandbox Code Playgroud)

我的印象是这在逻辑上产生了类似的结果。这次sqlalchemy确实在db上创建了唯一索引。

也许我对 UniqueConstraint 和 Index(unique=True) 之间的区别,或者 sqlalchemy 使用它们自动生成数据库的方式有一些误解。

任何人都可以对此有所了解吗?

Ilj*_*ilä 5

主要区别在于,虽然IndexAPI允许在表定义之外定义索引,只要它可以通过传递的 SQL 构造引用表,aUniqueConstraint和约束通常必须在表定义中内联定义

要将表级约束对象应用ForeignKeyConstraint到使用声明式定义的表,请使用表配置中__table_args__描述的属性。

需要理解的是,在声明性类的Table构造过程中,如果没有通过显式传递,则会构造一个 new __table__。在您的示例模型类中,UniqueConstraint实例绑定到一个类属性,但声明性基不包括Table从属性创建的实例中的约束。您必须在表参数中传递它:

class MyTable(DeclBase):
    __tablename__ = 'my_table'
    ...
    # A positional argument tuple, passed to Table constructor
    __table_args__ = (
        UniqueConstraint(attr_2, attr_3, name='my_table_uidx'),
    )
Run Code Online (Sandbox Code Playgroud)

请注意,您必须将约束名称作为关键字参数传递。您还可以使用Table.append_constraint(),传递约束,如果在任何尝试创建表之前调用:

class MyTable(DeclBase):
    ...

MyTable.__table__.append_constraint(
    UniqueConstraint('attr_2', 'attr_3', name='my_table_uidx'))
Run Code Online (Sandbox Code Playgroud)