定义约束和索引

优质
小牛编辑
134浏览
2023-12-01

本节将讨论SQL constraints 和指标。在SQLAlchemy中,键类包括 ForeignKeyConstraintIndex .

定义外键

A 外键 在SQL中是一个表级构造,它约束该表中的一个或多个列,使其只允许存在于不同的列集中的值,通常但不总是位于不同的表中。我们称之为约束 外键 列和它们被约束到的列 引用的 柱。被引用的列几乎总是为其所属表定义主键,尽管有例外。外键是连接成对行的“关节”,这些行彼此之间具有关系,而sqlAlchemy在其操作的几乎每个领域都非常重视这个概念。

在SQLAlchemy和DDL中,可以将外键约束定义为table子句中的附加属性,或者对于单列外键,可以在单列定义中选择指定它们。单列外键更常见,在列级别通过构造 ForeignKey 对象作为参数 Column 对象:

user_preference = Table('user_preference', metadata_obj,
    Column('pref_id', Integer, primary_key=True),
    Column('user_id', Integer, ForeignKey("user.user_id"), nullable=False),
    Column('pref_name', String(40), nullable=False),
    Column('pref_value', String(100))
)

上面,我们定义了一个新表 user_preference 其中每一行必须在 user_id 列中也存在 user 表的 user_id 列。

论点 ForeignKey 通常是窗体的字符串 <tablename>.<columnname> 或远程架构中的表或表单的“所有者” <schemaname>.<tablename>.<columnname> . 它也可能是一个实际的 Column 对象,稍后我们将看到,它是从现有的 Table 对象通过其 c 收藏:

ForeignKey(user.c.user_id)

使用字符串的优势在于 useruser_preference 只有在第一次需要时才解析,这样表对象就可以轻松地分布在多个模块中并以任意顺序定义。

也可以在表级别定义外键,使用 ForeignKeyConstraint 对象。此对象可以描述单列或多列外键。多列外键称为 混合成的 外键,并且几乎总是引用具有复合主键的表。下面我们定义一个表 invoice 它有一个复合主键:

invoice = Table('invoice', metadata_obj,
    Column('invoice_id', Integer, primary_key=True),
    Column('ref_num', Integer, primary_key=True),
    Column('description', String(60), nullable=False)
)

然后是一张桌子 invoice_item 具有复合外键引用 invoice ::

invoice_item = Table('invoice_item', metadata_obj,
    Column('item_id', Integer, primary_key=True),
    Column('item_name', String(60), nullable=False),
    Column('invoice_id', Integer, nullable=False),
    Column('ref_num', Integer, nullable=False),
    ForeignKeyConstraint(['invoice_id', 'ref_num'], ['invoice.invoice_id', 'invoice.ref_num'])
)

重要的是要注意 ForeignKeyConstraint 是定义复合外键的唯一方法。我们也可以把个人 ForeignKey 两个上的对象 invoice_item.invoice_idinvoice_item.ref_num 列,sqlAlchemy不知道这两个值应该成对出现-它将是两个单独的外键约束,而不是引用两列的单个复合外键。

通过alter创建/删除外键约束

我们在教程和其他涉及带有DDL的外键的地方看到的行为说明约束通常在create table语句中呈现为“inline”,例如:

CREATE TABLE addresses (
    id INTEGER NOT NULL,
    user_id INTEGER,
    email_address VARCHAR NOT NULL,
    PRIMARY KEY (id),
    CONSTRAINT user_id_fk FOREIGN KEY(user_id) REFERENCES users (id)
)

这个 CONSTRAINT .. FOREIGN KEY 指令用于在创建表定义中以“内联”方式创建约束。这个 MetaData.create_all()MetaData.drop_all() 默认情况下,方法会使用拓扑类型 Table 所涉及的对象,以便按照表的外键依赖性的顺序创建和删除表(也可以通过 MetaData.sorted_tables 访问器)。

