slqlalchemy UniqueConstraint VS Index(unique = True)

时间:2017-04-07 10:16:32

标签: python mysql database sqlalchemy

我正在使用MySQL(运行InnoDB),并使用sqlalchemy包装整个事物。现在,我想使用(参见docs

在我的数据库中生成更改
sqlalchemy_utils.functions.create_database(...)

一般来说,上述功能可以实现预期。唯一的例外是生成唯一索引。

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

## ...
# 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')

当我调用create_database时,我将使用sqlalchemy创建表'my_table',其中包含指定的所有列。外键也设置正常,但在数据库端没有找到唯一索引。然后我尝试使用索引(unique = True)。而不是

u_idx = UniqueConstraint(attr_2, attr_3, 'my_table_uidx')

我把

u_idx_1 = Index('my_table_uidx', attr_2, attr_3, unique=True)

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

也许我对于UniqueConstraint和Index(unique = True)之间的差异或者sqlalchemy使用它们自动生成数据库的方式产生了误解。

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

1 个答案:

答案 0 :(得分:2)

主要区别在于,Index API允许在表定义之外定义索引,只要它可以通过传递的SQL结构引用表,UniqueConstraint和约束must be defined inline in the table definition 3}}:

  

要将表ForeignKeyConstraint等表级约束对象应用于使用Declarative定义的表,请使用Table Configuration中描述的__table_args__属性。

要理解的是,在构造声明性类时,如果没有传递明确的Table,则构造新的__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'),
    )

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

class MyTable(DeclBase):
    ...

MyTable.__table__.append_constraint(
    UniqueConstraint('attr_2', 'attr_3', name='my_table_uidx'))