如果一个“依赖循环”中包含两个或多个外键约束,并且一组表相互依赖,则这种方法无法工作,假定后端强制使用外键(除了sqlite、mysql/myisam之外,始终如此)。因此,这些方法将在这样一个循环中将约束分解为单独的alter语句,位于除不支持大多数形式alter的sqlite之外的所有后端。给出如下模式:

node = Table(
    'node', metadata_obj,
    Column('node_id', Integer, primary_key=True),
    Column(
        'primary_element', Integer,
        ForeignKey('element.element_id')
    )
)

element = Table(
    'element', metadata_obj,
    Column('element_id', Integer, primary_key=True),
    Column('parent_node_id', Integer),
    ForeignKeyConstraint(
        ['parent_node_id'], ['node.node_id'],
        name='fk_element_parent_node_id'
    )
)

当我们召唤 MetaData.create_all() 在PostgreSQL后端等后端,解决这两个表之间的循环,并分别创建约束:

>>> with engine.connect() as conn:
...    metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
    element_id SERIAL NOT NULL,
    parent_node_id INTEGER,
    PRIMARY KEY (element_id)
)

CREATE TABLE node (
    node_id SERIAL NOT NULL,
    primary_element INTEGER,
    PRIMARY KEY (node_id)
)

ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
    FOREIGN KEY(parent_node_id) REFERENCES node (node_id)
ALTER TABLE node ADD FOREIGN KEY(primary_element)
    REFERENCES element (element_id)

为了为这些表发出DROP,同样的逻辑也适用,但是请注意,在SQL中,要发出DROP约束,需要该约束有一个名称。在这种情况下 'node' 上表中,我们没有命名这个约束;因此,系统将尝试只为那些命名为:

>>> with engine.connect() as conn:
...    metadata_obj.drop_all(conn, checkfirst=False)
ALTER TABLE element DROP CONSTRAINT fk_element_parent_node_id
DROP TABLE node
DROP TABLE element

在无法解决循环的情况下,例如,如果我们没有在此处对任一约束应用名称,我们将收到以下错误::

sqlalchemy.exc.CircularDependencyError: Can't sort tables for DROP;
an unresolvable foreign key dependency exists between tables:
element, node.  Please ensure that the ForeignKey and ForeignKeyConstraint
objects involved in the cycle have names so that they can be dropped
using DROP CONSTRAINT.

此错误仅适用于放置案例,因为我们可以在不带名称的创建案例中发出“添加约束”;数据库通常会自动分配一个。

这个 ForeignKeyConstraint.use_alterForeignKey.use_alter 关键字参数可用于手动解析依赖循环。我们只能将此标志添加到 'element' 下表:

element = Table(
    'element', metadata_obj,
    Column('element_id', Integer, primary_key=True),
    Column('parent_node_id', Integer),
    ForeignKeyConstraint(
        ['parent_node_id'], ['node.node_id'],
        use_alter=True, name='fk_element_parent_node_id'
    )
)

在create ddl中,我们将只看到这个约束的alter语句,而不会看到另一个约束:

>>> with engine.connect() as conn:
...    metadata_obj.create_all(conn, checkfirst=False)
CREATE TABLE element (
    element_id SERIAL NOT NULL,
    parent_node_id INTEGER,
    PRIMARY KEY (element_id)
)

CREATE TABLE node (
    node_id SERIAL NOT NULL,
    primary_element INTEGER,
    PRIMARY KEY (node_id),
    FOREIGN KEY(primary_element) REFERENCES element (element_id)
)

ALTER TABLE element ADD CONSTRAINT fk_element_parent_node_id
FOREIGN KEY(parent_node_id) REFERENCES node (node_id)

ForeignKeyConstraint.use_alterForeignKey.use_alter 当与DROP操作一起使用时,将要求命名约束,否则将生成如下错误:

sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name

在 1.0.0 版更改: -由调用的DDL系统 MetaData.create_all()MetaData.drop_all() 现在将自动解析由声明的表之间的相互依赖的外键 ForeignKeyConstraintForeignKey 对象,无需显式设置 ForeignKeyConstraint.use_alter 旗帜。

在 1.0.0 版更改: - The ForeignKeyConstraint.use_alter flag can be used with an un-named constraint; only the DROP operation will emit a specific error when actually called upon.

参见

配置约束命名约定

sort_tables_and_constraints()

更新和删除时

大多数数据库支持 级联 在外键值中,即当更新父行时,新值将放置在子行中,或者当删除父行时,所有相应的子行都将设置为空或已删除。在数据定义语言中,使用与外键约束相对应的短语(如“on update cascade”、“on delete cascade”和“on delete set null”)来指定这些值。“on update”或“on delete”之后的词组还允许使用其他特定于所用数据库的词组。这个 ForeignKeyForeignKeyConstraint 对象支持通过 onupdateondelete 关键字参数。该值是将在适当的“on update”或“on delete”短语之后输出的任何字符串:

child = Table('child', metadata_obj,
    Column('id', Integer,
            ForeignKey('parent.id', onupdate="CASCADE", ondelete="CASCADE"),
            primary_key=True
    )
)

composite = Table('composite', metadata_obj,
    Column('id', Integer, primary_key=True),
    Column('rev_id', Integer),
    Column('note_id', Integer),
    ForeignKeyConstraint(
                ['rev_id', 'note_id'],
                ['revisions.id', 'revisions.note_id'],
                onupdate="CASCADE", ondelete="SET NULL"
    )
)

请注意,这些条款要求 InnoDB 与MySQL一起使用时的表。其他数据库也可能不支持它们。

参见

关于 ON DELETE CASCADE 使用ORM relationship() 构件,请参见以下章节:

在具有ORM关系的DELETE cascade中使用外键

对多对多关系在DELETE上使用外键

唯一约束

可以使用在单个列上匿名创建唯一约束 unique 关键字在 Column . 显式命名的唯一约束和/或具有多个列的约束是通过 UniqueConstraint 表级构造。

from sqlalchemy import UniqueConstraint

metadata_obj = MetaData()
mytable = Table('mytable', metadata_obj,

    # per-column anonymous unique constraint
    Column('col1', Integer, unique=True),

    Column('col2', Integer),
    Column('col3', Integer),

    # explicit/composite unique constraint.  'name' is optional.
    UniqueConstraint('col2', 'col3', name='uix_1')
    )

检查约束

检查约束可以命名或未命名,也可以在列或表级别使用 CheckConstraint 构建。检查约束的文本直接传递给数据库,因此存在有限的“与数据库无关”行为。列级检查约束通常只应引用放置它们的列,而表级约束可以引用表中的任何列。

注意,有些数据库不主动支持检查约束,比如mysql。

from sqlalchemy import CheckConstraint

metadata_obj = MetaData()
mytable = Table('mytable', metadata_obj,

    # per-column CHECK constraint
    Column('col1', Integer, CheckConstraint('col1>5')),

    Column('col2', Integer),
    Column('col3', Integer),

    # table level CHECK constraint.  'name' is optional.
    CheckConstraint('col2 > col3 + 5', name='check1')
    )

sqlmytable.create(engine)
CREATE TABLE mytable (
    col1 INTEGER  CHECK (col1>5),
    col2 INTEGER,
    col3 INTEGER,
    CONSTRAINT check1  CHECK (col2 > col3 + 5)
)

主键约束

任何 Table 对象隐式存在,基于 Column 用标记的对象 Column.primary_key 旗帜。这个 PrimaryKeyConstraint 对象提供对该约束的显式访问,其中包括直接配置的选项:

from sqlalchemy import PrimaryKeyConstraint

my_table = Table('mytable', metadata_obj,
            Column('id', Integer),
            Column('version_id', Integer),
            Column('data', String(50)),
            PrimaryKeyConstraint('id', 'version_id', name='mytable_pk')
        )

参见

PrimaryKeyConstraint -详细的API文档。

使用声明性ORM扩展时设置约束

这个 Table 是允许定义表元数据的sqlAlchemy核心构造,其中,sqlAlchemy orm可以使用这些元数据作为映射类的目标。这个 Declarative 扩展允许 Table 将自动创建的对象,假定表的内容主要作为 Column 物体。

应用表级约束对象,例如 ForeignKeyConstraint 对于使用声明性定义的表,使用 __table_args__ 属性,描述于 表配置 .

配置约束命名约定

关系数据库通常为所有约束和索引指定显式名称。在创建表的常见情况下,使用 CREATE TABLE 如果在表定义中生成诸如check、unique和primary key约束之类的约束,则数据库通常有一个系统,在该系统中,如果没有另外指定名称,则会自动将名称分配给这些约束。当使用诸如 ALTER TABLE ,此命令通常需要为新约束指定显式名称,并且能够指定要删除或修改的现有约束的名称。

可以使用 Constraint.name 参数,对于索引, Index.name 参数。但是,在约束的情况下,此参数是可选的。还有一些使用 Column.uniqueColumn.index 创建的参数 UniqueConstraintIndex 未指定显式名称的对象。

修改现有表和约束的用例可以由模式迁移工具处理,例如 Alembic . 但是,alembic和sqlacalchemy目前都没有为未指定名称的约束对象创建名称,这导致了能够更改现有约束意味着必须对关系数据库使用的命名系统进行反向工程以自动分配名称,或者必须注意确保约束已命名。

与必须给所有人指定明确的名字不同 ConstraintIndex 对象,可以使用事件构造自动命名方案。这种方法的优点是,约束将获得一致的命名方案,而不需要在整个代码中使用显式的名称参数,而且对于由 Column.uniqueColumn.index 参数。从SQLAlchemy 0.9.2开始,此基于事件的方法包括在内,并且可以使用参数进行配置 MetaData.naming_convention .

配置元数据集合的命名约定

MetaData.naming_convention 指接受 Index 阶级或个人 Constraint 类作为键,python字符串模板作为值。它还接受一系列字符串代码作为可选键, "fk""pk""ix""ck""uq" 分别用于外键、主键、索引、检查和唯一约束。每当约束或索引与此关联时,将使用此字典中的字符串模板 MetaData 没有给定现有名称的对象(包括一个可以进一步修饰现有名称的异常情况)。

适合基本情况的命名约定示例如下:

convention = {
  "ix": 'ix_%(column_0_label)s',
  "uq": "uq_%(table_name)s_%(column_0_name)s",
  "ck": "ck_%(table_name)s_%(constraint_name)s",
  "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
  "pk": "pk_%(table_name)s"
}

metadata_obj = MetaData(naming_convention=convention)

上述约定将为目标内的所有约束建立名称。 MetaData 收集。例如,我们可以观察创建未命名的 UniqueConstraint ::

>>> user_table = Table('user', metadata_obj,
...                 Column('id', Integer, primary_key=True),
...                 Column('name', String(30), nullable=False),
...                 UniqueConstraint('name')
... )
>>> list(user_table.constraints)[1].name
'uq_user_name'

即使我们只使用 Column.unique 旗帜:

>>> user_table = Table('user', metadata_obj,
...                  Column('id', Integer, primary_key=True),
...                  Column('name', String(30), nullable=False, unique=True)
...     )
>>> list(user_table.constraints)[1].name
'uq_user_name'

命名约定方法的一个关键优势是,这些名称是在Python构建时建立的,而不是在DDL发出时建立的。使用Alembic的效果 --autogenerate 功能是,当生成新的迁移脚本时,命名约定将是显式的:

def upgrade():
    op.create_unique_constraint("uq_user_name", "user", ["name"])

以上 "uq_user_name" 字符串是从 UniqueConstraint 对象 --autogenerate 位于我们的元数据中。

可用的令牌包括 %(table_name)s%(referred_table_name)s%(column_0_name)s%(column_0_label)s%(column_0_key)s%(referred_column_0_name)s%(constraint_name)s 以及每个的多个列版本,包括 %(column_0N_name)s%(column_0_N_name)s%(referred_column_0_N_name)s 它呈现所有用下划线或不带下划线分隔的列名。文件 MetaData.naming_convention 对每一个约定都有进一步的详细说明。

默认命名约定

的默认值 MetaData.naming_convention 处理将名称分配给 Index 使用创建的对象 Column.index 参数::

>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})

长名称的截断

当生成的名称(尤其是使用多列标记的名称)对于目标数据库的标识符长度限制太长(例如,PostgreSQL限制为63个字符)时,将使用基于长名称的MD5哈希的4个字符后缀确定地截断名称。例如,下面的命名约定将根据使用中的列名生成非常长的名称:

metadata_obj = MetaData(naming_convention={
    "uq": "uq_%(table_name)s_%(column_0_N_name)s"
})

long_names = Table(
    'long_names', metadata_obj,
    Column('information_channel_code', Integer, key='a'),
    Column('billing_convention_name', Integer, key='b'),
    Column('product_identifier', Integer, key='c'),
    UniqueConstraint('a', 'b', 'c')
)

在PostgreSQL方言中,长度超过63个字符的名称将被截断,如下例所示:

CREATE TABLE long_names (
    information_channel_code INTEGER,
    billing_convention_name INTEGER,
    product_identifier INTEGER,
    CONSTRAINT uq_long_names_information_channel_code_billing_conventi_a79e
    UNIQUE (information_channel_code, billing_convention_name, product_identifier)
)

以上后缀 a79e 基于长名称的MD5哈希,每次都将生成相同的值,以为给定架构生成一致的名称。

为命名约定创建自定义令牌

也可以通过在命名约定字典中指定附加令牌和可调用的来添加新令牌。例如,如果我们想使用一个guid方案来命名我们的外键约束,我们可以这样做:

import uuid

def fk_guid(constraint, table):
    str_tokens = [
        table.name,
    ] + [
        element.parent.name for element in constraint.elements
    ] + [
        element.target_fullname for element in constraint.elements
    ]
    guid = uuid.uuid5(uuid.NAMESPACE_OID, "_".join(str_tokens).encode('ascii'))
    return str(guid)

convention = {
    "fk_guid": fk_guid,
    "ix": 'ix_%(column_0_label)s',
    "fk": "fk_%(fk_guid)s",
}

上面,当我们创建一个新的 ForeignKeyConstraint ,我们将得到如下名称:

>>> metadata_obj = MetaData(naming_convention=convention)

>>> user_table = Table('user', metadata_obj,
...         Column('id', Integer, primary_key=True),
...         Column('version', Integer, primary_key=True),
...         Column('data', String(30))
...     )
>>> address_table = Table('address', metadata_obj,
...        Column('id', Integer, primary_key=True),
...        Column('user_id', Integer),
...        Column('user_version_id', Integer)
...    )
>>> fk = ForeignKeyConstraint(['user_id', 'user_version_id'],
...                ['user.id', 'user.version'])
>>> address_table.append_constraint(fk)
>>> fk.name
fk_0cd51ab5-8d70-56e8-a83c-86661737766d

参见

MetaData.naming_convention -有关其他用法的详细信息以及所有可用命名组件的列表。

The Importance of Naming Constraints -在Alembic文档中。

1.3.0 新版功能: 添加了多列命名标记,如 %(column_0_N_name)s . 如果生成的名称超出了目标数据库的字符限制,则将被确定地截断。

命名检查约束

这个 CheckConstraint 对象是针对任意SQL表达式配置的,该表达式可以有任意数量的列,而且通常使用原始SQL字符串进行配置。因此,使用 CheckConstraint 我们期望对象已经有了一个名称,然后用其他约定元素来增强它。典型的惯例是 "ck_%(table_name)s_%(constraint_name)s" ::

metadata_obj = MetaData(
    naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)

Table('foo', metadata_obj,
    Column('value', Integer),
    CheckConstraint('value > 5', name='value_gt_5')
)

上表将生成名称 ck_foo_value_gt_5 ::

CREATE TABLE foo (
    value INTEGER,
    CONSTRAINT ck_foo_value_gt_5 CHECK (value > 5)
)

CheckConstraint 也支持 %(columns_0_name)s 令牌;我们可以通过确保使用 Columncolumn() 约束表达式中的元素,可以声明约束与表分离:

metadata_obj = MetaData(
    naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"}
)

foo = Table('foo', metadata_obj,
    Column('value', Integer)
)

CheckConstraint(foo.c.value > 5)

或使用 column() 内联:

from sqlalchemy import column

metadata_obj = MetaData(
    naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"}
)

foo = Table('foo', metadata_obj,
    Column('value', Integer),
    CheckConstraint(column('value') > 5)
)

两者都将产生名称 ck_foo_value ::

CREATE TABLE foo (
    value INTEGER,
    CONSTRAINT ck_foo_value CHECK (value > 5)
)

通过扫描列对象的给定表达式来确定“列零”的名称。如果表达式有多个列存在,扫描将使用确定性搜索,但是表达式的结构将确定哪个列被标记为“列零”。

1.0.0 新版功能: 这个 CheckConstraint 对象现在支持 column_0_name 命名约定令牌。

为布尔、枚举和其他架构类型配置命名

这个 SchemaType 类引用类型对象,例如 BooleanEnum 它会生成一个伴随类型的检查约束。这里的约束名称最直接的设置方式是发送“name”参数,例如 Boolean.name ::

Table('foo', metadata_obj,
    Column('flag', Boolean(name='ck_foo_flag'))
)

命名约定功能也可以与这些类型结合使用,通常使用的约定包括 %(constraint_name)s 然后对类型应用名称::

metadata_obj = MetaData(
    naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
)

Table('foo', metadata_obj,
    Column('flag', Boolean(name='flag_bool'))
)

上表将生成约束名 ck_foo_flag_bool ::

CREATE TABLE foo (
    flag BOOL,
    CONSTRAINT ck_foo_flag_bool CHECK (flag IN (0, 1))
)

这个 SchemaType 类使用特殊的内部符号,以便仅在DDL编译时确定命名约定。在PostgreSQL上,有一个本机布尔类型,因此 Boolean 不需要;我们可以安全地设置 Boolean 不带名称的类型,即使检查约束有命名约定。只有当我们对一个没有本机布尔类型(如sqlite或mysql)的数据库运行时,才会对check约束进行咨询。

检查约束也可以使用 column_0_name 令牌,它与 SchemaType 因为这些约束只有一列:

metadata_obj = MetaData(
    naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"}
)

Table('foo', metadata_obj,
    Column('flag', Boolean())
)

上述模式将产生:

CREATE TABLE foo (
    flag BOOL,
    CONSTRAINT ck_foo_flag CHECK (flag IN (0, 1))
)

在 1.0 版更改: 不包括的约束命名约定 %(constraint_name)s 再次工作 SchemaType 约束条件。

约束API

Object NameDescription

CheckConstraint

表级或列级检查约束。

ColumnCollectionConstraint

代理ColumnCollection的约束。

ColumnCollectionMixin

Constraint

表级SQL约束。

conv

标记一个字符串,指示名称已由命名约定转换。

ForeignKey

定义两列之间的依赖关系。

ForeignKeyConstraint

表级外键约束。

PrimaryKeyConstraint

表级主键约束。

UniqueConstraint

表级唯一约束。

class sqlalchemy.schema.Constraint(name=None, deferrable=None, initially=None, _create_rule=None, info=None, _type_bound=False, **dialect_kw)

可以匿名创建索引(使用自动生成的名称 ix_<column label> )对于使用inline的单个列 index 关键字在 Column ,它还修改了 unique 将唯一性应用于索引本身,而不是添加单独的唯一约束。对于具有特定名称或包含多个列的索引,请使用 Index 构造,需要名称。

下面我们举例说明 Table 用几个 Index 关联的对象。“create index”的DDL在表的create语句之后立即发出:

metadata_obj = MetaData()
mytable = Table('mytable', metadata_obj,
    # an indexed column, with index "ix_mytable_col1"
    Column('col1', Integer, index=True),

    # a uniquely indexed column with index "ix_mytable_col2"
    Column('col2', Integer, index=True, unique=True),

    Column('col3', Integer),
    Column('col4', Integer),

    Column('col5', Integer),
    Column('col6', Integer),
    )

# place an index on col3, col4
Index('idx_col34', mytable.c.col3, mytable.c.col4)

# place a unique index on col5, col6
Index('myindex', mytable.c.col5, mytable.c.col6, unique=True)

sqlmytable.create(engine)
CREATE TABLE mytable (
    col1 INTEGER,
    col2 INTEGER,
    col3 INTEGER,
    col4 INTEGER,
    col5 INTEGER,
    col6 INTEGER
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)
CREATE UNIQUE INDEX ix_mytable_col2 ON mytable (col2)
CREATE UNIQUE INDEX myindex ON mytable (col5, col6)
CREATE INDEX idx_col34 ON mytable (col3, col4)

注意在上面的例子中, Index 构造是在它对应的表外部创建的,使用 Column 直接对象。 Index 还支持在 Table ,使用字符串名称标识列::

metadata_obj = MetaData()
mytable = Table('mytable', metadata_obj,
    Column('col1', Integer),

    Column('col2', Integer),

    Column('col3', Integer),
    Column('col4', Integer),

    # place an index on col1, col2
    Index('idx_col12', 'col1', 'col2'),

    # place a unique index on col3, col4
    Index('idx_col34', 'col3', 'col4', unique=True)
)

这个 Index 对象还支持其自身 create() 方法:

i = Index('someindex', mytable.c.col5)
sqli.create(engine)
CREATE INDEX someindex ON mytable (col5)

功能指标

Index 支持SQL和函数表达式,目标后端支持。要使用降序值针对列创建索引,请 ColumnElement.desc() 可使用修饰符:

from sqlalchemy import Index

Index('someindex', mytable.c.somecol.desc())

或者,如果后端支持PostgreSQL等功能索引,则可以使用 lower() 功能:

from sqlalchemy import func, Index

Index('someindex', func.lower(mytable.c.somecol))

索引API

Object NameDescription

Index

表级索引。

class sqlalchemy.schema.Index(name, *expressions, **kw)

表级索引。

定义复合(一列或多列)索引。

例如。::

sometable = Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100))
            )

Index("some_index", sometable.c.name)

对于无虚饰,单列索引,添加 Column 也支持 index=True ::

sometable = Table("sometable", metadata,
                Column("name", String(50), index=True)
            )

对于复合索引,可以指定多个列::

Index("some_index", sometable.c.name, sometable.c.address)

也支持函数索引,通常使用 func 与表绑定一起构造 Column 物体::

Index("some_index", func.lower(sometable.c.name))

Index 也可以手动与 Table ,通过内联声明或使用 Table.append_constraint() . 使用此方法时,可以将索引列的名称指定为字符串::

Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100)),
                Index("some_index", "name", "address")
        )

要支持此表单中的函数索引或基于表达式的索引,请 text() 可使用构造:

from sqlalchemy import text

Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100)),
                Index("some_index", text("lower(name)"))
        )

0.9.5 新版功能: 这个 text() 构造可用于指定 Index 表达式,前提是 IndexTable .

参见

索引 -一般信息 Index .

PostgreSQL特定索引选项 -PostgreSQL特定选项可用于 Index 构造。

MySQL/MariaDB-特定索引选项 -mysql特定选项可用于 Index 构造。

聚集索引支持 -可用于 Index 构造。

类签名

class sqlalchemy.schema.Index (sqlalchemy.sql.base.DialectKWArgs, sqlalchemy.schema.ColumnCollectionMixin, sqlalchemy.schema.SchemaItem)

method sqlalchemy.schema.Index.__init__(name, *expressions, **kw)

构造索引对象。

参数
  • name -- 索引的名称

  • *expressions -- 要包含在索引中的列表达式。表达式通常是 Column ,但也可能是最终引用 Column .

  • unique=False -- 仅关键字参数;如果为true,则创建唯一索引。

  • quote=None -- 仅关键字参数;是否对索引名称应用引号。工作方式与 Column.quote .

  • info=None -- 可选数据字典,将填充到 SchemaItem.info 此对象的属性。…添加的版本:1.0.0

  • **kw -- 上面未提到的其他关键字参数是特定于方言的,并以形式传递 <dialectname>_<argname> . 有关单个方言的文档,请参见 方言 有关文档化参数的详细信息。

method sqlalchemy.schema.Index.classmethod argument_for(dialect_name, argument_name, default)

inherited from the DialectKWArgs.argument_for() method of DialectKWArgs

为此类添加一种新的方言特定关键字参数。

例如。::

Index.argument_for("mydialect", "length", None)

some_index = Index('a', 'b', mydialect_length=5)

这个 DialectKWArgs.argument_for() 方法是按参数向 DefaultDialect.construct_arguments 字典。此字典提供了各种模式级构造代表方言接受的参数名列表。

新方言通常应同时将此字典指定为方言类的数据成员。临时添加参数名的用例通常用于最终用户代码,该代码也使用自定义编译方案,该方案使用附加参数。

参数
  • dialect_name -- 方言的名称。方言必须可定位,否则 NoSuchModuleError 提高了。方言还必须包括现有的 DefaultDialect.construct_arguments 集合,指示它参与关键字参数验证和默认系统,否则 ArgumentError 提高了。如果方言不包含此集合,则可以代表此方言指定任何关键字参数。包含在sqlAlchemy中的所有方言都包含此集合,但是对于第三方方言,支持可能有所不同。

  • argument_name -- 参数的名称。

  • default -- 参数的默认值。

0.9.4 新版功能.

attribute sqlalchemy.schema.Index.bind

返回与此索引关联的可连接项。

method sqlalchemy.schema.Index.create(bind=None, checkfirst=False)

发行A CREATE 声明 Index ,使用给定的 Connectable 用于连接。

参见

MetaData.create_all() .

attribute sqlalchemy.schema.Index.dialect_kwargs

inherited from the DialectKWArgs.dialect_kwargs attribute of DialectKWArgs

指定为此构造的方言特定选项的关键字参数集合。

这些论据以原版呈现在这里。 <dialect>_<kwarg> 格式。只包括实际传递的参数;与 DialectKWArgs.dialect_options 集合,其中包含此方言已知的所有选项,包括默认值。

集合也是可写的;接受窗体的键 <dialect>_<kwarg> 值将组合到选项列表中。

0.9.2 新版功能.

在 0.9.4 版更改: 这个 DialectKWArgs.dialect_kwargs 集合现在可写。

参见

DialectKWArgs.dialect_options -嵌套字典窗体

attribute sqlalchemy.schema.Index.dialect_options

inherited from the DialectKWArgs.dialect_options attribute of DialectKWArgs

指定为此构造的方言特定选项的关键字参数集合。

这是一个两级嵌套注册表,键控为 <dialect_name><argument_name> . 例如, postgresql_where 参数可定位为:

arg = my_object.dialect_options['postgresql']['where']

0.9.2 新版功能.

参见

DialectKWArgs.dialect_kwargs -平字典形式

method sqlalchemy.schema.Index.drop(bind=None, checkfirst=False)

发行A DROP 声明 Index ,使用给定的 Connectable 用于连接。

参见

MetaData.drop_all() .

method sqlalchemy.schema.Index.get_children(omit_attrs=(), **kw)

inherited from the Traversible.get_children() method of Traversible

返回直接子对象 Traversible 这其中的要素 Traversible

这用于访问遍历。

**kw可能包含更改返回的集合的标志,例如,返回项的子集以减少更大的遍历,或者从不同的上下文返回子项(例如模式级集合而不是子句级集合)。

attribute sqlalchemy.schema.Index.info

inherited from the SchemaItem.info attribute of SchemaItem

与对象关联的信息字典,允许用户定义的数据与此关联 SchemaItem .

字典在第一次访问时自动生成。它也可以在一些对象的构造函数中指定,例如 TableColumn .

attribute sqlalchemy.schema.Index.kwargs

inherited from the DialectKWArgs.kwargs attribute of DialectKWArgs

同义词 DialectKWArgs.dialect_kwargs .