SqlAlchemy 2.0 中文文档(四十)

2024-08-21 16:17:17 浏览数 (2)

原文:docs.sqlalchemy.org/en/20/contents.html

列的插入/更新默认值

原文:docs.sqlalchemy.org/en/20/core/defaults.html

列的插入和更新默认值是指在针对该行进行插入或更新语句时,为该列创建默认值的函数,前提是对该列的插入或更新语句未提供任何值。也就是说,如果一个表有一个名为“timestamp”的列,并且进行了不包含该列值的插入语句,那么插入默认值将创建一个新值,例如当前时间,该值将用作要插入到“timestamp”列的值。如果语句包含该列的值,则默认值会发生。

列默认值可以是服务器端函数或与数据库中的架构一起定义的常量值,在 DDL 中,或者作为 SQLAlchemy 直接在 INSERT 或 UPDATE 语句中呈现的 SQL 表达式;它们也可以是由 SQLAlchemy 在将数据传递到数据库之前调用的客户端 Python 函数或常量值。

注意

列默认处理程序不应与拦截和修改传递给语句的插入和更新语句中的值的构造混淆。这称为数据编组,在这里,在将列值发送到数据库之前,应用程序以某种方式修改列值。SQLAlchemy 提供了几种实现这一点的方法,包括使用自定义数据类型、SQL 执行事件以及 ORM 中的自定义验证器以及属性事件。列默认值仅在 SQL DML 语句中的某一列没有值时调用。

SQLAlchemy 提供了一系列关于在插入和更新语句中针对不存在的值进行默认生成函数的特性。选项包括:

  • 插入和更新操作中用作默认值的标量值
  • 在插入和更新操作中执行的 Python 函数
  • 嵌入到插入语句中的 SQL 表达式(或在某些情况下提前执行的表达式)
  • 嵌入到更新语句中的 SQL 表达式
  • 插入时使用的服务器端默认值
  • 用于更新时的服务器端触发器的标记

所有插入/更新默认值的一般规则是,只有当某一列的值未作为execute()参数传递时,它们才会生效;否则,将使用给定的值。

标量默认值

最简单的默认值是用作列的默认值的标量值:

代码语言:javascript复制
Table("mytable", metadata_obj, Column("somecolumn", Integer, default=12))

在上述情况下,如果没有提供其他值,则“12”将绑定为插入时的列值。

标量值也可以与 UPDATE 语句关联,但这不是很常见(因为 UPDATE 语句通常正在寻找动态默认值):

代码语言:javascript复制
Table("mytable", metadata_obj, Column("somecolumn", Integer, onupdate=25))

Python 执行的函数

Column.defaultColumn.onupdate 关键字参数也接受 Python 函数。如果没有为该列提供其他值,则在插入或更新时调用这些函数,并且返回的值将用于列的值。下面说明了一个简单的“序列”,它将递增的计数器分配给主键列:

代码语言:javascript复制
# a function which counts upwards
i = 0

def mydefault():
    global i
    i  = 1
    return i

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True, default=mydefault),
)

应该注意,对于真正的“递增序列”行为,通常应使用数据库的内置功能,这可能包括序列对象或其他自动增量功能。对于主键列,SQLAlchemy 在大多数情况下将自动使用这些功能。请参阅关于 Column 的 API 文档,包括 Column.autoincrement 标志,以及本章后面关于 Sequence 的部分,了解标准主键生成技术的背景。

为了说明 onupdate,我们将 Python 的 datetime 函数 now 赋值给 Column.onupdate 属性:

代码语言:javascript复制
import datetime

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    # define 'last_updated' to be populated with datetime.now()
    Column("last_updated", DateTime, onupdate=datetime.datetime.now),
)

当执行更新语句并且没有为 last_updated 传递值时,将执行 datetime.datetime.now() Python 函数,并将其返回值用作 last_updated 的值。请注意,我们将 now 提供为函数本身而不是调用它(即后面没有括号) - SQLAlchemy 将在语句执行时执行该函数。

上下文敏感的默认函数

Column.defaultColumn.onupdate 使用的 Python 函数也可以利用当前语句的上下文来确定一个值。语句的上下文是一个内部的 SQLAlchemy 对象,它包含有关正在执行的语句的所有信息,包括其源表达式、与之关联的参数和游标。与默认生成相关的上下文的典型用例是访问正在插入或更新的行上的其他值。要访问上下文,请提供一个接受单个 context 参数的函数:

代码语言:javascript复制
def mydefault(context):
    return context.get_current_parameters()["counter"]   12

t = Table(
    "mytable",
    metadata_obj,
    Column("counter", Integer),
    Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)

上述默认生成函数适用于所有 INSERT 和 UPDATE 语句,其中未提供 counter_plus_twelve 的值,其值将是执行 counter 列的值加上数字 12。

对于使用“executemany”样式执行的单个语句,例如传递给 Connection.execute() 的多个参数集,用户定义的函数将为每组参数集调用一次。对于多值 Insert 构造的用例(例如通过 Insert.values() 方法设置了多个 VALUES 子句),用户定义的函数也将为每组参数集调用一次。

当调用该函数时,上下文对象(DefaultExecutionContext 的子类)中可用特殊方法 DefaultExecutionContext.get_current_parameters()。该方法返回一个列键到值的字典,表示 INSERT 或 UPDATE 语句的完整值集。在多值 INSERT 构造的情况下,与单个 VALUES 子句对应的参数子集被从完整参数字典中隔离并单独返回。

新版本 1.2 中:添加了 DefaultExecutionContext.get_current_parameters() 方法,它通过提供将多个 VALUES 子句组织成单独参数字典的服务,改进了仍然存在的 DefaultExecutionContext.current_parameters 属性。## 客户端调用的 SQL 表达式

Column.defaultColumn.onupdate 关键字还可以传递 SQL 表达式,大多数情况下,这些表达式将在 INSERT 或 UPDATE 语句中直接呈现。

代码语言:javascript复制
t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    # define 'create_date' to default to now()
    Column("create_date", DateTime, default=func.now()),
    # define 'key' to pull its default from the 'keyvalues' table
    Column(
        "key",
        String(20),
        default=select(keyvalues.c.key).where(keyvalues.c.type="type1"),
    ),
    # define 'last_modified' to use the current_timestamp SQL function on update
    Column("last_modified", DateTime, onupdate=func.utc_timestamp()),
)

在上面的例子中,create_date 列将在插入语句中使用 now() SQL 函数的结果填充(根据后端的不同,在大多数情况下编译为 NOW()CURRENT_TIMESTAMP),而 key 列将使用另一个表的 SELECT 子查询的结果填充。当为该表发出更新语句时,last_modified 列将填充为 SQL UTC_TIMESTAMP() MySQL 函数的值。

注意

在使用 func 构造与 SQL 函数时,我们“调用”命名函数,例如在 func.now() 中使用括号。这与当我们将 Python 可调用对象指定为默认值时不同,例如 datetime.datetime,在这种情况下,我们传递函数本身,但我们自己不调用它。对于 SQL 函数,调用 func.now() 返回将“NOW”函数渲染到正在发射的 SQL 中的 SQL 表达式对象。

Column.defaultColumn.onupdate 指定的默认值和更新 SQL 表达式在插入或更新语句发生时由 SQLAlchemy 明确调用,通常在 DML 语句中内联渲染,除了下面列出的特定情况。这与“服务器端”默认值不同,后者是表的 DDL 定义的一部分,例如作为“CREATE TABLE”语句的一部分,这种情况可能更常见。对于服务器端默认值,请参阅下一节 Server-invoked DDL-Explicit Default Expressions。

当通过 Column.default 指示的 SQL 表达式与主键列一起使用时,存在一些情况下,SQLAlchemy 必须“预执行”默认生成 SQL 函数,这意味着它在单独的 SELECT 语句中被调用,并且生成的值作为参数传递给 INSERT。这仅发生在要求返回此主键值的 INSERT 语句的主键列上,其中不能使用 RETURNING 或 cursor.lastrowid。指定了 insert.inline 标志的 Insert 构造将始终内联渲染默认表达式。

当语句使用单个参数集执行时(即不是“executemany”样式的执行),返回的CursorResult将包含通过CursorResult.postfetch_cols()可访问的集合,该集合包含所有具有内联执行默认值的Column对象的列表。同样,语句绑定的所有参数,包括预先执行的所有 Python 和 SQL 表达式,都存在于CursorResult.last_inserted_params()CursorResult.last_updated_params()集合中的CursorResult上。CursorResult.inserted_primary_key集合包含插入行的主键值列表(列表格式,以便单列和复合列主键以相同的格式表示)。 ## 服务器调用的 DDL-显式默认表达式

SQL 表达式默认值的变体是Column.server_default,在Table.create()操作期间会放置在 CREATE TABLE 语句中:

代码语言:javascript复制
t = Table(
    "test",
    metadata_obj,
    Column("abc", String(20), server_default="abc"),
    Column("created_at", DateTime, server_default=func.sysdate()),
    Column("index_value", Integer, server_default=text("0")),
)

对于上述表格的创建调用将产生:

代码语言:javascript复制
CREATE  TABLE  test  (
  abc  varchar(20)  default  'abc',
  created_at  datetime  default  sysdate,
  index_value  integer  default  0
)

上面的示例说明了Column.server_default的两种典型用例,即 SQL 函数(在上面的示例中为 SYSDATE)以及服务器端常量值(在上面的示例中为整数“0”)。建议对任何文字 SQL 值使用text()构造,而不是传递原始值,因为 SQLAlchemy 通常不会对这些值执行任何引号添加或转义。

与客户端生成的表达式类似,Column.server_default可以适应一般的 SQL 表达式,但通常预期这些将是简单的函数和表达式,而不是像嵌入式 SELECT 这样更复杂的情况。 ## 标记隐式生成的值、时间戳和触发列

列在插入或更新时基于其他服务器端数据库机制生成新值,例如某些平台上的时间戳列所见的数据库特定的自动生成行为,以及在插入或更新时调用的自定义触发器生成新值,可以使用FetchedValue作为标记:

代码语言:javascript复制
from sqlalchemy.schema import FetchedValue

t = Table(
    "test",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("abc", TIMESTAMP, server_default=FetchedValue()),
    Column("def", String(20), server_onupdate=FetchedValue()),
)

FetchedValue 指示符不会影响 CREATE TABLE 的渲染 DDL。相反,它标记列将在 INSERT 或 UPDATE 语句的过程中由数据库填充新值,并且对于支持的数据库,可以用于指示该列应该是 RETURNING 或 OUTPUT 子句的一部分。诸如 SQLAlchemy ORM 之类的工具随后利用此标记以了解如何在此类操作之后获取列的值。特别是,ValuesBase.return_defaults() 方法可与InsertUpdate 构造一起使用,以指示应返回这些值。

有关在 ORM 中使用FetchedValue 的详细信息,请参阅获取服务器生成的默认值。

警告

Column.server_onupdate 指令目前不会生成 MySQL 的“ON UPDATE CURRENT_TIMESTAMP()”子句。请参阅为 MySQL / MariaDB 的 explicit_defaults_for_timestamp 渲染 ON UPDATE CURRENT TIMESTAMP 了解如何生成此子句的背景信息。

另请参阅

获取服务器生成的默认值 ## 定义序列

SQLAlchemy 使用Sequence 对象表示数据库序列,被视为“列默认值”的特例。它仅对显式支持序列的数据库产生影响,其中包括 PostgreSQL、Oracle、MS SQL Server 和 MariaDB 在内的 SQLAlchemy 包含的方言。否则,Sequence 对象将被忽略。

提示

在较新的数据库引擎中,应该优先使用Identity 构造而不是Sequence 生成整数主键值。请参阅 Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY) 了解此构造的背景信息。

Sequence可以放置在任何列上作为“默认”生成器,在 INSERT 操作期间使用,并且如果需要,还可以配置为在 UPDATE 操作期间触发。它最常与单个整数主键列一起使用:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        Sequence("cart_id_seq", start=1),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上述情况中,表cartitems与名为cart_id_seq的序列相关联。对上述表执行MetaData.create_all()将包括:

代码语言:javascript复制
CREATE  SEQUENCE  cart_id_seq  START  WITH  1

CREATE  TABLE  cartitems  (
  cart_id  INTEGER  NOT  NULL,
  description  VARCHAR(40),
  createdate  TIMESTAMP  WITHOUT  TIME  ZONE,
  PRIMARY  KEY  (cart_id)
)

提示

当使用具有显式模式名称的表时(详见指定模式名称),Table的配置模式不会自动与嵌入的Sequence共享,而是需要指定Sequence.schema

代码语言:javascript复制
Sequence("cart_id_seq", start=1, schema="some_schema")

Sequence还可以自动使用正在使用的MetaData中的MetaData.schema设置;有关背景,请参阅将序列与 MetaData 关联。

当针对cartitems表调用Insert DML 构造时,如果未传递cart_id列的显式值,则将使用cart_id_seq序列在参与的后端生成值。通常,序列函数被嵌入到 INSERT 语句中,与 RETURNING 结合使用,以便将新生成的值返回给 Python 进程:

代码语言:javascript复制
INSERT  INTO  cartitems  (cart_id,  description,  createdate)
VALUES  (next_val(cart_id_seq),  'some description',  '2015-10-15 12:00:15')
RETURNING  cart_id

当使用Connection.execute()调用Insert构造时,包括但不限于使用Sequence生成的新生成的主键标识符,可通过CursorResult构造的CursorResult.inserted_primary_key属性获取。

SequenceColumn作为其Python 端默认生成器关联时,Sequence也将受到“CREATE SEQUENCE”和“DROP SEQUENCE” DDL 的影响,当为拥有的Table发出类似 DDL 时,比如使用MetaData.create_all()为一系列表生成 DDL 时。

Sequence也可以直接与MetaData构造关联。这允许Sequence同时用于多个Table,并且还允许继承MetaData.schema参数。请参见将序列与 MetaData 关联部分了解背景信息。

在 SERIAL 列上关联序列

PostgreSQL 的 SERIAL 数据类型是一个自增类型,意味着在发出 CREATE TABLE 时隐式创建一个 PostgreSQL 序列。当为Column指定Sequence构造时,可以通过为Sequence.optional参数指定True的值来指示在这种特定情况下不应使用它。这允许给定的Sequence用于没有其他主键生成系统的后端,但在后端(如 PostgreSQL)中会自动生成特定列的序列时忽略它:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        # use an explicit Sequence where available, but not on
        # PostgreSQL where SERIAL will be used
        Sequence("cart_id_seq", start=1, optional=True),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上面的示例中,对于 PostgreSQL 的CREATE TABLE将使用SERIAL数据类型来创建cart_id列,而cart_id_seq序列将被忽略。然而在 Oracle 上,cart_id_seq序列将被显式创建。

提示

SERIAL 和 SEQUENCE 的这种特定交互相当传统,就像其他情况一样,使用Identity将简化操作,只需在所有支持的后端上使用IDENTITY即可。

单独执行序列

SEQUENCE 是 SQL 中的一类一流模式对象,可用于独立生成数据库中的值。如果有一个Sequence对象,可以通过直接将其传递给 SQL 执行方法来调用其“next value”指令:

代码语言:javascript复制
with my_engine.connect() as conn:
    seq = Sequence("some_sequence", start=1)
    nextid = conn.execute(seq)

为了将Sequence的“next value”函数嵌入 SQL 语句(如 SELECT 或 INSERT)中,使用Sequence.next_value()方法,在语句编译时会生成适用于目标后端的 SQL 函数:

代码语言:javascript复制
>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT  nextval('some_sequence')  AS  next_value_1 
将序列与 MetaData 关联

对于要与任意Table对象关联的Sequence,可以使用Sequence.metadata参数将Sequence与特定的MetaData关联:

代码语言:javascript复制
seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)

这样的序列可以按照通常的方式与列关联:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    seq,
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上面的示例中,Sequence对象被视为独立的模式构造,可以独立存在或在表之间共享。

明确将SequenceMetaData关联允许以下行为:

  • Sequence将继承目标MetaData指定的MetaData.schema参数,这会影响 CREATE / DROP DDL 的生成以及Sequence.next_value()函数在 SQL 语句中的呈现方式。
  • MetaData.create_all()MetaData.drop_all() 方法将发出 CREATE / DROP 命令,即使此 Sequence 没有与任何属于此 MetaDataTable / Column 关联。
将序列关联为服务器端默认值

注意

以下技术仅已知适用于 PostgreSQL 数据库。它不适用于 Oracle。

上文说明了如何将 Sequence 关联到 Column 作为 Python 端的默认生成器

代码语言:javascript复制
Column(
    "cart_id",
    Integer,
    Sequence("cart_id_seq", metadata=metadata_obj, start=1),
    primary_key=True,
)

在上述情况下,当相关的 Table 被创建 / 删除时,Sequence 将自动受到 CREATE SEQUENCE / DROP SEQUENCE DDL 的影响。然而,当发出 CREATE TABLE 时,该序列不会作为列的服务器端默认值存在。

如果我们希望序列被用作服务器端默认值,即使我们从 SQL 命令行向表发出 INSERT 命令,它也会生效,我们可以使用 Column.server_default 参数与序列的值生成函数一起使用,该函数可从 Sequence.next_value() 方法中获得。下面我们展示了相同的 SequenceColumn 关联,既作为 Python 端的默认生成器,也作为服务器端的默认生成器:

代码语言:javascript复制
cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        cart_id_seq,
        server_default=cart_id_seq.next_value(),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

或者使用 ORM:

代码语言:javascript复制
class CartItem(Base):
    __tablename__ = "cartitems"

    cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
    cart_id = Column(
        Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
    )
    description = Column(String(40))
    createdate = Column(DateTime)

当发出“CREATE TABLE”语句时,在 PostgreSQL 上,它将被表述为:

代码语言:javascript复制
CREATE  TABLE  cartitems  (
  cart_id  INTEGER  DEFAULT  nextval('cart_id_seq')  NOT  NULL,
  description  VARCHAR(40),
  createdate  TIMESTAMP  WITHOUT  TIME  ZONE,
  PRIMARY  KEY  (cart_id)
)

在 Python 端和服务器端默认生成上下文中放置Sequence可确保“主键获取”逻辑在所有情况下都能正常工作。通常,支持序列的数据库也支持 INSERT 语句的 RETURNING,当发出此语句时,SQLAlchemy 会自动使用。但是,如果对于特定的插入操作不使用 RETURNING,则 SQLAlchemy 更倾向于在 INSERT 语句之外“预执行”序列,这仅在将序列包含为 Python 端默认生成函数时才有效。

该示例还直接将Sequence与封闭的MetaData关联,这再次确保SequenceMetaData集合的参数完全关联,包括默认模式(如果有)。

另请参阅

Sequences/SERIAL/IDENTITY - 在 PostgreSQL 方言文档中

RETURNING 支持 - 在 Oracle 方言文档中 ## 计算列 (GENERATED ALWAYS AS)

版本 1.3.11 中的新功能。

Computed 构造允许在 DDL 中声明一个“GENERATED ALWAYS AS”列的Column,即一个由数据库服务器计算值的列。该构造接受一个 SQL 表达式,通常使用字符串或text()构造进行文本声明,类似于CheckConstraint的方式。然后数据库服务器解释 SQL 表达式以确定行内列的值。

示例:

代码语言:javascript复制
from sqlalchemy import Table, Column, MetaData, Integer, Computed

metadata_obj = MetaData()

square = Table(
    "square",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("side", Integer),
    Column("area", Integer, Computed("side * side")),
    Column("perimeter", Integer, Computed("4 * side")),
)

在 PostgreSQL 12 后端运行时,square 表的 DDL 如下所示:

代码语言:javascript复制
CREATE  TABLE  square  (
  id  SERIAL  NOT  NULL,
  side  INTEGER,
  area  INTEGER  GENERATED  ALWAYS  AS  (side  *  side)  STORED,
  perimeter  INTEGER  GENERATED  ALWAYS  AS  (4  *  side)  STORED,
  PRIMARY  KEY  (id)
)

值在 INSERT 和 UPDATE 时是否持久化,或者在获取时是否计算,是数据库的实现细节;前者称为“stored”,后者称为“virtual”。一些数据库实现支持两者,但有些只支持其中一个。可以指定可选的Computed.persisted标志为 TrueFalse,以指示在 DDL 中是否应该呈现“STORED”或“VIRTUAL”关键字,但是如果目标后端不支持该关键字,则会引发错误;如果不设置,将为目标后端使用一个有效的默认值。

Computed 构造是 FetchedValue 对象的子类,将自己设置为目标 Column 的“服务器默认值”和“服务器更新”生成器,这意味着在生成 INSERT 和 UPDATE 语句时,它将被视为默认生成列,并且在使用 ORM 时将被作为生成列获取。这包括在数据库支持 RETURNING 且要急切地获取生成值时,它将成为数据库的 RETURNING 子句的一部分。

注意

使用 Computed 构造定义的 Column 可能不会存储除服务器应用于其外的任何值; 当为此类列传递值以在 INSERT 或 UPDATE 中写入时,SQLAlchemy 的行为目前是忽略该值。

“GENERATED ALWAYS AS” 目前已知受到支持的数据库有:

  • MySQL 版本 5.7 及更高版本
  • MariaDB 10.x 系列及更高版本
  • PostgreSQL 版本 12 及更高版本
  • Oracle - 值得注意的是,RETURNING 在 UPDATE 中不正确地工作(当包含计算列的 UPDATE…RETURNING 被渲染时,会发出此警告)
  • Microsoft SQL Server
  • SQLite 版本 3.31

Computed 与不受支持的后端一起使用时,如果目标方言不支持它,则在尝试渲染构造时会引发 CompileError。否则,如果方言支持它但正在使用的特定数据库服务器版本不支持它,则在将 DDL 发送到数据库时会引发 DBAPIError 的子类,通常是 OperationalError

另请参阅

Computed ## 标识列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)

版本 1.4 中新增。

Identity 构造允许将 Column 声明为标识列,并在 DDL 中渲染为 “GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”。标识列的值是由数据库服务器自动使用递增(或递减)序列生成的。该构造与 Sequence 共享控制数据库行为的大多数选项。

示例:

代码语言:javascript复制
from sqlalchemy import Table, Column, MetaData, Integer, Identity, String

metadata_obj = MetaData()

data = Table(
    "data",
    metadata_obj,
    Column("id", Integer, Identity(start=42, cycle=True), primary_key=True),
    Column("data", String),
)

在 PostgreSQL 12 后端运行时,data 表的 DDL 如下所示:

代码语言:javascript复制
CREATE  TABLE  data  (
  id  INTEGER  GENERATED  BY  DEFAULT  AS  IDENTITY  (START  WITH  42  CYCLE)  NOT  NULL,
  data  VARCHAR,
  PRIMARY  KEY  (id)
)

数据库将在插入时为 id 列生成值,从 42 开始,如果语句中尚未包含 id 列的值。标识列还可以要求数据库生成列的值,忽略语句中传递的值或引发错误,具体取决于后端。要激活此模式,请在 Identity 构造中将参数 Identity.always 设置为 True。更新前面的示例以包含此参数将生成以下 DDL:

代码语言:javascript复制
CREATE  TABLE  data  (
  id  INTEGER  GENERATED  ALWAYS  AS  IDENTITY  (START  WITH  42  CYCLE)  NOT  NULL,
  data  VARCHAR,
  PRIMARY  KEY  (id)
)

Identity 构造是 FetchedValue 对象的子类,并且将自身设置为目标 Column 的“服务器默认”生成器,这意味着当生成 INSERT 语句时,它将被视为默认生成列,以及在使用 ORM 时,它将被作为生成列提取。这包括对于支持 RETURNING 的数据库,它将成为 RETURNING 子句的一部分,并且生成的值将被急切地提取。

目前已知支持 Identity 构造的数据库有:

  • PostgreSQL 版本为 10。
  • Oracle 版本为 12。 还支持传递 always=None 以启用默认生成模式,并传递参数 on_null=True 以指定在使用 “BY DEFAULT” 标识列时“ON NULL”。
  • Microsoft SQL Server。 MSSQL 使用自定义语法,仅支持 startincrement 参数,并忽略所有其他参数。

当与不受支持的后端一起使用时,Identity 将被忽略,并且将使用默认的 SQLAlchemy 逻辑自动递增列。

Column 同时指定 Identity 并将 Column.autoincrement 设置为 False 时,会引发错误。

另请参阅

Identity

默认对象 API

对象名称

描述

ColumnDefault

列的普通默认值。

Computed

定义生成列,即“GENERATED ALWAYS AS”语法。

DefaultClause

由 DDL 指定的默认列值。

DefaultGenerator

列 默认 值的基类。

FetchedValue

用于透明数据库端默认值的标记。

Identity

定义标识列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。

Sequence

表示命名的数据库序列。

代码语言:javascript复制
class sqlalchemy.schema.Computed

定义一个生成列,即“GENERATED ALWAYS AS”语法。

Computed 构造是一个内联构造,添加到 Column 对象的参数列表中:

代码语言:javascript复制
from sqlalchemy import Computed

Table('square', metadata_obj,
    Column('side', Float, nullable=False),
    Column('area', Float, Computed('side * side'))
)

详细信息请参阅下面链接的文档。

新于版本 1.3.11。

请参阅

计算列(GENERATED ALWAYS AS)

成员

init(), copy()

类签名

sqlalchemy.schema.Computedsqlalchemy.schema.FetchedValuesqlalchemy.schema.SchemaItem

代码语言:javascript复制
method __init__(sqltext: _DDLColumnArgument, persisted: bool | None = None) → None

构造一个 GENERATED ALWAYS AS DDL 构造,以配合 Column

参数:

  • sqltext – 包含列生成表达式的字符串,该表达式将直接使用,或者是一个 SQL 表达式构造,比如text()对象。如果以字符串形式给出,则将该对象转换为text()对象。 警告 传递给ComputedComputed.sqltext参数可以作为 Python 字符串参数传递,它将被视为受信任的 SQL 文本并按给定方式呈现。请勿将不受信任的输入传递给此参数
  • persisted – 可选,控制该列在数据库中的持久化方式。可能的值包括:
    • None,默认值,它将使用数据库定义的默认持久化方式。
    • True,将呈现 GENERATED ALWAYS AS ... STORED,或者如果目标数据库支持的话,将呈现等效值。
    • False,将呈现 GENERATED ALWAYS AS ... VIRTUAL,或者如果目标数据库支持的话,将呈现等效值。

    如果数据库不支持该持久化选项,则指定 TrueFalse 可能会在将 DDL 发出到目标数据库时引发错误。将此参数保留为其默认值None 保证在所有支持 GENERATED ALWAYS AS 的数据库上都可以成功。

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → Computed

自版本 1.4 起已弃用:Computed.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
class sqlalchemy.schema.ColumnDefault

列上的纯默认值。

这可能对应于一个常量、一个可调用函数或一个 SQL 子句。

ColumnDefaultColumndefaultonupdate 参数被使用时会自动生成。一个 ColumnDefault 也可以作为位置参数传递。

例如,以下内容:

代码语言:javascript复制
Column('foo', Integer, default=50)

等价于:

代码语言:javascript复制
Column('foo', Integer, ColumnDefault(50))

类签名

sqlalchemy.schema.ColumnDefaultsqlalchemy.schema.DefaultGeneratorabc.ABC

代码语言:javascript复制
class sqlalchemy.schema.DefaultClause

DDL 指定的 DEFAULT 列值。

DefaultClause 是一个 FetchedValue,当发出 “CREATE TABLE” 时也会生成一个“DEFAULT”子句。

Columnserver_defaultserver_onupdate 参数被使用时,DefaultClause 会自动生成。一个 DefaultClause 也可以作为位置参数传递。

例如,以下内容:

代码语言:javascript复制
Column('foo', Integer, server_default="50")

等价于:

代码语言:javascript复制
Column('foo', Integer, DefaultClause("50"))

类签名

sqlalchemy.schema.DefaultClausesqlalchemy.schema.FetchedValue

代码语言:javascript复制
class sqlalchemy.schema.DefaultGenerator

列默认值的基类。

此对象仅出现在 column.default 或 column.onupdate。它不能作为服务器默认值有效。

类签名

sqlalchemy.schema.DefaultGeneratorsqlalchemy.sql.expression.Executablesqlalchemy.schema.SchemaItem

代码语言:javascript复制
class sqlalchemy.schema.FetchedValue

用于透明数据库端默认值的标记。

当数据库配置为为列提供一些自动默认值时,请使用 FetchedValue

例如:

代码语言:javascript复制
Column('foo', Integer, FetchedValue())

将指示某个触发器或默认生成器在 INSERT 期间为 foo 列创建一个新值。

另请参阅

标记隐式生成的值、时间戳和触发列

类签名

sqlalchemy.schema.FetchedValuesqlalchemy.sql.expression.SchemaEventTarget

代码语言:javascript复制
class sqlalchemy.schema.Sequence

表示一个命名的数据库序列。

Sequence 对象表示数据库序列的名称和配置参数。它还表示一个可以被 SQLAlchemy EngineConnection “执行”的结构,为目标数据库渲染适当的“下一个值”函数并返回结果。

Sequence 通常与主键列关联:

代码语言:javascript复制
some_table = Table(
    'some_table', metadata,
    Column('id', Integer, Sequence('some_table_seq', start=1),
    primary_key=True)
)

当为上述 Table 发射 CREATE TABLE 时,如果目标平台支持序列,则也会发射 CREATE SEQUENCE 语句。对于不支持序列的平台,将忽略 Sequence 构造。

另请参阅

定义序列

CreateSequence

DropSequence

成员

init(), create(), drop(), next_value()

类签名

sqlalchemy.schema.Sequence (sqlalchemy.schema.HasSchemaAttr, sqlalchemy.schema.IdentityOptions, sqlalchemy.schema.DefaultGenerator)

代码语言:javascript复制
method __init__(name: str, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, schema: str | Literal[SchemaConst.BLANK_SCHEMA] | None = None, cache: int | None = None, order: bool | None = None, data_type: _TypeEngineArgument[int] | None = None, optional: bool = False, quote: bool | None = None, metadata: MetaData | None = None, quote_schema: bool | None = None, for_update: bool = False) → None

构建一个 Sequence 对象。

参数:

  • name – 序列的名称。
  • start – 开始索引。 序列的起始索引。在将 CREATE SEQUENCE 命令发射到数据库时,此值被用作“START WITH”子句的值。如果为 None,则省略该子句,大多数平台上表示起始值为 1。 从版本 2.0 开始更改:要求 Sequence.start 参数以发射 DDL “START WITH”。这是在版本 1.4 中进行的一项更改的反转,该更改如果未包括 Sequence.start 将隐式渲染“START WITH 1”。有关更多详细信息,请参阅 序列结构还原为没有任何显式默认“开始”值;影响 MS SQL Server。
  • increment – 序列的增量值。在将 CREATE SEQUENCE 命令发射到数据库时,此值被用作“INCREMENT BY”子句的值。如果为 None,则省略该子句,大多数平台上表示增量为 1。
  • minvalue – 序列的最小值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“MINVALUE”子句的值。如果为 None,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和 -2⁶³-1。
  • maxvalue – 序列的最大值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“MAXVALUE”子句的值。如果为 None,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和 -1。
  • nominvalue – 序列没有最小值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“NO MINVALUE”子句的值。如果为 None,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和 -2⁶³-1。
  • nomaxvalue – 序列没有最大值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“NO MAXVALUE”子句的值。如果为 None,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和 -1。
  • cycle – 当升序或降序序列达到最大值或最小值时,允许序列环绕。当向数据库发出 CREATE SEQUENCE 命令时,此值用作“CYCLE”子句。如果达到限制,则下一个生成的数字将是最小值或最大值,分别是升序或降序。如果 cycle=False(默认值),在序列达到其最大值后,任何对 nextval 的调用都将返回错误。
  • schema – 序列的可选模式名称,如果位于默认模式之外的模式中。当 MetaData 也存在时,选择模式名称的规则与 Table.schema 相同。
  • cache – 可选整数值;提前计算序列中的未来值的数量。呈现 Oracle 和 PostgreSQL 可理解的 CACHE 关键字。
  • order – 可选布尔值;如果为 True,则呈现 ORDER 关键字,Oracle 可理解,表示序列是有序的。可能需要使用 Oracle RAC 提供确定性排序。
  • data_type – 序列返回的类型,适用于允许我们在 INTEGER、BIGINT 等之间进行选择的方言(例如,mssql)。 新版本 1.4.0 中新增。
  • optional – 布尔值,当为 True 时,表示此 Sequence 对象只需在没有其他方法生成主键标识符的后端上显式生成。目前,这实际上意味着,“在 PostgreSQL 后端上不要创建此序列,因为 SERIAL 关键字会自动为我们创建序列”。
  • quote – 布尔值,当为 TrueFalse 时,明确地强制引用 Sequence.name 的名称,打开或关闭。当保留其默认值 None 时,基于大小写和保留字的常规引用规则生效。
  • quote_schema – 设置对 schema 名称的引用首选项。
  • metadata – 可选的 MetaData 对象,此 Sequence 将与之关联。与 MetaData 关联的 Sequence 具有以下功能:
    • Sequence 将继承指定给目标 MetaDataMetaData.schema 参数,这会影响 CREATE / DROP DDL 的生成(如果有)。
    • Sequence.create()Sequence.drop() 方法会自动使用绑定到 MetaData 对象的引擎(如果有)。
    • MetaData.create_all()MetaData.drop_all() 方法将为此 Sequence 发出 CREATE / DROP,即使此 Sequence 未与此 MetaData 的任何成员 Table / Column 关联。

    上述行为只有在通过此参数将 Sequence 明确关联到 MetaData 时才会发生。 另请参阅 将序列与 MetaData 关联 - 关于Sequence.metadata参数的详细讨论。

  • for_update – 表示当与Column关联时,此Sequence应在该列的表上进行 UPDATE 语句调用,而不是在该语句中否则在该列中没有值。
代码语言:javascript复制
method create(bind: _CreateDropBind, checkfirst: bool = True) → None

在数据库中创建此序列。

代码语言:javascript复制
method drop(bind: _CreateDropBind, checkfirst: bool = True) → None

从数据库中删除此序列。

代码语言:javascript复制
method next_value() → Function[int]

返回一个next_value函数元素,该函数将为此Sequence在任何 SQL 表达式中呈现适当的增量函数。

代码语言:javascript复制
class sqlalchemy.schema.Identity

定义一个标识列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。

Identity结构是添加到Column对象的参数列表中的内联结构:

代码语言:javascript复制
from sqlalchemy import Identity

Table('foo', metadata_obj,
    Column('id', Integer, Identity())
    Column('description', Text),
)

请参阅下面链接的文档以获取完整详情。

从版本 1.4 开始新增。

另请参阅

标识列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)

成员

init(), copy()

类签名

sqlalchemy.schema.Identitysqlalchemy.schema.IdentityOptionssqlalchemy.schema.FetchedValuesqlalchemy.schema.SchemaItem

代码语言:javascript复制
method __init__(always: bool = False, on_null: bool | None = None, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, cache: int | None = None, order: bool | None = None) → None

创建一个 DDL 结构GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY,用于配合Column

请参阅Sequence文档,了解大多数参数的完整描述。

注意

MSSQL 支持此结构作为在列上生成 IDENTITY 的首选替代方案,但它使用的非标准语法仅支持Identity.startIdentity.increment。所有其他参数都会被忽略。

参数:

  • always – 一个布尔值,表示标识列的类型。如果指定了False,则默认情况下用户指定的值优先。如果指定了True,则不接受用户指定的值(在某些后端,如 PostgreSQL,可以在插入时指定 OVERRIDING SYSTEM VALUE 或类似语句以覆盖序列值)。某些后端也对此参数有默认值,None可以用于在 DDL 中省略渲染此部分。如果后端没有默认值,则将其视为False
  • on_null – 设置为True以与always=False标识列一起指定 ON NULL。此选项仅在某些后端(如 Oracle)上受支持。
  • start – 序列的起始索引。
  • increment – 序列的增量值。
  • minvalue – 序列的最小值。
  • maxvalue – 序列的最大值。
  • nominvalue – 序列的最小值不存在。
  • nomaxvalue – 序列的最大值不存在。
  • cycle – 当达到最大值或最小值时允许序列循环。
  • cache – 可选的整数值;提前计算的序列中未来值的数量。
  • order – 可选的布尔值;如果为 true,则呈现 ORDER 关键字。
代码语言:javascript复制
method copy(**kw: Any) → Identity

自版本 1.4 起已弃用:Identity.copy()方法已弃用,将在将来的版本中移除。

标量默认值

最简单的默认值是作为列默认值使用的标量值:

代码语言:javascript复制
Table("mytable", metadata_obj, Column("somecolumn", Integer, default=12))

上述,如果未提供其他值,则值“12”将在插入时绑定为列值。

标量值也可能与 UPDATE 语句关联,尽管这不是很常见(因为 UPDATE 语句通常寻找动态默认值):

代码语言:javascript复制
Table("mytable", metadata_obj, Column("somecolumn", Integer, onupdate=25))

Python 执行的函数

Column.defaultColumn.onupdate关键字参数也接受 Python 函数。如果未提供该列的其他值,则在插入或更新时调用这些函数,并使用返回的值作为列的值。以下示例说明了一个粗糙的“序列”,将递增计数器分配给主键列:

代码语言:javascript复制
# a function which counts upwards
i = 0

def mydefault():
    global i
    i  = 1
    return i

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True, default=mydefault),
)

应该注意,对于真正的“增量序列”行为,通常应该使用数据库的内置功能,这可能包括序列对象或其他自增能力。对于主键列,SQLAlchemy 在大多数情况下将自动使用这些功能。请参阅Column的 API 文档,包括Column.autoincrement标志,以及本章后面关于Sequence的部分,了解标准主键生成技术的背景。

为了说明 onupdate,我们将 Python 的datetime函数now赋值给Column.onupdate属性:

代码语言:javascript复制
import datetime

t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    # define 'last_updated' to be populated with datetime.now()
    Column("last_updated", DateTime, onupdate=datetime.datetime.now),
)

当执行更新语句并且未传递last_updated值时,将执行datetime.datetime.now() Python 函数,并将其返回值用作last_updated的值。请注意,我们将now作为函数本身提供,而不调用它(即后面没有括号)- SQLAlchemy 将在执行语句时执行该函数。

上下文敏感的默认函数

Column.defaultColumn.onupdate使用的 Python 函数也可以利用当前语句上下文来确定值。语句的上下文是一个内部的 SQLAlchemy 对象,包含有关正在执行的语句的所有信息,包括其源表达式、与之关联的参数和游标。在默认生成的上下文中,典型的用例是访问正在插入或更新的行上的其他值。要访问上下文,请提供一个接受单个context参数的函数:

代码语言:javascript复制
def mydefault(context):
    return context.get_current_parameters()["counter"]   12

t = Table(
    "mytable",
    metadata_obj,
    Column("counter", Integer),
    Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)

上述默认生成函数是这样应用的:它将用于所有未提供counter_plus_twelve值的 INSERT 和 UPDATE 语句,并且该值将是执行counter列时的任何值加上 12 的值。

对于使用“executemany”样式执行的单个语句,例如通过Connection.execute()传递多个参数集的情况,用户定义的函数将为每组参数集调用一次。对于多值Insert结构的用例(例如通过Insert.values()方法设置了多个 VALUES 子句),用户定义的函数也将为每组参数集调用一次。

当函数被调用时,上下文对象(DefaultExecutionContext的一个子类)中可用的特殊方法DefaultExecutionContext.get_current_parameters()。此方法返回一个字典,其中键-值对表示 INSERT 或 UPDATE 语句的完整值集。在多值 INSERT 结构的情况下,与单个 VALUES 子句对应的参数子集将从完整参数字典中隔离并单独返回。

1.2 版中的新功能:增加了DefaultExecutionContext.get_current_parameters()方法,它改进了仍然存在的DefaultExecutionContext.current_parameters属性,通过提供将多个 VALUES 子句组织成单独参数字典的服务。### 上下文敏感的默认函数

Column.defaultColumn.onupdate使用的 Python 函数还可以利用当前语句的上下文来确定一个值。语句的上下文是一个内部的 SQLAlchemy 对象,其中包含关于正在执行的语句的所有信息,包括其源表达式、与之关联的参数和游标。与默认生成相关的此上下文的典型用例是访问要插入或更新的行上的其他值。要访问上下文,请提供一个接受单个context参数的函数:

代码语言:javascript复制
def mydefault(context):
    return context.get_current_parameters()["counter"]   12

t = Table(
    "mytable",
    metadata_obj,
    Column("counter", Integer),
    Column("counter_plus_twelve", Integer, default=mydefault, onupdate=mydefault),
)

上述默认生成函数被应用于所有 INSERT 和 UPDATE 语句,其中未提供counter_plus_twelve的值,并且该值将为执行counter列时存在的任何值加上 12。

对于使用“executemany”风格执行的单个语句,例如向 Connection.execute() 传递多个参数集的情况,用户定义的函数会为每个参数集调用一次。对于多值 Insert 结构的用例(例如通过 Insert.values() 方法设置了多个 VALUES 子句),用户定义的函数也会为每个参数集调用一次。

当函数被调用时,上下文对象(DefaultExecutionContext的子类)中可用特殊方法DefaultExecutionContext.get_current_parameters()。该方法返回一个字典,列键到值的映射,表示 INSERT 或 UPDATE 语句的完整值集。对于多值 INSERT 结构的情况,与单个 VALUES 子句对应的参数子集被从完整参数字典中隔离并单独返回。

1.2 版本中新增:增加了 DefaultExecutionContext.get_current_parameters() 方法,它改进了仍然存在的 DefaultExecutionContext.current_parameters 属性,提供了将多个 VALUES 子句组织成单独参数字典的服务。

客户端调用的 SQL 表达式

也可以传递 SQL 表达式给 Column.defaultColumn.onupdate 关键字,这在大多数情况下会在 INSERT 或 UPDATE 语句中内联呈现:

代码语言:javascript复制
t = Table(
    "mytable",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    # define 'create_date' to default to now()
    Column("create_date", DateTime, default=func.now()),
    # define 'key' to pull its default from the 'keyvalues' table
    Column(
        "key",
        String(20),
        default=select(keyvalues.c.key).where(keyvalues.c.type="type1"),
    ),
    # define 'last_modified' to use the current_timestamp SQL function on update
    Column("last_modified", DateTime, onupdate=func.utc_timestamp()),
)

在上述情况中,create_date列将在 INSERT 语句期间填充 now() SQL 函数的结果(在大多数情况下,根据后端编译为 NOW()CURRENT_TIMESTAMP),而 key 列将填充另一张表的 SELECT 子查询的结果。当为此表发出 UPDATE 语句时,last_modified 列将填充 SQL UTC_TIMESTAMP() MySQL 函数的值。

注意

使用func构造和 SQL 函数时,我们会“调用”命名函数,例如在 func.now() 中使用括号。这与当我们将 Python 可调用对象(例如 datetime.datetime)指定为默认值时不同,其中我们传递函数本身,但我们不自己调用它。对于 SQL 函数,调用func.now()将返回将“NOW”函数呈现为正在发出的 SQL 中的 SQL 表达式对象。

当发生 INSERT 或 UPDATE 语句时,SQLAlchemy 在 Column.defaultColumn.onupdate 指定的默认和更新 SQL 表达式明确调用它们,通常在 DML 语句中内联渲染,除了下面列出的某些情况。这与“服务器端”默认值不同,后者是表的 DDL 定义的一部分,例如作为“CREATE TABLE”语句的一部分,这可能更常见。有关服务器端默认值,请参阅下一节服务器调用 DDL-显式默认表达式。

当由Column.default指示的 SQL 表达式与主键列一起使用时,有些情况下 SQLAlchemy 必须“预先执行”默认生成的 SQL 函数,这意味着它在单独的 SELECT 语句中被调用,并且生成的值作为参数传递给 INSERT。这仅发生在主键列为 INSERT 语句被要求返回该主键值的情况下,其中不能使用 RETURNING 或 cursor.lastrowid。指定了insert.inline标志的 Insert 构造将始终将默认表达式呈现为内联。

当执行语句使用单一参数集合(即不是“executemany”风格执行)时,返回的CursorResult将包含一个可通过CursorResult.postfetch_cols()访问的集合,其中包含所有具有内联执行默认值的Column对象的列表。同样,绑定到语句的所有参数,包括所有预先执行的 Python 和 SQL 表达式,都存在于CursorResult.last_inserted_params()CursorResult.last_updated_params()集合中的CursorResultCursorResult.inserted_primary_key集合包含插入的行的主键值列表(列表使得单列和复合列主键以相同格式表示)。

服务器调用的 DDL 显式默认表达式

SQL 表达式默认的一种变体是Column.server_default,在Table.create()操作期间会被放置在 CREATE TABLE 语句中:

代码语言:javascript复制
t = Table(
    "test",
    metadata_obj,
    Column("abc", String(20), server_default="abc"),
    Column("created_at", DateTime, server_default=func.sysdate()),
    Column("index_value", Integer, server_default=text("0")),
)

对上述表的创建调用将产生:

代码语言:javascript复制
CREATE  TABLE  test  (
  abc  varchar(20)  default  'abc',
  created_at  datetime  default  sysdate,
  index_value  integer  default  0
)

上述示例说明了Column.server_default的两种典型用法,即 SQL 函数(上述示例中的 SYSDATE)以及服务器端常量值(上述示例中的整数“0”)。建议对任何文字 SQL 值使用text()构造,而不是传递原始值,因为 SQLAlchemy 通常不对这些值执行任何引用或转义。

与客户端生成的表达式类似,Column.server_default可以容纳一般的 SQL 表达式,但是预期这些通常会是简单的函数和表达式,而不是更复杂的情况,比如嵌套的 SELECT。

标记隐式生成的值、时间戳和触发列

当插入或更新时,基于其他服务器端数据库机制生成新值的列,例如在某些平台上与时间戳列一起看到的数据库特定的自动生成行为,以及在插入或更新时调用的自定义触发器以生成新值,可以使用FetchedValue作为标记:

代码语言:javascript复制
from sqlalchemy.schema import FetchedValue

t = Table(
    "test",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("abc", TIMESTAMP, server_default=FetchedValue()),
    Column("def", String(20), server_onupdate=FetchedValue()),
)

FetchedValue 指示器不会影响 CREATE TABLE 的渲染 DDL。相反,它标记了在 INSERT 或 UPDATE 语句的过程中由数据库填充新值的列,并且对于支持的数据库,可能会用于指示该列应该是 RETURNING 或 OUTPUT 子句的一部分。然后,诸如 SQLAlchemy ORM 之类的工具使用此标记来了解如何获取此类操作后列的值。特别是,可以使用ValuesBase.return_defaults()方法与InsertUpdate构造来指示应返回这些值。

有关使用 ORM 中的FetchedValue的详细信息,请参阅获取服务器生成的默认值。

警告

Column.server_onupdate 指令目前不会生成 MySQL 的“ON UPDATE CURRENT_TIMESTAMP()”子句。有关如何生成此子句的背景信息,请参阅为 MySQL / MariaDB 的 explicit_defaults_for_timestamp 渲染 ON UPDATE CURRENT TIMESTAMP。

另请参阅

获取服务器生成的默认值

定义序列

SQLAlchemy 使用Sequence对象表示数据库序列,这被认为是“列默认值”的特殊情况。它仅对具有对序列的明确支持的数据库产生影响,其中包括 SQLAlchemy 包含的方言中的 PostgreSQL、Oracle、MS SQL Server 和 MariaDB。否则,Sequence对象将被忽略。

提示

在较新的数据库引擎中,应该优先使用Identity构造生成整数主键值,而不是Sequence。有关此构造的背景信息,请参阅 Identity Columns (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)。

Sequence可以放置在任何列上作为“默认”生成器,在 INSERT 操作期间使用,并且如果需要,还可以配置在 UPDATE 操作期间触发。它通常与单个整数主键列一起使用:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        Sequence("cart_id_seq", start=1),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上述情况下,表cartitems与名为cart_id_seq的序列相关联。发出上述表的MetaData.create_all()将包括:

代码语言:javascript复制
CREATE  SEQUENCE  cart_id_seq  START  WITH  1

CREATE  TABLE  cartitems  (
  cart_id  INTEGER  NOT  NULL,
  description  VARCHAR(40),
  createdate  TIMESTAMP  WITHOUT  TIME  ZONE,
  PRIMARY  KEY  (cart_id)
)

提示

当使用具有显式模式名称的表(详细信息请参阅指定模式名称)时,Table的配置模式不会自动由嵌入的Sequence共享,而是需要指定Sequence.schema:

代码语言:javascript复制
Sequence("cart_id_seq", start=1, schema="some_schema")

Sequence也可以自动使用正在使用的MetaData的设置中的MetaData.schema;有关背景信息,请参阅将序列与 MetaData 关联。

当针对cartitems表调用Insert DML 构造时,如果没有为cart_id列传递显式值,则cart_id_seq序列将用于在参与的后端生成一个值。通常,序列函数嵌入在 INSERT 语句中,与 RETURNING 结合在一起,以便新生成的值可以返回给 Python 进程:

代码语言:javascript复制
INSERT  INTO  cartitems  (cart_id,  description,  createdate)
VALUES  (next_val(cart_id_seq),  'some description',  '2015-10-15 12:00:15')
RETURNING  cart_id

当使用Connection.execute()来调用Insert构造时,包括但不限于使用Sequence生成的新生成的主键标识符,可以通过CursorResult构造使用CursorResult.inserted_primary_key属性获得。

当将 Sequence 关联到 Column 作为其 Python-side 默认生成器时,当为拥有 Table 发出类似 DDL 的情况下,例如使用 MetaData.create_all() 为一系列表生成 DDL 时,该 Sequence 也将受到 “CREATE SEQUENCE” 和 “DROP SEQUENCE” DDL 的约束。

Sequence 也可以直接与 MetaData 构造关联。这允许 Sequence 在多个 Table 中同时使用,并且还允许继承 MetaData.schema 参数。有关详情,请参见 将序列与元数据关联 部分。

在 SERIAL 列上关联一个序列

PostgreSQL 的 SERIAL 数据类型是一种自增类型,意味着在发出 CREATE TABLE 命令时隐式创建了一个 PostgreSQL 序列。当为 Column 指定了 Sequence 构造时,可以通过将 Sequence.optional 参数的值设置为 True 来指示在这种特定情况下不应使用它。这允许给定的 Sequence 用于没有其他替代主键生成系统的后端,但对于自动为特定列生成序列的后端(例如 PostgreSQL),可以忽略它:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        # use an explicit Sequence where available, but not on
        # PostgreSQL where SERIAL will be used
        Sequence("cart_id_seq", start=1, optional=True),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上面的示例中,对于 PostgreSQL,CREATE TABLE 将使用 SERIAL 数据类型来创建 cart_id 列,并且 cart_id_seq 序列将被忽略。然而在 Oracle 中,cart_id_seq 序列将被显式创建。

提示

SERIAL 和 SEQUENCE 的这种特定交互在相当程度上是遗留的,在其他情况下,使用 Identity 将简化操作,只需在所有支持的后端上使用 IDENTITY 即可。

执行一个独立的序列

SEQUENCE 是 SQL 中的一种一流模式对象,可用于在数据库中独立生成值。如果有 Sequence 对象,可以通过直接将其传递给 SQL 执行方法来调用其“next value”指令:

代码语言:javascript复制
with my_engine.connect() as conn:
    seq = Sequence("some_sequence", start=1)
    nextid = conn.execute(seq)

为了将 Sequence 的“next value”函数嵌入到类似于 SELECT 或 INSERT 的 SQL 语句中,可以使用 Sequence.next_value() 方法,该方法将在语句编译时生成适用于目标后端的 SQL 函数:

代码语言:javascript复制
>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT  nextval('some_sequence')  AS  next_value_1 
将序列与 MetaData 关联

对于将与任意 Table 对象关联的 Sequence,可以使用 Sequence.metadata 参数将 Sequence 关联到特定的 MetaData

代码语言:javascript复制
seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)

然后可以以通常的方式将这样的序列与列关联起来:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    seq,
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上面的示例中,Sequence 对象被视为独立的模式构造,可以独立存在或在表之间共享。

明确将 SequenceMetaData 关联允许以下行为:

  • Sequence 将继承指定给目标 MetaDataMetaData.schema 参数,这影响了 CREATE / DROP DDL 的生成以及 SQL 语句中 Sequence.next_value() 函数的呈现方式。
  • MetaData.create_all()MetaData.drop_all() 方法将发出 CREATE / DROP 用于此 Sequence,即使该 Sequence 未与任何此 MetaData 的成员 Table / Column 相关联。
将序列关联为服务器端默认值

注意

以下技术仅在 PostgreSQL 数据库中有效,不适用于 Oracle。

前面的部分说明了如何将 SequenceColumn 关联为Python 端默认生成器

代码语言:javascript复制
Column(
    "cart_id",
    Integer,
    Sequence("cart_id_seq", metadata=metadata_obj, start=1),
    primary_key=True,
)

在上述情况下,当相关的 Table 被 CREATE / DROP 时,Sequence 将自动受到 CREATE SEQUENCE / DROP SEQUENCE DDL 的影响。但是,当发出 CREATE TABLE 时,该序列不会作为列的服务器端默认值存在。

如果我们希望序列被用作服务器端默认值,即使我们从 SQL 命令行向表中发出 INSERT 命令,我们可以使用 Column.server_default 参数与序列的值生成函数一起使用,该函数可以从 Sequence.next_value() 方法中获取。下面我们将演示相同的 Sequence 作为 Python 端默认生成器以及服务器端默认生成器与 Column 相关联的情况:

代码语言:javascript复制
cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        cart_id_seq,
        server_default=cart_id_seq.next_value(),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

或者使用 ORM:

代码语言:javascript复制
class CartItem(Base):
    __tablename__ = "cartitems"

    cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
    cart_id = Column(
        Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
    )
    description = Column(String(40))
    createdate = Column(DateTime)

当发出“CREATE TABLE”语句时,在 PostgreSQL 上,它将被生成为:

代码语言:javascript复制
CREATE  TABLE  cartitems  (
  cart_id  INTEGER  DEFAULT  nextval('cart_id_seq')  NOT  NULL,
  description  VARCHAR(40),
  createdate  TIMESTAMP  WITHOUT  TIME  ZONE,
  PRIMARY  KEY  (cart_id)
)

在 Python 端和服务器端默认生成上下文中放置 Sequence 确保“主键获取”逻辑在所有情况下都能正常工作。通常,启用序列的数据库还支持 INSERT 语句的 RETURNING,当发出此语句时,SQLAlchemy 会自动使用它。但是,如果对于特定的插入未使用 RETURNING,则 SQLAlchemy 更愿意在 INSERT 语句本身之外“预先执行”序列,只有在将序列作为 Python 端默认生成函数包含时才能正常工作。

该示例还将 Sequence 直接与封闭的 MetaData 关联起来,这再次确保 Sequence 完全与 MetaData 集合的参数相关联,包括默认模式(如果有)。

另请参阅

序列/SERIAL/IDENTITY - 在 PostgreSQL 方言文档中

返回支持 - 在 Oracle 方言文档中

将序列关联到 SERIAL 列

PostgreSQL 的 SERIAL 数据类型是一种自增类型,它意味着在发出 CREATE TABLE 时会隐式创建一个 PostgreSQL 序列。当为 Column 指定 Sequence 构造时,可以通过为 Sequence.optional 参数指定 True 值来表明在这种特定情况下不应使用它。这允许给定的 Sequence 用于没有其他替代主键生成系统的后端,但对于诸如 PostgreSQL 之类的后端,它会自动生成一个特定列的序列:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        # use an explicit Sequence where available, but not on
        # PostgreSQL where SERIAL will be used
        Sequence("cart_id_seq", start=1, optional=True),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上面的例子中,对于 PostgreSQL 的 CREATE TABLE 将使用 SERIAL 数据类型来创建 cart_id 列,而 cart_id_seq 序列将被忽略。然而,在 Oracle 中,cart_id_seq 序列将被显式创建。

提示

SERIAL 和 SEQUENCE 的这种特定交互相当古老,与其他情况一样,改用 Identity 将简化操作,只需在所有支持的后端上使用 IDENTITY 即可。

单独执行序列

SEQUENCE 是 SQL 中的一级模式对象,并且可以在数据库中独立生成值。如果你有一个 Sequence 对象,可以直接将其传递给 SQL 执行方法,通过其“next value”指令来调用它:

代码语言:javascript复制
with my_engine.connect() as conn:
    seq = Sequence("some_sequence", start=1)
    nextid = conn.execute(seq)

为了将 Sequence 的“next value”函数嵌入到类似 SELECT 或 INSERT 的 SQL 语句中,可以使用 Sequence.next_value() 方法,该方法将在语句编译时生成适合目标后端的 SQL 函数:

代码语言:javascript复制
>>> my_seq = Sequence("some_sequence", start=1)
>>> stmt = select(my_seq.next_value())
>>> print(stmt.compile(dialect=postgresql.dialect()))
SELECT  nextval('some_sequence')  AS  next_value_1 
将 Sequence 与 MetaData 关联起来

对于要与任意 Table 对象关联的 Sequence,可以使用 Sequence.metadata 参数将 Sequence 关联到特定的 MetaData

代码语言:javascript复制
seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)

这样的序列可以按照通常的方式与列关联起来:

代码语言:javascript复制
table = Table(
    "cartitems",
    metadata_obj,
    seq,
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

在上面的例子中,Sequence 对象被视为一个独立的模式构造,可以独立存在或在表之间共享。

显式地将 SequenceMetaData 关联起来,可以实现以下行为:

  • Sequence 会继承指定给目标 MetaDataMetaData.schema 参数,这会影响 CREATE / DROP DDL 的生成,以及 Sequence.next_value() 函数在 SQL 语句中的呈现方式。
  • MetaData.create_all()MetaData.drop_all() 方法将为此 Sequence 发出 CREATE / DROP,即使该 Sequence 未与此 MetaData 的任何成员 Table / Column 关联。
将 Sequence 关联为服务器端默认

注意

以下技术仅在 PostgreSQL 数据库中可用。它在 Oracle 中不起作用。

前面的部分演示了如何将 Sequence 关联到 Column 作为Python 端默认生成器

代码语言:javascript复制
Column(
    "cart_id",
    Integer,
    Sequence("cart_id_seq", metadata=metadata_obj, start=1),
    primary_key=True,
)

在上述情况下,当相关的 Table 要被创建 / 删除时,Sequence 将自动受到 CREATE SEQUENCE / DROP SEQUENCE DDL 的影响。但是,在发出 CREATE TABLE 时,该序列不会出现为该列的服务器端默认。

如果我们希望序列被用作服务器端默认,即使我们从 SQL 命令行向表中发出 INSERT 命令,我们可以使用 Column.server_default 参数,与序列的值生成函数一起使用,该函数可以从 Sequence.next_value() 方法获得。下面我们演示了相同的 Sequence 同时关联到 Column,既作为 Python 端的默认生成器,又作为服务器端的默认生成器:

代码语言:javascript复制
cart_id_seq = Sequence("cart_id_seq", metadata=metadata_obj, start=1)
table = Table(
    "cartitems",
    metadata_obj,
    Column(
        "cart_id",
        Integer,
        cart_id_seq,
        server_default=cart_id_seq.next_value(),
        primary_key=True,
    ),
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

或使用 ORM:

代码语言:javascript复制
class CartItem(Base):
    __tablename__ = "cartitems"

    cart_id_seq = Sequence("cart_id_seq", metadata=Base.metadata, start=1)
    cart_id = Column(
        Integer, cart_id_seq, server_default=cart_id_seq.next_value(), primary_key=True
    )
    description = Column(String(40))
    createdate = Column(DateTime)

在发出“CREATE TABLE”语句时,在 PostgreSQL 上会发出:

代码语言:javascript复制
CREATE  TABLE  cartitems  (
  cart_id  INTEGER  DEFAULT  nextval('cart_id_seq')  NOT  NULL,
  description  VARCHAR(40),
  createdate  TIMESTAMP  WITHOUT  TIME  ZONE,
  PRIMARY  KEY  (cart_id)
)

在 Python 端和服务器端默认生成上下文中放置Sequence可以确保“主键提取”逻辑在所有情况下都有效。 通常,启用序列的数据库也支持对 INSERT 语句使用 RETURNING,当发出此语句时,SQLAlchemy 会自动使用它。 但是,如果对特定插入未使用 RETURNING,则 SQLAlchemy 更愿意在 INSERT 语句本身之外“预执行”序列,这仅在序列作为 Python 端默认生成器函数时有效。

该示例还将Sequence直接与封闭的MetaData关联起来,这再次确保了SequenceMetaData集合的参数完全关联,包括默认模式(如果有)。

另请参阅

序列/SERIAL/IDENTITY - 在 PostgreSQL 方言文档中

RETURNING 支持 - 在 Oracle 方言文档中

计算列(GENERATED ALWAYS AS)

1.3.11 版中新增。

Computed 构造允许将 Column 声明为“GENERATED ALWAYS AS”列,在 DDL 中,即由数据库服务器计算值的列。 该构造接受一个 SQL 表达式,通常使用字符串或 text() 构造进行文本声明,类似于 CheckConstraint 的方式。 然后,数据库服务器会解释该 SQL 表达式,以确定行内列的值。

示例:

代码语言:javascript复制
from sqlalchemy import Table, Column, MetaData, Integer, Computed

metadata_obj = MetaData()

square = Table(
    "square",
    metadata_obj,
    Column("id", Integer, primary_key=True),
    Column("side", Integer),
    Column("area", Integer, Computed("side * side")),
    Column("perimeter", Integer, Computed("4 * side")),
)

在 PostgreSQL 12 后端上运行 square 表的 DDL 如下所示:

代码语言:javascript复制
CREATE  TABLE  square  (
  id  SERIAL  NOT  NULL,
  side  INTEGER,
  area  INTEGER  GENERATED  ALWAYS  AS  (side  *  side)  STORED,
  perimeter  INTEGER  GENERATED  ALWAYS  AS  (4  *  side)  STORED,
  PRIMARY  KEY  (id)
)

值是在 INSERT 和 UPDATE 时持久化,还是在获取时计算,是数据库的实现细节;前者称为“存储”,后者称为“虚拟”。 一些数据库实现支持两者,但有些只支持其中一个。 可以指定可选的 Computed.persisted 标志为 TrueFalse,以指示是否在 DDL 中渲染“STORED”或“VIRTUAL”关键字,但是如果目标后端不支持该关键字,则会引发错误; 如果将其设置为未设置,则将使用目标后端的有效默认值。

计算列 构造是 FetchedValue 对象的子类,并且会自行设置为目标 的“服务器默认值”和“服务器更新时生成器”,这意味着当生成 INSERT 和 UPDATE 语句时,它将被视为默认生成的列,以及当使用 ORM 时,它将被视为生成的列被获取。这包括它将作为数据库的 RETURNING 子句的一部分,对于支持 RETURNING 并且生成的值需要被急切地获取的数据库。

使用 计算列 构造定义的 可能不会存储除服务器应用之外的任何值;当尝试写入 INSERT 或 UPDATE 时,SQLAlchemy 目前的行为是将忽略该值。

“GENERATED ALWAYS AS” 目前已知受支持的数据库有:

  • MySQL 版本 5.7 及以上
  • MariaDB 10.x 系列及以上
  • PostgreSQL 版本 12 及以上
  • Oracle - 注意 RETURNING 在 UPDATE 中无法正常工作(在包含计算列的 UPDATE…RETURNING 被呈现时会发出警告)
  • Microsoft SQL Server
  • SQLite 版本 3.31 及以上

计算列 与不受支持的后端一起使用时,如果目标方言不支持它,则在尝试呈现构造时会引发 CompileError。否则,如果方言支持它但使用的特定数据库服务器版本不支持它,则在将 DDL 发送到数据库时会引发 DBAPIError 的子类,通常是 OperationalError

请参见

计算列

自增列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)

1.4 版本中新增。

Identity 构造允许将 声明为自增列,并在 DDL 中呈现为“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”。自增列的值由数据库服务器自动生成,使用增量(或减量)序列。该构造与 Sequence 共享大部分用于控制数据库行为的选项。

示例:

代码语言:javascript复制
from sqlalchemy import Table, Column, MetaData, Integer, Identity, String

metadata_obj = MetaData()

data = Table(
    "data",
    metadata_obj,
    Column("id", Integer, Identity(start=42, cycle=True), primary_key=True),
    Column("data", String),
)

在 PostgreSQL 12 后端上运行时,data 表的 DDL 如下所示:

代码语言:javascript复制
CREATE  TABLE  data  (
  id  INTEGER  GENERATED  BY  DEFAULT  AS  IDENTITY  (START  WITH  42  CYCLE)  NOT  NULL,
  data  VARCHAR,
  PRIMARY  KEY  (id)
)

数据库将在插入时为 id 列生成一个值,从 42 开始,如果语句尚未包含 id 列的值。身份列也可以要求数据库生成列的值,忽略语句中传递的值或者根据后端引发错误。要激活此模式,请在 Identity 构造函数中将参数 Identity.always 设置为 True。将上一个示例更新以包含此参数将生成以下 DDL:

代码语言:javascript复制
CREATE  TABLE  data  (
  id  INTEGER  GENERATED  ALWAYS  AS  IDENTITY  (START  WITH  42  CYCLE)  NOT  NULL,
  data  VARCHAR,
  PRIMARY  KEY  (id)
)

Identity 构造函数是 FetchedValue 对象的子类,并将自己设置为目标 Column 的“服务器默认”生成器,这意味着当生成 INSERT 语句时,它将被视为默认生成列,以及在使用 ORM 时,它将被视为生成列。这包括它将作为数据库的 RETURNING 子句的一部分,对于支持 RETURNING 并且要急切获取生成的值的数据库来说,它将被提前获取。

当前已知支持 Identity 构造函数的包括:

  • PostgreSQL 版本为 10。
  • Oracle 版本为 12. 还支持传递 always=None 以启用默认生成模式,以及传递参数 on_null=True 以指定“ON NULL”与“BY DEFAULT”身份列一起使用。
  • Microsoft SQL Server. MSSQL 使用一种自定义语法,仅支持 startincrement 参数,而忽略所有其他参数。

Identity 与不受支持的后端一起使用时,它会被忽略,并且会使用默认的 SQLAlchemy 自增列逻辑。

Column 同时指定 Identity 并将 Column.autoincrement 设置为 False 时,将引发错误。

另请参阅

Identity

默认对象 API

对象名称

描述

ColumnDefault

列的普通默认值。

Computed

定义了一个生成的列,即“GENERATED ALWAYS AS”语法。

DefaultClause

由 DDL 指定的 DEFAULT 列值。

DefaultGenerator

用于列默认值的基类。

FetchedValue

透明数据库端默认值的标记。

Identity

定义标识列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。

Sequence

表示命名的数据库序列。

代码语言:javascript复制
class sqlalchemy.schema.Computed

定义一个生成列,即“GENERATED ALWAYS AS”语法。

Computed构造是添加到Column对象的参数列表中的内联构造:

代码语言:javascript复制
from sqlalchemy import Computed

Table('square', metadata_obj,
    Column('side', Float, nullable=False),
    Column('area', Float, Computed('side * side'))
)

请参阅下面链接的文档以获取完整详细信息。

版本 1.3.11 中的新功能。

另请参阅

计算列(GENERATED ALWAYS AS)

成员

init(), copy()

类签名

sqlalchemy.schema.Computedsqlalchemy.schema.FetchedValuesqlalchemy.schema.SchemaItem)

代码语言:javascript复制
method __init__(sqltext: _DDLColumnArgument, persisted: bool | None = None) → None

构造一个生成的 DDL 构造,以配合Column

参数:

  • sqltext – 包含列生成表达式的字符串,该表达式将逐字使用,或者 SQL 表达式构造,例如text()对象。 如果以字符串形式给出,则将对象转换为text()对象。 警告 Computed.sqltext参数可以作为 Python 字符串参数传递给Computed,它将被视为受信任的 SQL 文本并按照给定的方式呈现。 不要将不受信任的输入传递给此参数
  • persisted – 可选,控制数据库如何持久化此列。 可能的值为:
    • None,默认值,将使用数据库定义的默认持久性。
    • True,将呈现GENERATED ALWAYS AS ... STORED,或者如果支持的话,将呈现目标数据库的等效值。
    • False,将呈现GENERATED ALWAYS AS ... VIRTUAL,或者如果支持的话,将呈现目标数据库的等效值。

    当 DDL 发出到目标数据库时,如果数据库不支持持久性选项,则指定TrueFalse可能会引发错误。 将此参数保留在其默认值None上可确保对所有支持GENERATED ALWAYS AS的数据库都能成功。

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → Computed

自版本 1.4 起已弃用:Computed.copy()方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
class sqlalchemy.schema.ColumnDefault

列上的普通默认值。

这可能对应于一个常量,一个可调用函数,或者一个 SQL 子句。

每当使用 Columndefaultonupdate 参数时,都会自动生成 ColumnDefaultColumnDefault 也可以按位置传递。

例如,以下内容:

代码语言:javascript复制
Column('foo', Integer, default=50)

等同于:

代码语言:javascript复制
Column('foo', Integer, ColumnDefault(50))

类签名

class sqlalchemy.schema.ColumnDefault (sqlalchemy.schema.DefaultGenerator, abc.ABC)

代码语言:javascript复制
class sqlalchemy.schema.DefaultClause

由 DDL 指定的 DEFAULT 列值。

DefaultClause 是一个 FetchedValue,在发出“CREATE TABLE”时也会生成一个“DEFAULT”子句。

每当使用 Columnserver_defaultserver_onupdate 参数时,都会自动生成 DefaultClauseDefaultClause 也可以按位置传递。

例如,以下内容:

代码语言:javascript复制
Column('foo', Integer, server_default="50")

等同于:

代码语言:javascript复制
Column('foo', Integer, DefaultClause("50"))

类签名

class sqlalchemy.schema.DefaultClause (sqlalchemy.schema.FetchedValue)

代码语言:javascript复制
class sqlalchemy.schema.DefaultGenerator

列默认值的基类。

此对象仅存在于 column.default 或 column.onupdate。它不作为服务器默认值有效。

类签名

class sqlalchemy.schema.DefaultGenerator (sqlalchemy.sql.expression.Executable, sqlalchemy.schema.SchemaItem)

代码语言:javascript复制
class sqlalchemy.schema.FetchedValue

一个用于透明数据库端默认值的标记。

当数据库配置为为列提供一些自动默认值时,请使用 FetchedValue

例如:

代码语言:javascript复制
Column('foo', Integer, FetchedValue())

将指示某个触发器或默认生成器在插入期间为 foo 列创建一个新值。

另请参阅

标记隐式生成的值、时间戳和触发列

类签名

class sqlalchemy.schema.FetchedValue (sqlalchemy.sql.expression.SchemaEventTarget)

代码语言:javascript复制
class sqlalchemy.schema.Sequence

表示一个命名的数据库序列。

Sequence 对象表示数据库序列的名称和配置参数。它还表示可以由 SQLAlchemy EngineConnection “执行”的构造,为目标数据库渲染适当的 “下一个值” 函数并返回结果。

Sequence 通常与主键列相关联:

代码语言:javascript复制
some_table = Table(
    'some_table', metadata,
    Column('id', Integer, Sequence('some_table_seq', start=1),
    primary_key=True)
)

当为上述 Table 发出 CREATE TABLE 时,如果目标平台支持序列,则还将发出 CREATE SEQUENCE 语句。对于不支持序列的平台,将忽略 Sequence 构造。

另请参阅

定义序列

CreateSequence

DropSequence

成员

init(), create(), drop(), next_value()

类签名

sqlalchemy.schema.Sequence (sqlalchemy.schema.HasSchemaAttr, sqlalchemy.schema.IdentityOptions, sqlalchemy.schema.DefaultGenerator)

代码语言:javascript复制
method __init__(name: str, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, schema: str | Literal[SchemaConst.BLANK_SCHEMA] | None = None, cache: int | None = None, order: bool | None = None, data_type: _TypeEngineArgument[int] | None = None, optional: bool = False, quote: bool | None = None, metadata: MetaData | None = None, quote_schema: bool | None = None, for_update: bool = False) → None

构造一个 Sequence 对象。

参数:

  • name – 序列的名称。
  • start – 序列的起始索引。当向数据库发出 CREATE SEQUENCE 命令时,此值用作 “START WITH” 子句的值。如果为 None,则省略子句,大多数平台上表示起始值为 1。 从版本 2.0 开始:要使 DDL 发出 “START WITH” 命令,Sequence.start 参数是必需的。这是对版本 1.4 中所做更改的逆转,该更改如果未包括 Sequence.start 将隐式地渲染 “START WITH 1”。有关更多详细信息,请参见序列构造将恢复为没有任何显式默认的“start”值;影响 MS SQL Server。
  • increment – 序列的增量值。当向数据库发出 CREATE SEQUENCE 命令时,此值用作 “INCREMENT BY” 子句的值。如果为 None,则省略子句,大多数平台上表示增量为 1。
  • minvalue – 序列的最小值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“MINVALUE”子句的值。如果为None,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和-2⁶³-1。
  • maxvalue – 序列的最大值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“MAXVALUE”子句的值。如果为None,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和-1。
  • nominvalue – 序列的无最小值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“NO MINVALUE”子句的值。如果为None,则省略该子句,在大多数平台上表示升序和降序序列的最小值分别为 1 和-2⁶³-1。
  • nomaxvalue – 序列的无最大值。当将 CREATE SEQUENCE 命令发送到数据库时,此值用作“NO MAXVALUE”子句的值。如果为None,则省略该子句,在大多数平台上表示升序和降序序列的最大值分别为 2⁶³-1 和-1。
  • cycle – 允许序列在达到最大值或最小值时循环。当升序或降序序列分别达到最大值或最小值时,此值用于在将 CREATE SEQUENCE 命令发送到数据库时作为“CYCLE”子句。如果达到限制,则生成的下一个数字将分别是最小值或最大值。如果 cycle=False(默认值),则在序列达到其最大值后调用 nextval 将返回错误。
  • schema – 序列的可选模式名称,如果位于除默认模式之外的模式中。当MetaData也存在时,选择模式名称的规则与Table.schema的规则相同。
  • cache – 可选的整数值;提前计算序列中未来值的数量。渲染 Oracle 和 PostgreSQL 理解的 CACHE 关键字。
  • order – 可选的布尔值;如果为True,则渲染 ORDER 关键字,Oracle 可理解此关键字,表示序列是有确定顺序的。可能需要使用 Oracle RAC 提供确定性排序。
  • data_type – 序列要返回的类型,对于允许我们在 INTEGER、BIGINT 等之间选择的方言(例如 mssql)。 自 1.4.0 版本新增。
  • optional – 布尔值,当为True时,表示这个Sequence对象只需在不提供其他方法生成主键标识符的后端上显式生成。目前,它基本上意味着“在 PostgreSQL 后端上不要创建这个序列,在那里,SERIAL 关键字会自动为我们创建一个序列”。
  • quote – 布尔值,当为TrueFalse时,显式地强制对 Sequence.name 进行引用或取消引用。当保持其默认值None时,将根据大小写和保留字规则进行正常的引用。
  • quote_schema – 设置对schema名称的引用偏好。
  • metadata – 可选的 MetaData 对象,这个Sequence将与之关联。与 MetaData 关联的 Sequence 将获得以下功能:
    • Sequence将继承指定给目标MetaDataMetaData.schema参数,这会影响创建/删除 DDL 的生成,如果有的话。
    • Sequence.create()Sequence.drop() 方法会自动使用绑定到 MetaData 对象的引擎(如果有的话)。
    • MetaData.create_all()MetaData.drop_all() 方法将为这个Sequence发出 CREATE / DROP,即使这个Sequence没有与任何属于这个MetaDataTable / Column相关联也是如此。

    上述行为只有在通过此参数将 Sequence 显式关联到 MetaData 时才会发生。 另请参见 将 Sequence 与 MetaData 关联 - 对Sequence.metadata参数的完整讨论。

  • for_update – 当与Column相关联时,表示应该在该列的表上对 UPDATE 语句调用此Sequence,而不是在 INSERT 语句中,当该列在语句中没有其他值时。
代码语言:javascript复制
method create(bind: _CreateDropBind, checkfirst: bool = True) → None

在数据库中创建此序列。

代码语言:javascript复制
method drop(bind: _CreateDropBind, checkfirst: bool = True) → None

从数据库中删除此序列。

代码语言:javascript复制
method next_value() → Function[int]

返回一个next_value函数元素,该函数将在任何 SQL 表达式中为此Sequence呈现适当的增量函数。

代码语言:javascript复制
class sqlalchemy.schema.Identity

定义一个 identity 列,即“GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY”语法。

Identity 构造是一个内联构造,添加到Column对象的参数列表中:

代码语言:javascript复制
from sqlalchemy import Identity

Table('foo', metadata_obj,
    Column('id', Integer, Identity())
    Column('description', Text),
)

详细信息请参见下面的链接文档。

版本 1.4 中新增。

另请参阅

Identity 列(GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY)

成员

init(), copy()

类签名

class sqlalchemy.schema.Identity (sqlalchemy.schema.IdentityOptions, sqlalchemy.schema.FetchedValue, sqlalchemy.schema.SchemaItem)

代码语言:javascript复制
method __init__(always: bool = False, on_null: bool | None = None, start: int | None = None, increment: int | None = None, minvalue: int | None = None, maxvalue: int | None = None, nominvalue: bool | None = None, nomaxvalue: bool | None = None, cycle: bool | None = None, cache: int | None = None, order: bool | None = None) → None

构造一个 GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY 的 DDL 构造,以配合一个Column

有关大多数参数的完整描述,请参阅Sequence文档。

注意

MSSQL 支持此构造作为在列上生成 IDENTITY 的首选替代方法,但它使用的非标准语法仅支持Identity.startIdentity.increment。所有其他参数都将被忽略。

参数:

  • always – 一个布尔值,表示身份列的类型。如果指定为False,则用户指定的值优先。如果指定为True,则不接受用户指定的值(在某些后端,如 PostgreSQL,可以在 INSERT 中指定 OVERRIDING SYSTEM VALUE 或类似的内容来覆盖序列值)。一些后端也对此参数有一个默认值,None 可以用来省略在 DDL 中呈现这部分。如果后端没有默认值,则将其视为False
  • on_null – 设置为True 以指定在always=False身份列中与ON NULL一起使用。此选项仅在某些后端(如 Oracle)上受支持。
  • start – 序列的起始索引。
  • increment – 序列的增量值。
  • minvalue – 序列的最小值。
  • maxvalue – 序列的最大值。
  • nominvalue – 序列没有最小值。
  • nomaxvalue – 序列没有最大值。
  • cycle – 允许序列在达到maxvalueminvalue时循环。
  • cache – 可选整数值;提前计算的序列中未来值的数量。
  • order – 可选布尔值;如果为真,则呈现 ORDER 关键字。
代码语言:javascript复制
method copy(**kw: Any) → Identity

自版本 1.4 弃用:Identity.copy() 方法已弃用,并将在将来的版本中移除。

定义约束和索引

原文:docs.sqlalchemy.org/en/20/core/constraints.html

这一部分将讨论 SQL 的约束和索引。在 SQLAlchemy 中,关键类包括ForeignKeyConstraintIndex

定义外键

SQL 中的外键是一个表级构造,它将该表中的一个或多个列约束为仅允许存在于另一组列中的值,通常但不总是位于不同的表上。我们称被约束的列为外键列,它们被约束到的列为引用列。引用列几乎总是定义其拥有表的主键,尽管也有例外情况。外键是连接具有关系的行对的“关节”,SQLAlchemy 在其几乎每个操作的每个区域都赋予了这个概念非常深的重要性。

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

代码语言:javascript复制
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表的user_id列中的值。

参数ForeignKey最常见的形式是一个字符串,格式为*.,或者对于远程模式或者“owner”的表格是..*。它也可以是一个实际的Column对象,稍后我们将看到它是通过其c集合从现有的Table对象中访问的:

代码语言:javascript复制
ForeignKey(user.c.user_id)

使用字符串的优点是,在首次需要时才解析useruser_preference之间的 Python 链接,因此表对象可以轻松地分布在多个模块中并按任何顺序定义。

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

代码语言:javascript复制
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 的复合外键的表 invoice_item

代码语言:javascript复制
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 语句中呈现,例如:

代码语言:javascript复制
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 指令用于在 CREATE TABLE 定义中以“内联”的方式创建约束。 MetaData.create_all()MetaData.drop_all() 方法默认使用所有涉及的 Table 对象的拓扑排序,以便按照它们的外键依赖顺序创建和删除表(此排序也可通过 MetaData.sorted_tables 访问器获取)。

当涉及两个或更多外键约束参与“依赖循环”时,这种方法无法工作,其中一组表彼此相互依赖,假设后端执行外键(除了 SQLite、MySQL/MyISAM 之外总是是这样的情况)。因此,这些方法将在除 SQLite 之外的所有后端上将循环中的约束拆分为单独的 ALTER 语句,SQLite 不支持大多数形式的 ALTER。给定这样的模式:

代码语言:javascript复制
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"
    ),
)

当我们在像 PostgreSQL 这样的后端上调用 MetaData.create_all() 时,这两个表之间的循环被解析,并且约束被分别创建:

代码语言:javascript复制
>>> 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 CONSTRAINT 需要约束具有名称。在上面的 'node' 表的情况下,我们还没有为此约束命名;因此系统将仅尝试发出对具有名称的约束的 DROP:

代码语言:javascript复制
>>> 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 

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

代码语言:javascript复制
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.

此错误仅适用于 DROP 情况,因为我们可以在 CREATE 情况下发出 “ADD CONSTRAINT” 而无需名称;数据库通常会自动分配一个名称。

ForeignKeyConstraint.use_alterForeignKey.use_alter 关键字参数可用于手动解决依赖循环。我们可以仅将此标志添加到 'element' 表中,如下所示:

代码语言:javascript复制
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 语句,而不是另一个约束的 ALTER 语句:

代码语言:javascript复制
>>> 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 将要求约束具有名称,否则将生成类似以下的错误:

代码语言:javascript复制
sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name

另请参阅

配置约束命名约定

sort_tables_and_constraints() ### ON UPDATE 和 ON DELETE

大多数数据库都支持外键值的级联,即当父行更新时,新值会放在子行中,或者当父行删除时,所有相应的子行都会被设置为 null 或删除。在数据定义语言中,这些是使用诸如 “ON UPDATE CASCADE”,“ON DELETE CASCADE” 和 “ON DELETE SET NULL” 之类的短语来指定的,对应于外键约束。在 “ON UPDATE” 或 “ON DELETE” 之后的短语可能还允许使用特定于正在使用的数据库的其他短语。ForeignKeyForeignKeyConstraint 对象通过 onupdateondelete 关键字参数支持生成此子句。该值是任何字符串,该字符串将在适当的 “ON UPDATE” 或 “ON DELETE” 短语之后输出:

代码语言:javascript复制
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",
    ),
)

请注意,这些子句在与 MySQL 配合使用时需要 InnoDB 表。它们在其他数据库上也可能不受支持。

另请参阅

有关将 ON DELETE CASCADE 与 ORM relationship() 结构集成的背景,请参阅以下部分:

使用外键 ON DELETE cascade 处理 ORM 关系

使用外键 ON DELETE 处理多对多关系 ## 唯一约束

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

代码语言:javascript复制
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(在 8.0.16 之前)。

代码语言:javascript复制
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"),
)

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

主键约束

任何 Table 对象的主键约束在本质上是隐式存在的,基于标记有 Column.primary_key 标志的 Column 对象。PrimaryKeyConstraint 对象提供了对此约束的显式访问,其中包括直接配置的选项:

代码语言:javascript复制
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 文档。

使用 Declarative ORM 扩展设置约束

Table 是 SQLAlchemy 核心构造,允许定义表元数据,其中可以用于 SQLAlchemy ORM 作为映射类的目标。Declarative 扩展允许自动创建 Table 对象,主要根据表的内容作为 Column 对象的映射。

要将表级约束对象(例如 ForeignKeyConstraint)应用于使用 Declarative 定义的表,请使用 __table_args__ 属性,详见 表配置。

配置约束命名约定

关系数据库通常会为所有约束和索引分配明确的名称。在常见情况下,使用CREATE TABLE创建表时,约束(如 CHECK、UNIQUE 和 PRIMARY KEY 约束)会与表定义一起内联生成,如果未另行指定名称,则数据库通常会自动为这些约束分配名称。当在使用诸如ALTER TABLE之类的命令更改数据库中的现有数据库表时,此命令通常需要为新约束指定显式名称,以及能够指定要删除或修改的现有约束的名称。

使用Constraint.name参数可以明确命名约束,对于索引,可以使用Index.name参数。然而,在约束的情况下,此参数是可选的。还有使用Column.uniqueColumn.index参数的用例,这些参数创建UniqueConstraintIndex对象时未明确指定名称。

对现有表和约束进行更改的用例可以由模式迁移工具(如Alembic)处理。然而,Alembic 和 SQLAlchemy 目前都不会为未指定名称的约束对象创建名称,导致可以更改现有约束的情况下,必须反向工程关系数据库用于自动分配名称的命名系统,或者必须注意确保所有约束都已命名。

与必须为所有ConstraintIndex对象分配显式名称相比,可以使用事件构建自动命名方案。这种方法的优势在于,约束将获得一致的命名方案,无需在整个代码中使用显式名称参数,并且约定也适用于由Column.uniqueColumn.index参数生成的那些约束和索引。从 SQLAlchemy 0.9.2 开始,包含了这种基于事件的方法,并且可以使用参数MetaData.naming_convention进行配置。

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

MetaData.naming_convention指的是一个接受Index类或单独的Constraint类作为键,Python 字符串模板作为值的字典。它还接受一系列字符串代码作为备用键,分别为外键、主键、索引、检查和唯一约束的"fk""pk""ix""ck""uq"。在这个字典中的字符串模板在与这个MetaData对象关联的约束或索引没有给出现有名称的情况下���用。(包括一个例外情况,其中现有名称可以进一步装饰)。

适用于基本情况的一个命名约定示例如下:

代码语言:javascript复制
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时,我们可以观察到生成的名称:

代码语言:javascript复制
>>> 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标志,这个相同的特性也会生效:

代码语言:javascript复制
>>> 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功能时,这个特性的效果是,当生成新的迁移脚本时,命名约定将是明确的:

代码语言:javascript复制
def upgrade():
    op.create_unique_constraint("uq_user_name", "user", ["name"])

上述的"uq_user_name"字符串是从--autogenerate在我们的元数据中定位的UniqueConstraint对象复制而来。

可用的令牌包括 %(table_name)s%(referred_table_name)s%(column_0_name)s%(column_0_label)s%(column_0_key)s%(referred_column_0_name)s,以及每个令牌的多列版本,包括 %(column_0N_name)s%(column_0_N_name)s%(referred_column_0_N_name)s,它们以带有或不带有下划线的形式呈现所有列名称。关于 MetaData.naming_convention 的文档进一步详细说明了这些约定。

默认命名约定

MetaData.naming_convention 的默认值处理了长期以来 SQLAlchemy 的行为,即使用 Column.index 参数创建 Index 对象时分配名称的情况:

代码语言:javascript复制
>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})
长名称的截断

当生成的名称,特别是使用多列令牌的名称,超出目标数据库的标识符长度限制(例如,PostgreSQL 具有 63 个字符的限制)时,名称将使用基于长名称的 md5 哈希的 4 个字符后缀进行确定性截断。例如,以下命名约定将根据使用的列名生成非常长的名称:

代码语言:javascript复制
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 个字符的名称将被截断,如以下示例所示:

代码语言:javascript复制
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 哈希,并且每次生成相同的值,以便为给定模式生成一致的名称。

创建用于命名约定的自定义令牌

还可以通过在 naming_convention 字典中指定额外的令牌和可调用对象来添加新的令牌。例如,如果我们想要使用 GUID 方案对外键约束进行命名,我们可以这样做:

代码语言:javascript复制
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 时,我们将获得以下名称:

代码语言:javascript复制
>>> 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 - 附加使用详细信息以及所有可用命名组件的列表。

命名约束的重要性 - 在 Alembic 文档中。

版本 1.3.0 中的新功能:添加了诸如 %(column_0_N_name)s 等多列命名令牌。超出目标数据库字符限制的生成名称将被确定性地截断。

命名 CHECK 约束

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

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  value  INTEGER,
  CONSTRAINT  ck_foo_value_gt_5  CHECK  (value  >  5)
)

CheckConstraint 还支持 %(columns_0_name)s token;我们可以通过确保在约束表达式中使用 Columncolumn() 元素来利用它,无论是通过单独声明约束表达式还是内联到表中:

代码语言:javascript复制
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()

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  value  INTEGER,
  CONSTRAINT  ck_foo_value  CHECK  (value  >  5)
)

“column zero”的名称确定是通过扫描给定表达式中的列对象来执行的。如果表达式中有多个列,扫描将使用确定性搜索,但是表达式的结构将决定哪个列被标记为“column zero”。### 针对布尔、枚举和其他模式类型进行命名配置

SchemaType 类指的是诸如 BooleanEnum 等类型对象,它们生成与类型相伴随的 CHECK 约束。这里约束的名称最直接是通过发送“name”参数来设置的,例如 Boolean.name

代码语言:javascript复制
Table("foo", metadata_obj, Column("flag", Boolean(name="ck_foo_flag")))

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

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  flag  BOOL,
  CONSTRAINT  ck_foo_flag_bool  CHECK  (flag  IN  (0,  1))
)

SchemaType类使用特殊的内部符号,以便命名约定仅在 DDL 编译时确定。在 PostgreSQL 上,有一个原生的 BOOLEAN 类型,因此不需要Boolean的 CHECK 约束;即使为检查约束设置了命名约定,我们也可以安全地设置不带名称的Boolean类型。如果我们针对没有原生 BOOLEAN 类型的数据库运行,如 SQLite 或 MySQL,那么仅当我们运行时才会参考此约定 CHECK 约束。

CHECK 约束也可以使用column_0_name标记,与SchemaType很好地配合使用,因为这些约束只有一个列:

代码语言:javascript复制
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})

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

以上模式将产生:

代码语言:javascript复制
CREATE  TABLE  foo  (
  flag  BOOL,
  CONSTRAINT  ck_foo_flag  CHECK  (flag  IN  (0,  1))
)
使用 ORM 声明式混合与命名约定

使用命名约定功能与 ORM 声明性混合一起使用时,必须为每个实际表映射的子类存在单独的约束对象。有关背景和示例,请参见使用命名约定在混合上创建索引和约束部分。

约束 API

对象名称

描述

CheckConstraint

表级或列级 CHECK 约束。

ColumnCollectionConstraint

代理 ColumnCollection 的约束。

ColumnCollectionMixin

Column对象的ColumnCollection。

Constraint

表级 SQL 约束。

conv

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

ForeignKey

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

ForeignKeyConstraint

表级 FOREIGN KEY 约束。

HasConditionalDDL

定义一个包括HasConditionalDDL.ddl_if()方法的类,允许对 DDL 进行条件渲染。

PrimaryKeyConstraint

表级主键约束。

UniqueConstraint

表级 UNIQUE 约束。

代码语言:javascript复制
class sqlalchemy.schema.Constraint

表级 SQL 约束。

Constraint 作为一系列约束对象的基类,可以与 Table 对象关联,包括 PrimaryKeyConstraintForeignKeyConstraintUniqueConstraintCheckConstraint

成员

init(), argument_for(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.Constraint (sqlalchemy.sql.base.DialectKWArgs, sqlalchemy.schema.HasConditionalDDL, sqlalchemy.schema.SchemaItem)

代码语言:javascript复制
method __init__(name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, comment: str | None = None, _create_rule: Any | None = None, _type_bound: bool = False, **dialect_kw: Any) → None

创建一个 SQL 约束。

参数:

  • name – 可选,此 Constraint 的数据库名称。
  • deferrable – 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。
  • info – 可选数据字典,将填充到此对象的 SchemaItem.info 属性中。
  • comment – 可选字符串,���在创建外键约束时呈现 SQL 注释。 2.0 版本中的新功能。
  • **dialect_kw – 附加关键字参数是特定于方言的,并以 <dialectname>_<argname> 的形式传递。有关单个方言的文档参数详细信息,请参阅 方言。
  • _create_rule – 一些数据类型内部使用,也创建约束。
  • _type_bound – 内部使用,表示此约束与特定数据类型相关联。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
method copy(**kw: Any) → Self

自 1.4 版本弃用:Constraint.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 的方法 HasConditionalDDL

对此模式项目应用条件 DDL 规则。

这些规则的工作方式与ExecutableDDLElement.execute_if()类似,不同之处在于可以在 DDL 编译阶段检查条件,例如CreateTable这样的结构。 HasConditionalDDL.ddl_if() 目前适用于Index结构以及所有Constraint结构。

参数:

  • dialect – 方言的字符串名称,或字符串名称的元组,表示多个方言类型。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_中描述的相同形式构建的可调用对象。
  • state – 将传递给可调用对象的任意任意对象(如果存在)。

2.0 版本中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

作为针对此结构的方言特定选项指定的关键字参数的集合。

这里的参数以原始的<dialect>_<kwarg>格式呈现。仅包含实际传递的参数;与包含此方言的所有选项(包括默认值)的DialectKWArgs.dialect_options 集合不同。

该集合也是可写的;键采用<dialect>_<kwarg>形式,其中的值将被组装成选项列表。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

作为针对此结构的方言特定选项指定的关键字参数的集合。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

0.9.2 版本中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs DialectKWArgs 属性

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
class sqlalchemy.schema.ColumnCollectionMixin

一个Column对象的ColumnCollection

此集合表示此对象引用的列。

代码语言:javascript复制
class sqlalchemy.schema.ColumnCollectionConstraint

代理列集合的约束。

成员

init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

class sqlalchemy.schema.ColumnCollectionConstraint (sqlalchemy.schema.ColumnCollectionMixin, sqlalchemy.schema.Constraint)

代码语言:javascript复制
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None

参数:

  • *columns – 一系列列名或列对象。
  • name – 可选项,此约束的数据库中的名称。
  • deferrable – 可选布尔值。如果设置,发出 DDL 时会发出 DEFERRABLE 或 NOT DEFERRABLE 用于此约束。
  • initially – 可选字符串。如果设置,发出 DDL 时会发出 INITIALLY 用于此约束。
  • **dialect_kw – 其他关键字参数,包括方言特定参数,都会传播到Constraint 超类。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin 属性 ColumnCollectionMixin.columns

代表此约束的一组列的 ColumnCollection

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

如果此约束包含给定的列,则返回 True。

请注意,此对象还包含一个属性 .columns,它是 Column 对象的 ColumnCollection

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint

从版本 1.4 开始弃用:ColumnCollectionConstraint.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

对此模式项应用条件 DDL 规则。

这些规则的工作方式与ExecutableDDLElement.execute_if()可调用对象类似,额外的特性是可以在 DDL 编译阶段检查条件,例如CreateTable构造中的条件。HasConditionalDDL.ddl_if()目前也适用于Index构造以及所有Constraint构造。

参数:

  • dialect – 方言的字符串名称,或表示多个方言类型的字符串名称元组。
  • callable_ – 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_中描述的形式相同。
  • state – 任意对象,如果存在将传递给可调用对象。

版本 2.0 中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以原始的<dialect>_<kwarg>格式呈现。仅包括实际传递的参数;与包含所有已知选项的默认值的DialectKWArgs.dialect_options集合不同。

该集合也是可写的;键的形式为<dialect>_<kwarg>,其中的值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

新版本 0.9.2 中新增。

另见

DialectKWArgs.dialect_kwargs - 扁平字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
class sqlalchemy.schema.CheckConstraint

表或列级别的检查约束。

可以包含在表或列的定义中。

成员

init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.CheckConstraint (sqlalchemy.schema.ColumnCollectionConstraint)

代码语言:javascript复制
method __init__(sqltext: _TextCoercedExpressionArgument[Any], name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, table: Table | None = None, info: _InfoType | None = None, _create_rule: Any | None = None, _autoattach: bool = True, _type_bound: bool = False, **dialect_kw: Any) → None

构建一个检查约束。

参数:

sqltext

包含约束定义的字符串,将会原样使用,或者是一个 SQL 表达式构造。如果给定为字符串,则将对象转换为 text() 对象。如果文本字符串包含冒号字符,则使用反斜杠进行转义:

代码语言:javascript复制
CheckConstraint(r"foo ~ E'a(?:b|c)d")

警告

CheckConstraint.sqltext 参数可以作为 Python 字符串参数传递给 CheckConstraint,该参数将被视为受信任的 SQL 文本并按原样呈现。不要将不受信任的输入传递给此参数

name – 可选的,约束在数据库中的名称。

deferrable – 可选布尔值。如果设置了,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。

initially – 可选字符串。如果设置了,则在为此约束发出 DDL 时发出 INITIALLY 。

info – 可选的数据字典,将填充到该对象的 SchemaItem.info 属性中。

代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin.columns 属性的 ColumnCollectionMixin

表示此约束的列集合。

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

继承自 ColumnCollectionConstraint.contains_column() 方法的 ColumnCollectionConstraint

如果此约束包含给定的列,则返回 True。

注意,此对象还包含一个属性 .columns,它是一个 ColumnCollection,其中包含 Column 对象。

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → CheckConstraint

自版本 1.4 起已弃用:CheckConstraint.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

对此模式项应用条件 DDL 规则。

这些规则的工作方式与ExecutableDDLElement.execute_if()可调用对象类似,但增加了一个功能,即可以在 DDL 编译阶段检查条件,例如CreateTable构造。 HasConditionalDDL.ddl_if()目前也适用于Index构造以及所有Constraint构造。

参数:

  • dialect - 方言的字符串名称,或字符串名称的元组以指示多个方言类型。
  • callable_ - 使用与ExecutableDDLElement.execute_if.callable_描述的相同形式构造的可调用对象。
  • state - 任意对象,如果存在,将传递给可调用对象。

版本 2.0 中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

作为方言特定选项传递给此构造函数的关键字参数集合。

这里的参数以其原始的<dialect>_<kwarg>格式存在。只包括实际传递的参数;与包含此方言的所有选项的DialectKWArgs.dialect_options集合不同,后者包含了所有已知选项,包括默认值。

该集合也可写入;键的形式为<dialect>_<kwarg>,其中的值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

作为方言特定选项传递给此构造函数的关键字参数集合。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

当首次访问时,字典会自动生成。也可以在某些对象的构造函数中指定,例如TableColumn

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs的同义词。

代码语言:javascript复制
class sqlalchemy.schema.ForeignKey

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

ForeignKey被指定为Column对象的一个参数,例如:

代码语言:javascript复制
t = Table("remote_table", metadata,
    Column("remote_id", ForeignKey("main_table.id"))
)

注意ForeignKey只是一个标记对象,它定义了两个列之间的依赖关系。在所有情况下,实际的约束由ForeignKeyConstraint对象表示。当ForeignKey与一个与Table关联的Column相关联时,此对象将自动生成。相反,当ForeignKeyConstraint应用于一个与Table相关联的Table时,将自动生成ForeignKey标记,这些标记也与约束对象相关联。

请注意,您不能使用ForeignKey对象定义“复合”外键约束,即多个父/子列的分组之间的约束。要定义此分组,必须使用ForeignKeyConstraint对象,并将其应用于Table。相关的ForeignKey对象会自动生成。

与单个Column对象关联的ForeignKey对象可在该列的 foreign_keys 集合中使用。

更多外键配置示例见定义外键。

成员

init(), argument_for(), column, copy(), dialect_kwargs, dialect_options, get_referent(), info, kwargs, references(), target_fullname

类签名

sqlalchemy.schema.ForeignKeysqlalchemy.sql.base.DialectKWArgs, sqlalchemy.schema.SchemaItem)

代码语言:javascript复制
method __init__(column: _DDLColumnArgument, _constraint: ForeignKeyConstraint | None = None, use_alter: bool = False, name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, link_to_name: bool = False, match: str | None = None, info: _InfoType | None = None, comment: str | None = None, _unresolvable: bool = False, **dialect_kw: Any)

构造列级 FOREIGN KEY。

构造ForeignKey对象时生成与父Table对象的约束集合关联的ForeignKeyConstraint

参数:

  • column – 关键关系的单个目标列。一个Column对象或作为字符串的列名:tablename.columnkeyschema.tablename.columnkey。除非link_to_nameTrue,否则columnkey是分配给列的key(默认为列名本身)。
  • name – 可选的字符串。如果未提供约束,则用于键的数据库内名称。
  • onupdate – 可选的字符串。如果设置,发出 ON UPDATE 的 DDL。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • ondelete – 可选的字符串。如果设置,发出 ON DELETE 的 DDL。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • deferrable – 可选的布尔值。如果设置,发出 DEFERRABLE 或 NOT DEFERRABLE 的 DDL。
  • initially – 可选的字符串。如果设置,发出 INITIALLY 的 DDL。
  • link_to_name – 如果为 True,则column中给定的字符串名称是引用列的呈现名称,而不是其本地分配的key
  • use_alter – 传递给底层 ForeignKeyConstraint 以指示应该从 CREATE TABLE/ DROP TABLE 语句外部生成/删除约束。 有关详细信息,请参阅 ForeignKeyConstraint.use_alter。 另请参见 ForeignKeyConstraint.use_alter 通过 ALTER 创建/删除外键约束
  • match – 可选字符串。 如果设置,当为此约束发出 DDL 时,将发出 MATCH 。 典型值包括 SIMPLE、PARTIAL 和 FULL。
  • info – 可选数据字典,将填充到此对象的 SchemaItem.info 属性中。
  • comment – 可选字符串,将在外键约束创建时渲染 SQL 注释。 2.0 版中的新内容。
  • **dialect_kw – 额外的关键字参数是特定于方言的,并以 <dialectname>_<argname> 的形式传递。 这些参数最终由相应的 ForeignKeyConstraint 处理。 有关已记录参数的详细信息,请参阅 方言 中有关单个方言的文档。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute column

返回由此 ForeignKey 引用的目标 Column

如果没有建立目标列,则会引发异常��

代码语言:javascript复制
method copy(*, schema: str | None = None, **kw: Any) → ForeignKey

自版本 1.4 弃用:ForeignKey.copy() 方法已弃用,并将在将来的版本中移除。

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性DialectKWArgs

作为特定于方言的选项指定的关键字参数集合。

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

该集合也是可写的;键的形式为 <dialect>_<kwarg>,其中的值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性DialectKWArgs

作为特定于方言的选项指定的关键字参数集合。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 扁平字典形式

代码语言:javascript复制
method get_referent(table: FromClause) → Column[Any] | None

返回此ForeignKey引用的给定Table(或任何FromClause)中的Column

如果此ForeignKey未引用给定的Table,则返回 None。

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs的同义词。

代码语言:javascript复制
method references(table: Table) → bool

如果此ForeignKey引用给定的Table,则返回 True。

代码语言:javascript复制
attribute target_fullname

返回此ForeignKey的基于字符串的‘列规范’。

这通常相当于首先传递给对象构造函数的基于字符串的“tablename.colname”参数。

代码语言:javascript复制
class sqlalchemy.schema.ForeignKeyConstraint

表级别的外键约束。

定义单列或复合 FOREIGN KEY … REFERENCES 约束。对于简单的、单列的外键,将 ForeignKey 添加到 Column 的定义中相当于一个未命名的、单列的 ForeignKeyConstraint

外键配置示例位于 定义外键 中。

成员

init(), argument_for(), column_keys, columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, elements, info, kwargs, referred_table

类签名

sqlalchemy.schema.ForeignKeyConstraintsqlalchemy.schema.ColumnCollectionConstraint

代码语言:javascript复制
method __init__(columns: _typing_Sequence[_DDLColumnArgument], refcolumns: _typing_Sequence[_DDLColumnArgument], name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, use_alter: bool = False, link_to_name: bool = False, match: str | None = None, table: Table | None = None, info: _InfoType | None = None, comment: str | None = None, **dialect_kw: Any) → None

构造一个能够处理复合键的 FOREIGN KEY。

参数:

  • columns – 一系列本地列名称。所命名的列必须在父表中定义并存在。除非 link_to_name 为 True,否则名称应与每列给定的 key 匹配(默认为名称)。
  • refcolumns – 一系列外键列名称或 Column 对象。这些列必须全部位于同一张表内。
  • name – 可选,键的数据库内名称。
  • onupdate – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON UPDATE 。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • ondelete – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON DELETE 。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • deferrable – 可选布尔值。如果设置,则在发出此约束的 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。
  • link_to_name – 如果为 True,则 column 中给定的字符串名称是引用列的渲染名称,而不是其本地分配的 key
  • use_alter – 如果为 True,则不会将此约束的 DDL 作为 CREATE TABLE 定义的一部分输出。相反,在创建完整的表集合之后,通过 ALTER TABLE 语句生成它,在删除完整的表集合之前,通过 ALTER TABLE 语句将其删除。 ForeignKeyConstraint.use_alter 的使用特别适用于两个或多个表在相互依赖的外键约束关系内建立的情况;然而,MetaData.create_all()MetaData.drop_all() 方法将自动执行此解析,因此通常不需要该标志。 另请参阅 通过 ALTER 创建/删除外键约束
  • match – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 MATCH 。典型值包括 SIMPLE、PARTIAL 和 FULL。
  • info – 将填充到此对象的 SchemaItem.info 属性中的可选数据字典。
  • comment – 可选字符串,将在创建外键约束时呈现 SQL 注释。 新版本 2.0 中新增。
  • **dialect_kw – 附加关键字参数是方言特定的,并以 <方言名称>_<参数名称> 形式传递。有关文档中记录的参数的详细信息,请参阅方言中有关单个方言的文档。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

来自 DialectKWArgs DialectKWArgs.argument_for() 方法继承

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute column_keys

返回表示此 ForeignKeyConstraint 中本地列的字符串键列表。

此列表是发送到 ForeignKeyConstraint 构造函数的原始字符串参数,或者如果约束已使用 Column 对象进行初始化,则是每个元素的字符串 .key

代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

ColumnCollectionMixin ColumnCollectionMixin.columns 属性继承

表示此约束的列集合的 ColumnCollection

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

ColumnCollectionConstraint.contains_column() 方法继承

如果此约束包含给定的列,则返回 True。

请注意,此对象还包含一个属性 .columns,它是 Column 对象的 ColumnCollection

代码语言:javascript复制
method copy(*, schema: str | None = None, target_table: Table | None = None, **kw: Any) → ForeignKeyConstraint

从版本 1.4 起弃用:ForeignKeyConstraint.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

HasConditionalDDL HasConditionalDDL.ddl_if() 方法继承

对此模式项应用条件 DDL 规则。

这些规则的工作方式与ExecutableDDLElement.execute_if()可调用对象类似,但增加了在 DDL 编译阶段检查条件的功能,例如CreateTable构造。HasConditionalDDL.ddl_if()当前还适用于Index构造以及所有Constraint构造。

参数:

  • dialect – 方言的字符串名称,或一个字符串名称元组,表示多个方言类型。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_描述的相同形式构造的可调用对象。
  • state – 如果存在,则会传递给可调用对象的任意对象。

版本 2.0 中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

一组关键字参数,指定为此构造的方言特定选项。

这些参数在这里以其原始的<dialect>_<kwarg>格式呈现。只包括实际传递的参数;与包含此方言的所有选项(包括默认值)的DialectKWArgs.dialect_options集合不同。

该集合也是可写的;接受形式为<dialect>_<kwarg>的键,值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

一组关键字参数,指定为此构造的方言特定选项。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute elements: List[ForeignKey]

一系列ForeignKey对象。

每个ForeignKey表示一个引用列/被引用列对。

此集合预期为只读。

代码语言:javascript复制
attribute info

继承自SchemaItem.info 属性的

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

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

代码语言:javascript复制
attribute kwargs

继承自DialectKWArgs.kwargs 属性的

DialectKWArgs.dialect_kwargs的同义词。

代码语言:javascript复制
attribute referred_table

ForeignKeyConstraint引用的Table对象。

这是一个动态计算的属性,如果约束和/或父表尚未与包含所引用表的元数据集合关联,则可能无法使用此属性。

代码语言:javascript复制
class sqlalchemy.schema.HasConditionalDDL

定义一个包含HasConditionalDDL.ddl_if()方法的类,允许对 DDL 进行条件渲染。

目前适用于约束和索引。

成员

ddl_if()

版本 2.0 中的新功能。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

对此模式项应用条件 DDL 规则。

这些规则的工作方式类似于 ExecutableDDLElement.execute_if() 可调用对象,但增加了一个特性,即在 DDL 编译阶段可以检查条件,例如 CreateTable 等构造中的条件。 HasConditionalDDL.ddl_if() 目前也适用于 Index 构造以及所有 Constraint 构造。

参数:

  • dialect – 方言的字符串名称,或者字符串名称的元组,表示多种方言类型。
  • callable_ – 一个可调用对象,其构造方式与 ExecutableDDLElement.execute_if.callable_ 中描述的相同。
  • state – 如果存在,则将传递给可调用对象的任意对象。

版本 2.0 中的新增内容。

另请参阅

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
class sqlalchemy.schema.PrimaryKeyConstraint

表级别的主键约束。

Table 对象上自动存在 PrimaryKeyConstraint 对象;它被分配了一组与标记有 Column.primary_key 标志的列对应的 Column 对象:

代码语言:javascript复制
>>> my_table = Table('mytable', metadata,
...                 Column('id', Integer, primary_key=True),
...                 Column('version_id', Integer, primary_key=True),
...                 Column('data', String(50))
...     )
>>> my_table.primary_key
PrimaryKeyConstraint(
 Column('id', Integer(), table=<mytable>,
 primary_key=True, nullable=False),
 Column('version_id', Integer(), table=<mytable>,
 primary_key=True, nullable=False)
)

也可以通过显式使用 PrimaryKeyConstraint 对象来指定 Table 的主键;在这种用法模式下,还可以指定约束的“名称”,以及方言可能识别的其他选项:

代码语言:javascript复制
my_table = Table('mytable', metadata,
            Column('id', Integer),
            Column('version_id', Integer),
            Column('data', String(50)),
            PrimaryKeyConstraint('id', 'version_id',
                                 name='mytable_pk')
        )

通常不应混合两种列规范样式。如果同时存在 PrimaryKeyConstraint 中的列与标记为 primary_key=True 的列不匹配,则会发出警告;在这种情况下,列严格来自 PrimaryKeyConstraint 声明,并且其他标记为 primary_key=True 的列将被忽略。此行为旨在向后兼容以前的行为。

对于需要在 PrimaryKeyConstraint 上指定特定选项的用例,但仍希望使用 primary_key=True 标志的常规方式,可以指定一个空的 PrimaryKeyConstraint,该约束将根据标志从 Table 中获取主键列集合:

代码语言:javascript复制
my_table = Table('mytable', metadata,
            Column('id', Integer, primary_key=True),
            Column('version_id', Integer, primary_key=True),
            Column('data', String(50)),
            PrimaryKeyConstraint(name='mytable_pk',
                                 mssql_clustered=True)
        )

成员

argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

class sqlalchemy.schema.PrimaryKeyConstraint (sqlalchemy.schema.ColumnCollectionConstraint)

代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin.columns 属性的 ColumnCollectionMixin

代表此约束的一组列的 ColumnCollection

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

继承自 ColumnCollectionConstraint.contains_column() 方法的 ColumnCollectionConstraint

如果此约束包含给定的列,则返回 True。

请注意,此对象还包含一个名为 .columns 的属性,它是 Column 对象的 ColumnCollection

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint

继承自 ColumnCollectionConstraint.copy() 方法的 ColumnCollectionConstraint

从版本 1.4 开始已弃用:ColumnCollectionConstraint.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

对这个模式项应用一个条件 DDL 规则。

这些规则与ExecutableDDLElement.execute_if()可调用对象的工作方式类似,额外的特性是可以在 DDL 编译阶段检查条件,例如CreateTable这样的结构。 HasConditionalDDL.ddl_if()目前也适用于Index结构以及所有Constraint结构。

参数:

  • dialect – 方言的字符串名称,或者字符串名称的元组以指示多个方言类型。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_中描述的相同形式构造的可调用对象。
  • state – 如果存在,将传递给可调用对象的任意对象。

版本 2.0 中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

一组作为特定于方言的选项指定为此结构的关键字参数。

这些参数以原始的 <dialect>_<kwarg> 格式出现在此处。仅包括实际传递的参数;不像DialectKWArgs.dialect_options集合,该集合包含该方言知道的所有选项,包括默认值。

该集合也是可写的;键以 <dialect>_<kwarg> 形式接受,其中值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

一组作为特定于方言的选项指定为此结构的关键字参数。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 平展的字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
class sqlalchemy.schema.UniqueConstraint

表级别的唯一约束。

定义单列或组合唯一约束。对于简单的单列约束,向 Column 定义中添加 unique=True 是一个等效的缩写,相当于未命名的单列 UniqueConstraint。

成员

init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.UniqueConstraint (sqlalchemy.schema.ColumnCollectionConstraint)。

代码语言:javascript复制
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None

继承自 sqlalchemy.schema.ColumnCollectionConstraint.__init__ 方法的 ColumnCollectionConstraint

参数:

  • *columns – 一系列列名或 Column 对象。
  • name – 可选项,此约束的数据库内名称。
  • deferrable – 可选的布尔值。如果设置,当为此约束发出 DDL 时会发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,当为此约束发出 DDL 时,会发出 INITIALLY 。
  • **dialect_kw – 其他关键字参数,包括方言特定参数,将传播到 Constraint 超类。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs DialectKWArgs.argument_for() 方法

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin ColumnCollectionMixin.columns 属性

表示此约束的列集合的 ColumnCollection

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

继承自 ColumnCollectionConstraint.contains_column() 方法的 ColumnCollectionConstraint

如果此约束包含给定的列,则返回 True。

请注意,此对象还包含一个属性.columns,它是Column对象的ColumnCollection

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint

继承自 ColumnCollectionConstraint.copy() 方法的 ColumnCollectionConstraint

自版本 1.4 开始已弃用:ColumnCollectionConstraint.copy() 方法已弃用,将在未来版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

对此模式项应用一个条件 DDL 规则。

这些规则的工作方式与ExecutableDDLElement.execute_if()可调用对象类似,但添加了一个特性,即可以在 DDL 编译阶段检查条件,例如CreateTable构造。 HasConditionalDDL.ddl_if() 目前也适用于Index构造以及所有Constraint构造。

参数:

  • dialect – 方言的字符串名称,或者一个字符串名称的元组,表示多个方言类型。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_描述的相同形式构建的可调用对象。
  • state – 如果存在,将传递给可调用对象的任意对象。

2.0 版中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以其原始的 <dialect>_<kwarg> 格式呈现。仅包括实际传递的参数;与 DialectKWArgs.dialect_options 集合不同,后者包含此方言的所有已知选项,包括默认值。

该集合也是可写的;接受形式为 <dialect>_<kwarg> 的键,其值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

新版本中新增 0.9.2。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

当首次访问时,该字典将自动生成。也可以在某些对象的构造函数中指定它,例如 TableColumn

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
function sqlalchemy.schema.conv(value: str, quote: bool | None = None) → Any

标记字符串,指示名称已经被命名约定转换。

这是一个字符串子类,指示不应再受任何进一步命名约定的影响的名称。

例如,当我们按照以下命名约定创建一个 Constraint 时:

代码语言:javascript复制
m = MetaData(naming_convention={
    "ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
                CheckConstraint('x > 5', name='x5'))

上述约束的名称将呈现为 "ck_t_x5"。也就是说,现有名称 x5 被用作命名约定中的 constraint_name 令牌。

在某些情况下,例如在迁移脚本中,我们可能会使用已经转换过的名称渲染上述 CheckConstraint。为了确保名称不被双重修改,新名称使用 conv() 标记应用。我们可以显式地使用如下:

代码语言:javascript复制
m = MetaData(naming_convention={
    "ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
                CheckConstraint('x > 5', name=conv('ck_t_x5')))

在上述情况中,conv() 标记指示此处约束名为最终名称,名称将呈现为 "ck_t_x5" 而不是 "ck_t_ck_t_x5"

另请参见

配置约束命名约定

索引

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

下面我们示例了一个带有多个相关 Index 对象的 Table。DDL “创建索引”的语句会在表的创建语句之后立即发出:

代码语言:javascript复制
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)

mytable.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 内部“内联”定义,使用字符串名称标识列:

代码语言:javascript复制
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() 方法:

代码语言:javascript复制
i = Index("someindex", mytable.c.col5)
i.create(engine)
CREATE  INDEX  someindex  ON  mytable  (col5) 
函数索引

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

代码语言:javascript复制
from sqlalchemy import Index

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

或者使用支持功能性索引的后端,比如 PostgreSQL,可以使用 lower() 函数创建“不区分大小写”的索引:

代码语言:javascript复制
from sqlalchemy import func, Index

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

索引 API

对象名称

描述

Index

表级别的索引。

代码语言:javascript复制
class sqlalchemy.schema.Index

表级别的索引。

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

例如:

代码语言:javascript复制
sometable = Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100))
            )

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

对于一个简单的单列索引,添加 Column 也支持 index=True

代码语言:javascript复制
sometable = Table("sometable", metadata,
                Column("name", String(50), index=True)
            )

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

代码语言:javascript复制
Index("some_index", sometable.c.name, sometable.c.address)

也支持功能性索引,通常通过结合绑定到表的 Column 对象使用 func 构造来实现:

代码语言:javascript复制
Index("some_index", func.lower(sometable.c.name))

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

代码语言:javascript复制
Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100)),
                Index("some_index", "name", "address")
        )

为了在此形式中支持功能性或基于表达式的索引,可以使用 text() 构造:

代码语言:javascript复制
from sqlalchemy import text

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

另请参阅

索引 - 关于 Index 的一般信息。

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

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

聚集索引支持 - 用于 Index 构造的特定于 MSSQL 的选项。

成员

init(), argument_for(), create(), ddl_if(), dialect_kwargs, dialect_options, drop(), info, kwargs

类签名

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

代码语言:javascript复制
method __init__(name: str | None, *expressions: _DDLColumnArgument, unique: bool = False, quote: bool | None = None, info: _InfoType | None = None, _table: Table | None = None, _column_flag: bool = False, **dialect_kw: Any) → None

构造索引对象。

参数:

  • name – 索引的名称
  • *expressions – 要包含在索引中的列表达式。这些表达式通常是 Column 的实例,但也可以是最终引用 Column 的任意 SQL 表达式。
  • unique=False – 仅限关键字参数;如果为 True,则创建唯一索引。
  • quote=None – 仅限关键字参数;是否对索引名称应用引号。其工作方式与 Column.quote 相同。
  • info=None – 可选数据字典,将填充到此对象的 SchemaItem.info 属性中。
  • **dialect_kw – 除上述未提及的其他关键字参数是方言特定的,并以<dialectname>_<argname>的形式传递。有关文档中列出的参数的详细信息,请参阅有关单个方言的文档 方言 。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
method create(bind: _CreateDropBind, checkfirst: bool = False) → None

为这个 Index 发出一个 CREATE 语句,使用给定的 ConnectionEngine 进行连接。

另请参见

MetaData.create_all().

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

对此模式项应用条件 DDL 规则。

这些规则的工作方式类似于 ExecutableDDLElement.execute_if() 可调用对象,额外的功能是可以在 DDL 编译阶段检查条件,例如 CreateTable 这样的构造。HasConditionalDDL.ddl_if() 目前也适用于 Index 构造以及所有 Constraint 构造。

参数:

  • dialect – 方言的字符串名称,或者字符串名称的元组,表示多个方言类型。
  • callable_ – 一个可调用对象,其构造方式与 ExecutableDDLElement.execute_if.callable_ 中描述的形式相同。
  • state – 如果存在,将传递给可调用对象的任意对象。

版本 2.0 中的新功能。

另请参见

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以原始的<dialect>_<kwarg>格式呈现。仅包括实际传递的参数;不像DialectKWArgs.dialect_options集合,该集合包含此方言已知的所有选项,包括默认值。

该集合也是可写的;接受形式为<dialect>_<kwarg>的键,其值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

作为特定于方言的选项指定的关键字参数集合。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

从版本 0.9.2 开始。

另请参阅

DialectKWArgs.dialect_kwargs - 扁平字典形式

代码语言:javascript复制
method drop(bind: _CreateDropBind, checkfirst: bool = False) → None

使用给定的ConnectionEngine进行此IndexDROP语句。

另请参阅

MetaData.drop_all()

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的一个同义词。

定义外键

在 SQL 中,外键是一个表级构造,它限制该表中的一个或多个列只允许存在于另一组列中的值,通常但不总是位于不同的表中。我们将受到限制的列称为外键列,它们被约束到的列称为引用列。引用列几乎总是定义其所属表的主键,尽管也有例外情况。外键是连接具有彼此关系的行对的“接头部分”,在几乎每个操作中,SQLAlchemy 都将这个概念赋予了非常重要的意义。

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

代码语言:javascript复制
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 表的 user_id 列中的值。

ForeignKey 的参数最常见的是形式为 . 的字符串,或者对于远程架构或“拥有者”的表,形式为 ..。它也可以是一个实际的 Column 对象,稍后我们将看到,它通过其 c 集合从现有的 Table 对象中访问:

代码语言:javascript复制
ForeignKey(user.c.user_id)

使用字符串的优势在于,useruser_preference 之间的 python 链接只有在首次需要时才会解析,因此表对象可以轻松地分布在多个模块中,并且以任何顺序定义。

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

代码语言:javascript复制
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的复合外键的invoice_item表:

代码语言:javascript复制
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 语句中呈现,例如:

代码语言:javascript复制
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指令用于在 CREATE TABLE 定义内“内联”创建约束。MetaData.create_all()MetaData.drop_all() 方法默认使用拓扑排序对所有涉及的 Table 对象进行排序,以便按外键依赖关系的顺序创建和删除表(此排序也可通过 MetaData.sorted_tables 访问器获得)。

当涉及两个或更多外键约束的“依赖循环”时,此方法无法工作,在这种情况下,一组表彼此相互依赖,假设后端执行外键(SQLite 除外,MySQL/MyISAM 总是如此)。因此,该方法将在除 SQLite 之外的所有后端上将循环中的约束分解为单独的 ALTER 语句,因为 SQLite 不支持大多数形式的 ALTER。给定一个类似的模式:

代码语言:javascript复制
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"
    ),
)

当我们在后端(如 PostgreSQL 后端)调用MetaData.create_all()时,这两个表之间的循环被解决,约束被分别创建:

代码语言:javascript复制
>>> 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 CONSTRAINT 需要约束具有名称。 在上述'node'表的情况下,我们没有命名此约束; 因此,系统将仅尝试为具有名称的约束发出 DROP:

代码语言:javascript复制
>>> 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 

在无法解析循环的情况下,例如,如果我们没有在这里为任一约束指定名称,我们将收到以下错误:

代码语言:javascript复制
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.

此错误仅适用于 DROP 情况,因为在 CREATE 情况下我们可以不带名称发出“ADD CONSTRAINT”; 数据库通常会自动分配一个名称。

当手动解析依赖关系循环时,可以使用ForeignKeyConstraint.use_alterForeignKey.use_alter 关键字参数。 我们可以仅将此标志添加到'element'表中,如下所示:

代码语言:javascript复制
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 语句,而不是其他约束:

代码语言:javascript复制
>>> 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 关键字参数将要求约束具有名称,否则将生成以下错误:

代码语言:javascript复制
sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name

请参见

配置约束命名约定

sort_tables_and_constraints() ### ON UPDATE and ON DELETE

大多数数据库支持外键值的级联,即当父行更新时,新值将放置在子行中,或者当父行删除时,所有相应的子行都将设置为 null 或删除。 在数据定义语言中,这些是使用诸如“ON UPDATE CASCADE”,“ON DELETE CASCADE”和“ON DELETE SET NULL”之类的短语来指定的,这些短语对应于外键约束。 “ON UPDATE”或“ON DELETE”后面的短语还可以允许其他与正在使用的数据库特定的短语相对应的短语。 ForeignKeyForeignKeyConstraint 对象通过 onupdateondelete 关键字参数支持通过生成此子句。 值是任何字符串,将在适当的“ON UPDATE”或“ON DELETE”短语之后输出:

代码语言:javascript复制
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",
    ),
)

请注意,这些子句在与 MySQL 一起使用时需要InnoDB表。 它们在其他数据库上也可能不受支持。

请参见

关于与 ORM relationship() 构造的 ON DELETE CASCADE 集成的背景,请参见以下各节:

使用 ORM 关系中的外键 ON DELETE cascade

在多对多关系中使用外键 ON DELETE ### 通过 ALTER 创建/删除外键约束

我们在教程和其他地方看到的涉及 DDL 的外键的行为表明,约束通常在 CREATE TABLE 语句中“内联”呈现,例如:

代码语言:javascript复制
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 指令用于以“内联”方式在 CREATE TABLE 定义中创建约束。 MetaData.create_all()MetaData.drop_all() 方法默认使用所有涉及的 Table 对象的拓扑排序,这样表就按照它们的外键依赖顺序创建和删除(此排序也可以通过 MetaData.sorted_tables 访问器获得)。

当涉及两个或更多个外键约束参与“依赖循环”时,此方法无法工作,在此循环中一组表相互依赖,假设后端强制执行外键(除 SQLite、MySQL/MyISAM 之外的情况始终如此)。因此,方法将在除不支持大多数 ALTER 形式的 SQLite 外的所有后端上将此类循环中的约束拆分为单独的 ALTER 语句。给定这样的模式:

代码语言:javascript复制
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"
    ),
)

当我们在诸如 PostgreSQL 后端之类的后端上调用 MetaData.create_all() 时,这两个表之间的循环被解决,并且约束被单独创建:

代码语言:javascript复制
>>> 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 CONSTRAINT 需要约束具有名称。在上面的 'node' 表的情况下,我们没有为此约束命名;因此系统将尝试仅发出命名的约束的 DROP:

代码语言:javascript复制
>>> 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 

如果无法解决循环,例如我们在这里未给任何约束应用名称的情况,我们将收到以下错误:

代码语言:javascript复制
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.

此错误仅适用于 DROP 案例,因为我们可以在 CREATE 案例中发出“ADD CONSTRAINT”而无需名称;数据库通常会自动分配一个名称。

ForeignKeyConstraint.use_alterForeignKey.use_alter 关键字参数可用于手动解决依赖循环。我们可以将此标志仅添加到 'element' 表中,如下所示:

代码语言:javascript复制
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 语句,而不是其他的:

代码语言:javascript复制
>>> 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 需要命名约束,否则会生成以下错误:

代码语言:javascript复制
sqlalchemy.exc.CompileError: Can't emit DROP CONSTRAINT for constraint
ForeignKeyConstraint(...); it has no name

另见

配置约束命名约定

sort_tables_and_constraints()

ON UPDATE 和 ON DELETE

大多数数据库支持外键值的级联,也就是当父行更新时,新值将放置在子行中,或者当父行删除时,所有相应的子行都设置为 null 或删除。在数据定义语言中,这些是使用诸如“ON UPDATE CASCADE”、“ON DELETE CASCADE”和“ON DELETE SET NULL”之类的短语指定的,对应于外键约束。在“ON UPDATE”或“ON DELETE”之后的短语可能还允许其他特定于正在使用的数据库的短语。 ForeignKeyForeignKeyConstraint 对象支持通过 onupdateondelete 关键字参数生成此子句。该值是任何字符串,将在适当的“ON UPDATE”或“ON DELETE”短语之后输出:

代码语言:javascript复制
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",
    ),
)

请注意,当与 MySQL 一起使用时,这些子句需要 InnoDB 表。它们在其他数据库上也可能不受支持。

另见

关于将 ON DELETE CASCADE 与 ORM relationship() 构造集成的背景信息,请参见以下部分:

使用 ORM 关联的外键 ON DELETE cascade

在多对多关系中使用外键 ON DELETE

唯一约束

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

代码语言:javascript复制
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"),
)

CHECK 约束

检查约束可以具有命名或未命名,并且可以在列级别或表级别上创建,使用 CheckConstraint 构造。检查约束的文本直接传递到数据库,因此具有有限的“数据库独立”行为。列级别的检查约束通常只应引用它们所放置的列,而表级别的约束可以引用表中的任何列。

请注意,一些数据库不支持主动支持检查约束,例如较旧版本的 MySQL(在 8.0.16 之前)。

代码语言:javascript复制
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"),
)

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

主键约束

任何 Table 对象的主键约束都是隐式存在的,基于标记有 Column.primary_key 标志的 Column 对象。PrimaryKeyConstraint 对象提供对此约束的显式访问,包括直接配置的选项:

代码语言:javascript复制
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 文档。

使用 Declarative ORM 扩展时设置约束

Table 是 SQLAlchemy 核心的构造,允许定义表元数据,这些元数据可以被 SQLAlchemy ORM 用作映射类的目标之一。Declarative 扩展允许自动创建 Table 对象,主要是将表的内容作为 Column 对象的映射。

要将诸如 ForeignKeyConstraint 等表级约束对象应用于使用 Declarative 定义的表,请使用 __table_args__ 属性,详见 表配置。

配置约束命名约定

关系数据库通常为所有约束和索引分配显式名称。在创建表时使用CREATE TABLE的常见情况下,约束(如 CHECK、UNIQUE 和 PRIMARY KEY 约束)会与表定义一起内联生成,如果未另有规定,则数据库通常会自动分配名称给这些约束。在使用诸如ALTER TABLE之类的命令在数据库中更改现有数据库表时,此命令通常需要为新约束指定显式名称,以及能够指定要删除或修改的现有约束的名称。

可以使用Constraint.name参数和索引的Index.name参数明确地为约束命名。然而,在约束的情况下,此参数是可选的。还有使用Column.uniqueColumn.index参数的用例,这些参数会创建未指定显式名称的UniqueConstraintIndex对象。

通过架构迁移工具,如Alembic,可以处理现有表格和约束的更改用例。但是,目前既不是 Alembic 也不是 SQLAlchemy 创建约束对象的名称,除非另有规定,否则导致能够更改现有约束的情况,这意味着必须逆向工程关系数据库用于自动分配名称的命名系统,或者必须小心确保所有约束都有名称。

与不得不为所有ConstraintIndex对象分配显式名称相比,可以使用事件构建自动命名方案。这种方法的优点是,约束将获得一致的命名方案,无需在代码中的所有位置都使用显式名称参数,而且约定也会对由Column.uniqueColumn.index参数生成的约束和索引同样适用。从 SQLAlchemy 0.9.2 开始,包含了这种基于事件的方法,可以使用参数MetaData.naming_convention进行配置。

为 MetaData 集合配置命名约定

MetaData.naming_convention 指的是一个字典,接受 Index 类或单独的 Constraint 类作为键,并接受 Python 字符串模板作为值。它还接受一系列字符串代码作为替代键,分别为外键、主键、索引、检查和唯一约束的 "fk""pk""ix""ck""uq"。在这个字典中的字符串模板在与此 MetaData 对象关联的约束或索引没有给出现有名称时使用(包括一个例外情况,即可以进一步装饰现有名称的情况)。

适用于基本情况的一个示例命名约定如下:

代码语言:javascript复制
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 时,我们可以观察到生成的名称:

代码语言:javascript复制
>>> 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 标志,这个相同的特性也会生效:

代码语言:javascript复制
>>> 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 功能时的影响是,当生成新的迁移脚本时,命名约定将是明确的:

代码语言:javascript复制
def upgrade():
    op.create_unique_constraint("uq_user_name", "user", ["name"])

上面的 "uq_user_name" 字符串是从我们的元数据中 --autogenerate 定位到的 UniqueConstraint 对象中复制的。

可用的标记包括 %(table_name)s%(referred_table_name)s%(column_0_name)s%(column_0_label)s%(column_0_key)s%(referred_column_0_name)s,以及每个的多列版本,包括 %(column_0N_name)s%(column_0_N_name)s%(referred_column_0_N_name)s,它们以带有或不带有下划线的形式呈现所有列名称。关于 MetaData.naming_convention 的文档对每个约定有进一步的详细信息。

默认命名规则

MetaData.naming_convention的默认值处理了 SQLAlchemy 长期以来的行为,即为使用Column.index参数创建的Index对象分配名称:

代码语言:javascript复制
>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})
长名称的截断

当一个生成的名称,特别是那些使用多列令牌的名称,超出了目标数据库的标识符长度限制时(例如,PostgreSQL 的限制为 63 个字符),名称将使用基于长名称的 md5 哈希的 4 字符后缀进行确定性截断。例如,以下命名约定将基于正在使用的列名称生成非常长的名称:

代码语言:javascript复制
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 个字符的名称将被截断,如下例所示:

代码语言:javascript复制
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 哈希值,并且每次都会生成相同的值,以便为给定模式生成一致的名称。

创建用于命名约定的自定义令牌

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

代码语言:javascript复制
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时,我们将获得如下名称:

代码语言:javascript复制
>>> 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 - 用于额外的用法详情以及所有可用命名组件的列表。

命名约束的重要性 - 在 Alembic 文档中。

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

命名 CHECK 约束

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

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  value  INTEGER,
  CONSTRAINT  ck_foo_value_gt_5  CHECK  (value  >  5)
)

CheckConstraint 还支持%(columns_0_name)s令牌;我们可以通过确保在约束的表达式中使用Columncolumn()元素来使用此令牌,无论是通过将约束声明为表的一部分:

代码语言:javascript复制
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()内联:

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  value  INTEGER,
  CONSTRAINT  ck_foo_value  CHECK  (value  >  5)
)

对“列零”的名称确定是通过扫描给定表达式以查找列对象进行的。如果表达式中存在多个列,则扫描会使用确定性搜索,但是表达式的结构将确定哪一列被指定为“列零”。 ### 对布尔、枚举和其他模式类型进行命名配置

SchemaType 类引用诸如 BooleanEnum 之类的类型对象,这些对象生成伴随类型的 CHECK 约束。此处约束的名称最直接通过发送“name”参数设置,例如 Boolean.name

代码语言:javascript复制
Table("foo", metadata_obj, Column("flag", Boolean(name="ck_foo_flag")))

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

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  flag  BOOL,
  CONSTRAINT  ck_foo_flag_bool  CHECK  (flag  IN  (0,  1))
)

SchemaType 类使用特殊的内部符号,以便命名约定仅在 DDL 编译时确定。在 PostgreSQL 上,有一个原生的 BOOLEAN 类型,因此不需要 Boolean 的 CHECK 约束;我们可以安全地设置 Boolean 类型而不需要名称,即使对于检查约束已经设置了命名约定。如果我们在没有原生 BOOLEAN 类型的数据库上运行,例如 SQLite 或 MySQL,则仅会查阅此约定以获取 CHECK 约束。

CHECK 约束也可以使用column_0_name令牌,与SchemaType非常匹配,因为这些约束只有一列:

代码语言:javascript复制
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})

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

上述模式将产生:

代码语言:javascript复制
CREATE  TABLE  foo  (
  flag  BOOL,
  CONSTRAINT  ck_foo_flag  CHECK  (flag  IN  (0,  1))
)
使用 ORM 声明性混合物时使用命名约定

当使用命名约定功能与 ORM 声明式 Mixins 时,每个实际表映射子类必须存在单独的约束对象。有关背景和示例,请参阅使用命名约定在 Mixins 上创建索引和约束的部分。

配置 MetaData 集合的命名约定

MetaData.naming_convention指的是一个字典,接受Index类或个别Constraint类作为键,以及 Python 字符串模板作为值。它还接受一系列字符串代码作为替代键,分别为外键、主键、索引、检查和唯一约束的 "fk""pk""ix""ck""uq"。这个字典中的字符串模板在与这个MetaData对象相关联的约束或索引没有给出现有名称时使用(包括一个现有名称可以进一步修饰的例外情况)。

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

代码语言:javascript复制
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时,我们可以观察到生成的名称。

代码语言:javascript复制
>>> 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标志,同样的特性也会生效:

代码语言:javascript复制
>>> 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 特性时,这个效果是命名约定在生成新的迁移脚本时将是明确的:

代码语言:javascript复制
def upgrade():
    op.create_unique_constraint("uq_user_name", "user", ["name"])

上述"uq_user_name"字符串是从我们的元数据中--autogenerate定位到的UniqueConstraint对象中复制的。

可用的标记包括%(table_name)s%(referred_table_name)s%(column_0_name)s%(column_0_label)s%(column_0_key)s%(referred_column_0_name)s,以及每个的多列版本,包括%(column_0N_name)s%(column_0_N_name)s%(referred_column_0_N_name)s,它们用下划线分隔或不分隔所有列名。有关MetaData.naming_convention的文档还详细介绍了每个约定。

默认命名约定

MetaData.naming_convention的默认值处理了 SQLAlchemy 的长期行为,即为使用Column.index参数创建的Index对象分配名称:

代码语言:javascript复制
>>> from sqlalchemy.sql.schema import DEFAULT_NAMING_CONVENTION
>>> DEFAULT_NAMING_CONVENTION
immutabledict({'ix': 'ix_%(column_0_label)s'})
截断长名称

当生成的名称特别是那些使用多列令牌的名称,超出目标数据库的标识符长度限制时(例如,PostgreSQL 的限制为 63 个字符),名称将使用基于长名称的 md5 哈希的 4 字符后缀进行确定性截断。例如,给定以下命名约定,根据使用的列名称,将生成非常长的名称:

代码语言:javascript复制
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 个字符的将被截断,如以下示例所示:

代码语言:javascript复制
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 哈希值,并且每次生成相同的值,以便为给定模式生成一致的名称。

创建自定义令牌以用于命名约定

也可以通过在 naming_convention 字典中指定额外的令牌和可调用对象来添加新令牌。例如,如果我们想要使用 GUID 方案为外键约束命名,我们可以这样做:

代码语言:javascript复制
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时,我们将得到以下名称:

代码语言:javascript复制
>>> 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 - 有关更多使用详细信息以及所有可用命名组件的列表。

命名约束的重要性 - Alembic 文档中的内容。

从版本 1.3.0 开始:添加了多列命名令牌,例如%(column_0_N_name)s。生成的名称如果超过目标数据库的字符限制,将被确定性地截断。

命名 CHECK 约束

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

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  value  INTEGER,
  CONSTRAINT  ck_foo_value_gt_5  CHECK  (value  >  5)
)

CheckConstraint还支持%(columns_0_name)s令牌;我们可以通过确保在约束表达式中使用Columncolumn()元素来利用这一点,无论是通过单独声明约束还是通过在表内:

代码语言:javascript复制
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()内联:

代码语言:javascript复制
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的内容:

代码语言:javascript复制
CREATE  TABLE  foo  (
  value  INTEGER,
  CONSTRAINT  ck_foo_value  CHECK  (value  >  5)
)

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

针对布尔型、枚举型和其他模式类型进行命名配置

SchemaType类引用诸如BooleanEnum之类的类型对象,这些对象生成伴随类型的 CHECK 约束。此处约束的名称最直接通过发送“name”参数设置,例如Boolean.name

代码语言:javascript复制
Table("foo", metadata_obj, Column("flag", Boolean(name="ck_foo_flag")))

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

代码语言:javascript复制
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

代码语言:javascript复制
CREATE  TABLE  foo  (
  flag  BOOL,
  CONSTRAINT  ck_foo_flag_bool  CHECK  (flag  IN  (0,  1))
)

SchemaType类使用特殊的内部符号,以便命名约定仅在 DDL 编译时确定。在 PostgreSQL 上,有一种原生的 BOOLEAN 类型,因此不需要Boolean的 CHECK 约束;即使有检查约定,我们也可以安全地设置一个不带名称的Boolean类型。只有在没有原生 BOOLEAN 类型的数据库(如 SQLite 或 MySQL)上运行时,才会咨询此约定以进行 CHECK 约束。

CHECK 约束也可以使用column_0_name令牌,这与SchemaType非常匹配,因为这些约束只有一个列:

代码语言:javascript复制
metadata_obj = MetaData(naming_convention={"ck": "ck_%(table_name)s_%(column_0_name)s"})

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

上述模式将产生:

代码语言:javascript复制
CREATE  TABLE  foo  (
  flag  BOOL,
  CONSTRAINT  ck_foo_flag  CHECK  (flag  IN  (0,  1))
)
使用 ORM 声明性 Mixin 配置命名约定

在使用命名约定功能与 ORM 声明性混合时,每个实际表映射的子类必须存在单独的约束对象。有关背景和示例,请参见使用命名约定在混合上创建索引和约束部分。

约束 API

对象名称

描述

检查约束

表级或列级检查约束。

列集合约束

代理列集合的约束。

ColumnCollectionMixin

一个ColumnCollection对象的Column集合。

约束

表级 SQL 约束。

conv

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

外键

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

外键约束

表级外键约束。

具有条件 DDL

定义一个包括HasConditionalDDL.ddl_if()方法的类,允许对 DDL 进行条件渲染。

主键约束

表级主键约束。

唯一约束

表级唯一约束。

代码语言:javascript复制
class sqlalchemy.schema.Constraint

表级 SQL 约束。

Constraint作为可以与Table对象关联的一系列约束对象的基类,包括PrimaryKeyConstraintForeignKeyConstraintUniqueConstraintCheckConstraint

成员

init(), argument_for(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.Constraint (sqlalchemy.sql.base.DialectKWArgs, sqlalchemy.schema.HasConditionalDDL, sqlalchemy.schema.SchemaItem)

代码语言:javascript复制
method __init__(name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, comment: str | None = None, _create_rule: Any | None = None, _type_bound: bool = False, **dialect_kw: Any) → None

创建一个 SQL 约束。

参数:

  • name – 可选的,这个 Constraint 在数据库中的名称。
  • deferrable – 可选布尔值。如果设置,当为这个约束发出 DDL 时,会发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,当为这个约束发出 DDL 时,会发出 INITIALLY 。
  • info – 可选的数据字典,将被填充到此对象的 SchemaItem.info 属性中。
  • comment – 在外键约束创建时渲染 SQL 注释的可选字符串。 新版本 2.0 中新增。
  • **dialect_kw – 附加的关键字参数是方言特定的,并以 <dialectname>_<argname> 的形式传递。有关每个方言的文档参数的详细信息,请参见 Dialects 中的文档。
  • _create_rule – 由一些也创建约束的数据类型内部使用。
  • _type_bound – 用于内部指示此约束与特定数据类型相关联。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
method copy(**kw: Any) → Self

从 1.4 版开始已弃用:Constraint.copy()方法已弃用,并将在未来的版本中移除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

将条件 DDL 规则应用于此模式项。

这些规则的工作方式类似于ExecutableDDLElement.execute_if()可调用对象,但增加了一个特性,即可以在 DDL 编译阶段为CreateTable等结构检查条件。HasConditionalDDL.ddl_if()目前适用于Index结构以及所有Constraint结构。

参数:

  • dialect – 方言的字符串名称,或者表示多个方言类型的字符串名称元组。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_描述的相同形式构造的可调用对象。
  • state – 如果存在,则将传递给可调用对象的任意对象。

2.0 版中的新功能。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这些参数以原始的 <dialect>_<kwarg> 格式呈现在这里。仅包括实际传递的参数;不像DialectKWArgs.dialect_options 集合那样,它包含了该方言已知的所有选项,包括默认值。

该集合也是可写的;键的形式为 <dialect>_<kwarg>,其中的值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

在版本 0.9.2 中新增。

另请参阅

DialectKWArgs.dialect_kwargs - 扁平字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

与对象相关联的信息字典,允许将用户定义的数据与此SchemaItem 关联起来。

字典在首次访问时会自动生成。它也可以在某些对象的构造函数中指定,比如TableColumn

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

一个与DialectKWArgs.dialect_kwargs 同义的词语。

代码语言:javascript复制
class sqlalchemy.schema.ColumnCollectionMixin

一个Column对象的ColumnCollection

此集合代表此对象引用的列。

代码语言:javascript复制
class sqlalchemy.schema.ColumnCollectionConstraint

代理列集合的约束。

成员

init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

class sqlalchemy.schema.ColumnCollectionConstraint (sqlalchemy.schema.ColumnCollectionMixin, sqlalchemy.schema.Constraint)

代码语言:javascript复制
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None

参数:

  • *columns – 一系列列名或列对象。
  • name – 可选,此约束在数据库中的名称。
  • deferrable – 可选布尔值。如果设置,当为此约束发���DDL 时,发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,当为此约束发出 DDL 时,发出 INITIALLY 。
  • **dialect_kw – 其他关键字参数,包括方言特定参数,将传播到Constraint超类。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs DialectKWArgs.argument_for() 方法

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin.columns 属性,来自于 ColumnCollectionMixin

一个 ColumnCollection 表示这个约束的列集合。

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

如果此约束包含给定的列,则返回 True。

注意,此对象还包含一个属性 .columns,它是一个 ColumnCollection,包含了 Column 对象。

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint

从版本 1.4 开始不推荐使用:ColumnCollectionConstraint.copy() 方法已弃用,将在未来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法,来自于 HasConditionalDDL

为此模式项应用条件性 DDL 规则。

这些规则的工作方式类似于 ExecutableDDLElement.execute_if() 可调用对象,额外的功能是可以在 DDL 编译阶段检查条件,例如 CreateTable 这样的结构。 HasConditionalDDL.ddl_if() 目前也适用于 Index 结构以及所有 Constraint 结构。

参数:

  • dialect – 方言的字符串名称,或指示多个方言类型的字符串名称的元组。
  • callable_ – 一个可调用对象,其构造方式与 ExecutableDDLElement.execute_if.callable_ 中描述的形式相同。
  • state – 如果存在,将传递给可调用对象的任意对象。

新版本 2.0 中新增。

另请参阅

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

DialectKWArgs.dialect_kwargs 属性继承

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

这里的参数以其原始 <dialect>_<kwarg> 格式呈现。只包括实际传递的参数;与 DialectKWArgs.dialect_options 集合不同,后者包含此方言知道的所有选项,包括默认值。

此集合也是可写的;接受形式为 <dialect>_<kwarg> 的键,其值将组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

DialectKWArgs.dialect_options 属性继承

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

新版本 0.9.2 中新增。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
class sqlalchemy.schema.CheckConstraint

表或列级别的 CHECK 约束。

可以包含在表或列的定义中。

成员

init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.CheckConstraint (sqlalchemy.schema.ColumnCollectionConstraint)

代码语言:javascript复制
method __init__(sqltext: _TextCoercedExpressionArgument[Any], name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, table: Table | None = None, info: _InfoType | None = None, _create_rule: Any | None = None, _autoattach: bool = True, _type_bound: bool = False, **dialect_kw: Any) → None

构造一个 CHECK 约束。

参数:

sqltext

包含约束定义的字符串,将直接使用,或者是一个 SQL 表达式构造。如果给定为字符串,则对象将转换为 text() 对象。如果文本字符串包含冒号字符,请使用反斜杠进行转义:

代码语言:javascript复制
CheckConstraint(r"foo ~ E'a(?:b|c)d")

警告

CheckConstraintCheckConstraint.sqltext 参数可以作为 Python 字符串参数传递,该字符串参数将被视为可信任的 SQL 文本并按照给定的方式呈现。不要将不受信任的输入传递给此参数

name – 可选,约束的数据库中名称。

deferrable – 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。

initially – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。

info – 可选数据字典,将填充到此对象的SchemaItem.info属性中。

代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs 类的 DialectKWArgs.argument_for() 方法

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin ColumnCollectionMixin.columns 属性

表示此约束的列集合。

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

继承自 ColumnCollectionConstraint ColumnCollectionConstraint.contains_column() 方法

如果此约束包含给定列,则返回 True。

请注意,此对象还包含一个属性 .columns,它是 Column 对象的 ColumnCollection

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → CheckConstraint

自版本 1.4 弃用:CheckConstraint.copy() 方法已弃用,将在未来的版本中移除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL HasConditionalDDL.ddl_if() 方法

将条件 DDL 规则应用于此模式项。

这些规则的工作方式与 ExecutableDDLElement.execute_if() 可调用对象类似,额外的功能是可以在 DDL 编译阶段检查标准,例如 CreateTable 构造。 HasConditionalDDL.ddl_if() 目前也适用于 Index 构造以及所有 Constraint 构造。

参数:

  • dialect – 方言的字符串名称,或字符串名称的元组,以指示多个方言类型。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_中描述的相同形式构建的可调用对象。
  • state – 将传递给可调用对象的任意对象(如果存在)。

自版本 2.0 新增。

另请参阅

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以其原始 <dialect>_<kwarg> 格式呈现。仅包含实际传递的参数;不像 DialectKWArgs.dialect_options 集合,该集合包含此方言已知的所有选项,包括默认值。

该集合也是可写的;接受的键的形式为 <dialect>_<kwarg>,其中值将被组装成选项列表。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中新增。

另请参阅

DialectKWArgs.dialect_kwargs - 扁平字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
class sqlalchemy.schema.ForeignKey

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

ForeignKey 被指定为 Column 对象的参数,例如:

代码语言:javascript复制
t = Table("remote_table", metadata,
    Column("remote_id", ForeignKey("main_table.id"))
)

请注意,ForeignKey 仅是一个标记对象,定义了两列之间的依赖关系。在所有情况下,实际约束都由 ForeignKeyConstraint 对象表示。当ForeignKey与一个 Column 相关联,而这个列又与一个 Table 相关联时,此对象将自动生成。反之,当 ForeignKeyConstraint 应用于一个 Table 时,ForeignKey 标记将自动在每个相关联的 Column 上存在,这些列也与约束对象相关联。

请注意,您不能使用 ForeignKey 对象定义“复合”外键约束,即多个父/子列的分组约束。要定义此分组,必须使用 ForeignKeyConstraint 对象,并应用于 Table。相关联的ForeignKey对象将自动创建。

与单个 Column 对象相关联的 ForeignKey 对象可在该列的 foreign_keys 集合中找到。

关于外键配置的更多示例在定义外键中。

成员

init(), argument_for(), column, copy(), dialect_kwargs, dialect_options, get_referent(), info, kwargs, references(), target_fullname

类签名

sqlalchemy.schema.ForeignKey (sqlalchemy.sql.base.DialectKWArgs, sqlalchemy.schema.SchemaItem)

代码语言:javascript复制
method __init__(column: _DDLColumnArgument, _constraint: ForeignKeyConstraint | None = None, use_alter: bool = False, name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, link_to_name: bool = False, match: str | None = None, info: _InfoType | None = None, comment: str | None = None, _unresolvable: bool = False, **dialect_kw: Any)

构建一个列级的外键。

构造时生成 ForeignKey 对象,与父 Table 对象的约束集合关联的 ForeignKeyConstraint

参数:

  • column – 键关系的单个目标列。Column 对象或列名称字符串:tablename.columnkeyschema.tablename.columnkeycolumnkey 是分配给列的 key(默认为列名称本身),除非 link_to_nameTrue,此时使用列的呈现名称。
  • name – 可选字符串。如果未提供约束,则键的数据库名称。
  • onupdate – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON UPDATE 。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • ondelete – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON DELETE 。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • deferrable – 可选布尔值。如果设置,则在为此约束发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。
  • link_to_name – 如果为 True,则 column 中给定的字符串名称是引用列的呈现名称,而不是其本地分配的 key
  • use_alter – 传递给底层 ForeignKeyConstraint,以指示约束应从 CREATE TABLE/ DROP TABLE 语句外部生成/删除。有关详细描述,请参阅 ForeignKeyConstraint.use_alter。 另请参阅 ForeignKeyConstraint.use_alter 通过 ALTER 创建/删除外键约束
  • match – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 MATCH 。典型值包括 SIMPLE、PARTIAL 和 FULL。
  • info – 可选数据字典,将填充到此对象的 SchemaItem.info 属性中。
  • comment – 可选字符串,将在创建外键约束时呈现 SQL 注释。 版本 2.0 中的新内容。
  • **dialect_kw – 附加的关键字参数是方言特定的,并以 <dialectname>_<argname> 的形式传递。这些参数最终由相应的 ForeignKeyConstraint 处理。有关文档化参数的详细信息,请参阅 Dialects 中关于各个方言的文档。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

DialectKWArgs DialectKWArgs.argument_for() 方法继承

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute column

返回由此 ForeignKey 引用的目标 Column

如果没有建立目标列,则会引发异常。

代码语言:javascript复制
method copy(*, schema: str | None = None, **kw: Any) → ForeignKey

自版本 1.4 起弃用:ForeignKey.copy() 方法已弃用,并将在未来版本中移除。

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

这是作为方言特定选项指定的关键字参数的集合。

这些参数以原始的 <dialect>_<kwarg> 格式显示在此处。仅包括实际传递的参数;与 DialectKWArgs.dialect_options 不同,后者包含此方言已知的所有选项,包括默认值。

该集合也是可写的;接受形式为 <dialect>_<kwarg> 的键,其中值将被组装成选项列表。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

这是作为方言特定选项指定的关键字参数的集合。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

新版本为 0.9.2。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
method get_referent(table: FromClause) → Column[Any] | None

返回由此 ForeignKey 引用的给定 Table(或任何 FromClause)中的 Column

如果此 ForeignKey 未引用给定的 Table,则返回 None。

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

DialectKWArgs.kwargs 属性继承 DialectKWArgs

DialectKWArgs.dialect_kwargs的同义词。

代码语言:javascript复制
method references(table: Table) → bool

如果给定的Table被此ForeignKey引用,则返回 True。

代码语言:javascript复制
attribute target_fullname

为此ForeignKey返回基于字符串的“列规范”。

这通常是传递给对象构造函数的基于字符串的“tablename.colname”参数的等效值。

代码语言:javascript复制
class sqlalchemy.schema.ForeignKeyConstraint

表级外键约束。

定义单列或复合外键引用约束。对于简单的、单列外键,向Column的定义中添加一个ForeignKey是一个简写等效于未命名的、单列ForeignKeyConstraint

外键配置示例在定义外键中。

成员

init(), argument_for(), column_keys, columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, elements, info, kwargs, referred_table

类签名

sqlalchemy.schema.ForeignKeyConstraintsqlalchemy.schema.ColumnCollectionConstraint

代码语言:javascript复制
method __init__(columns: _typing_Sequence[_DDLColumnArgument], refcolumns: _typing_Sequence[_DDLColumnArgument], name: _ConstraintNameArgument = None, onupdate: str | None = None, ondelete: str | None = None, deferrable: bool | None = None, initially: str | None = None, use_alter: bool = False, link_to_name: bool = False, match: str | None = None, table: Table | None = None, info: _InfoType | None = None, comment: str | None = None, **dialect_kw: Any) → None

构造一个支持复合的外键。

参数:

  • columns – 本地列名称的序列。这些命名列必须在父表中定义并存在。除非 link_to_name 为 True,否则名称应与每个列(默认为名称)给定的 key 匹配。
  • refcolumns – 外键列名称或 Column 对象的序列。这些列必须全部位于同一个表中。
  • name – 可选项,键的数据库内名称。
  • onupdate – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON UPDATE 。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • ondelete – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 ON DELETE 。典型值包括 CASCADE、DELETE 和 RESTRICT。
  • deferrable – 可选布尔值。如果设置,则在发出 DDL 时发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 INITIALLY 。
  • link_to_name – 如果为 True,则 column 中给定的字符串名称是引用列的渲染名称,而不是其在本地分配的 key
  • use_alter – 如果为 True,则不会将此约束的 DDL 作为 CREATE TABLE 定义的一部分发出。相反,在完整的表集合创建之后,通过 ALTER TABLE 语句生成它,并在删除完整的表集合之前通过 ALTER TABLE 语句将其删除。 使用 ForeignKeyConstraint.use_alter 特别适用于两个或多个表在相互依赖的外键约束关系中建立的情况;但是,MetaData.create_all()MetaData.drop_all() 方法将自动执行此解析,因此通常不需要此标志。 另请参阅 通过 ALTER 创建/删除外键约束
  • match – 可选字符串。如果设置,则在为此约束发出 DDL 时发出 MATCH 。典型值包括 SIMPLE、PARTIAL 和 FULL。
  • info – 将填充到此对象的 SchemaItem.info 属性中的可选数据字典。
  • comment – 在外键约束创建时渲染一个 SQL 注释的可选字符串。 在 2.0 版中新增。
  • **dialect_kw – 额外的关键字参数是方言特定的,并以 <方言名称>_<参数名称> 的形式传递。有关文档化参数的详细信息,请参阅方言中有关各个方言的文档。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs DialectKWArgs.argument_for() 方法

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute column_keys

返回一个字符串键列表,表示此ForeignKeyConstraint中的本地列。

此列表是发送到ForeignKeyConstraint构造函数的原始字符串参数,或者如果约束已使用Column对象初始化,则是每个元素的字符串.key

代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin.columns 属性

代表此约束的ColumnCollection表示列的集合。

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

继承自 ColumnCollectionConstraint.contains_column() 方法的 ColumnCollectionConstraint

如果此约束包含给定列,则返回 True。

请注意,这个对象还包含一个属性.columns,它是一个ColumnCollection对象的集合,其中包含Column对象。

代码语言:javascript复制
method copy(*, schema: str | None = None, target_table: Table | None = None, **kw: Any) → ForeignKeyConstraint

自版本 1.4 弃用:ForeignKeyConstraint.copy()方法已弃用,并将在将来的版本中移除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

将条件 DDL 规则应用于此模式项。

这些规则的工作方式类似于ExecutableDDLElement.execute_if()可调用对象,只是增加了一个特性,即在 DDL 编译阶段可以检查条件,例如CreateTable构造。HasConditionalDDL.ddl_if()当前还适用于Index构造以及所有Constraint构造。

参数:

  • dialect – 方言的字符串名称,或者一个字符串名称的元组,表示多个方言类型。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_描述的相同形式构造的可调用对象。
  • state – 任意的对象,如果存在,将传递给可调用对象。

从版本 2.0 开始新添加。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以其原始<dialect>_<kwarg>格式呈现。仅包含实际传递的参数;与DialectKWArgs.dialect_options集合不同,后者包含此方言已知的所有选项,包括默认值。

该集合也是可写的;键采用<dialect>_<kwarg>的形式,其中值将被组装成选项列表。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

从版本 0.9.2 开始。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute elements: List[ForeignKey]

一系列ForeignKey对象。

每个ForeignKey代表单个引用列/被引用列对。

此集合旨在为只读。

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性,属于 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
attribute referred_table

ForeignKeyConstraint 引用的 Table 对象。

这是一个动态计算的属性,如果约束和/或父表尚未与包含所引用表的元数据集关联,则可能不可用。

代码语言:javascript复制
class sqlalchemy.schema.HasConditionalDDL

定义一个包含 HasConditionalDDL.ddl_if() 方法的类,允许对 DDL 进行条件渲染。

目前适用于约束和索引。

成员

ddl_if()

版本 2.0 中新增。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

将一个条件 DDL 规则应用到此模式项。

这些规则的工作方式与 ExecutableDDLElement.execute_if() 可调用对象类似,但增加了一个功能,即可以在 DDL 编译阶段检查条件,例如 CreateTableHasConditionalDDL.ddl_if() 目前也适用于 Index 构造以及所有 Constraint 构造。

参数:

  • dialect – 方言的字符串名称,或字符串名称的元组,表示多个方言类型。
  • callable_ – 使用与 ExecutableDDLElement.execute_if.callable_ 描述的形式构建的可调用对象。
  • state – 如果存在,将传递给可调用对象的任意对象。

版本 2.0 中新增。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
class sqlalchemy.schema.PrimaryKeyConstraint

表级主键约束。

PrimaryKeyConstraint 对象会自动出现在任何 Table 对象上;它被分配一组与标记为 Column.primary_key 标志相对应的 Column 对象:

代码语言:javascript复制
>>> my_table = Table('mytable', metadata,
...                 Column('id', Integer, primary_key=True),
...                 Column('version_id', Integer, primary_key=True),
...                 Column('data', String(50))
...     )
>>> my_table.primary_key
PrimaryKeyConstraint(
 Column('id', Integer(), table=<mytable>,
 primary_key=True, nullable=False),
 Column('version_id', Integer(), table=<mytable>,
 primary_key=True, nullable=False)
)

Table 的主键也可以通过显式使用 PrimaryKeyConstraint 对象来指定;在这种用法模式下,“约束”的“名称”也可以指定,以及方言可能识别的其他选项:

代码语言:javascript复制
my_table = Table('mytable', metadata,
            Column('id', Integer),
            Column('version_id', Integer),
            Column('data', String(50)),
            PrimaryKeyConstraint('id', 'version_id',
                                 name='mytable_pk')
        )

两种列规范样式通常不应混合使用。如果 PrimaryKeyConstraint 中存在的列与标记为 primary_key=True 的列不匹配,则会发出警告,如果两者都存在;在这种情况下,列严格来自 PrimaryKeyConstraint 声明,并且其他标记为 primary_key=True 的列将被忽略。这种行为旨在与先前的行为向后兼容。

对于需要在 PrimaryKeyConstraint 上指定特定选项的用例,但仍然希望使用 primary_key=True 标志的常规样式的情况,可以指定一个空的 PrimaryKeyConstraint,它将从基于标志的 Table 中采用主键列集合:

代码语言:javascript复制
my_table = Table('mytable', metadata,
            Column('id', Integer, primary_key=True),
            Column('version_id', Integer, primary_key=True),
            Column('data', String(50)),
            PrimaryKeyConstraint(name='mytable_pk',
                                 mssql_clustered=True)
        )

成员

argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.PrimaryKeyConstraintsqlalchemy.schema.ColumnCollectionConstraint

代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

继承自 ColumnCollectionMixin.columns 属性的 ColumnCollectionMixin

表示此约束的列集合的 ColumnCollection

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

继承自 ColumnCollectionConstraint.contains_column() 方法的 ColumnCollectionConstraint

如果此约束包含给定列,则返回 True。

请注意,此对象还包含一个名为.columns的属性,它是Column对象的ColumnCollection

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint

继承自 ColumnCollectionConstraint.copy() 方法的 ColumnCollectionConstraint

自版本 1.4 起弃用:ColumnCollectionConstraint.copy()方法已弃用,并将在将来的版本中移除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法的 HasConditionalDDL

对此模式项应用条件 DDL 规则。

这些规则的工作方式类似于ExecutableDDLElement.execute_if()可调用对象,额外的特性是可以在 DDL 编译阶段检查条件,例如CreateTable这样的构造函数。HasConditionalDDL.ddl_if()目前也适用于Index构造以及所有Constraint构造。

参数:

  • dialect – 方言的字符串名称,或表示多个方言类型的字符串名称元组。
  • callable_ – 使用与ExecutableDDLElement.execute_if.callable_中描述的相同形式构造的可调用对象。
  • state – 如果存在,将传递给可调用对象的任意对象。

从版本 2.0 开始新增。

另请参阅

控制约束和索引的 DDL 生成 - 背景和使用示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以其原始<dialect>_<kwarg>格式呈现。仅包括实际传递的参数;不像DialectKWArgs.dialect_options集合,该集合包含此方言已知的所有选项,包括默认值。

该集合也是可写的;接受形式为<dialect>_<kwarg>的键,其中值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

新版本中新增的功能为 0.9.2。

另请参阅

DialectKWArgs.dialect_kwargs - 平面字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
class sqlalchemy.schema.UniqueConstraint

表级别的唯一约束。

定义单列或复合唯一约束。对于简单的单列约束,将unique=True添加到Column定义中相当于未命名的单列 UniqueConstraint 的简写等效形式。

成员

init(), argument_for(), columns, contains_column(), copy(), ddl_if(), dialect_kwargs, dialect_options, info, kwargs

类签名

sqlalchemy.schema.UniqueConstraint (sqlalchemy.schema.ColumnCollectionConstraint)

代码语言:javascript复制
method __init__(*columns: _DDLColumnArgument, name: _ConstraintNameArgument = None, deferrable: bool | None = None, initially: str | None = None, info: _InfoType | None = None, _autoattach: bool = True, _column_flag: bool = False, _gather_expressions: List[_DDLColumnArgument] | None = None, **dialect_kw: Any) → None

继承自 sqlalchemy.schema.ColumnCollectionConstraint.__init__ 方法的 ColumnCollectionConstraint

参数:

  • *columns – 列名或列对象的序列。
  • name – 可选,此约束的数据库中的名称。
  • deferrable – 可选布尔值。 如果设置,为此约束发出 DEFERRABLE 或 NOT DEFERRABLE。
  • initially – 可选字符串。 如果设置,发出 INITIALLY when 为此约束发出 DDL。
  • **dialect_kw – 其他关键字参数,包括方言特定参数,将传递给Constraint超类。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 – 参数的默认值。
代码语言:javascript复制
attribute columns: ReadOnlyColumnCollection[str, Column[Any]]

ColumnCollectionMixin .columns 属性继承

代表此约束的一组列的 ColumnCollection

代码语言:javascript复制
method contains_column(col: Column[Any]) → bool

ColumnCollectionConstraint ColumnCollectionConstraint.contains_column() 方法继承

如果此约束包含给定列,则返回 True。

请注意,此对象还包含一个名为.columns的属性,它是 Column 对象的 ColumnCollection

代码语言:javascript复制
method copy(*, target_table: Table | None = None, **kw: Any) → ColumnCollectionConstraint

ColumnCollectionConstraint ColumnCollectionConstraint.copy() 方法继承

自版本 1.4 起已弃用:ColumnCollectionConstraint.copy() 方法已弃用,并将在将来的版本中删除。

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

HasConditionalDDL HasConditionalDDL.ddl_if() 方法继承

对此模式项目应用条件 DDL 规则。

这些规则的工作方式类似于ExecutableDDLElement.execute_if()可调用对象,额外的特性是在 DDL 编译阶段可以检查条件,例如CreateTable构造中。HasConditionalDDL.ddl_if() 目前也适用于Index构造以及所有Constraint构造。

参数:

  • dialect – 方言的字符串名称,或者字符串名称的元组,表示多个方言类型。
  • callable_ – 一个可调用对象,其构造方式与ExecutableDDLElement.execute_if.callable_中描述的形式相同。
  • state – 任意对象,如果存在将传递给可调用对象。

新版本 2.0。

另请参阅

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

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

这里的参数以其原始的<dialect>_<kwarg>格式呈现。仅包括实际传递的参数;不像DialectKWArgs.dialect_options集合,该集合包含此方言已��的所有选项,包括默认值。

该集合也是可写的;键的形式为<dialect>_<kwarg>,其中值将被组装到选项列表中。

另请参阅

DialectKWArgs.dialect_options - 嵌套字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

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

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

新版本 0.9.2。

另请参阅

DialectKWArgs.dialect_kwargs - 平坦的字典形式

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

代码语言:javascript复制
function sqlalchemy.schema.conv(value: str, quote: bool | None = None) → Any

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

这是一个字符串子类,表示不应再受任何其他命名约定影响的名称。

例如 当我们使用以下命名约定创建 Constraint 时:

代码语言:javascript复制
m = MetaData(naming_convention={
    "ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
                CheckConstraint('x > 5', name='x5'))

上述约束的名称将呈现为 "ck_t_x5"。即,现有名称 x5 被用作命名约定中的 constraint_name 令牌。

在某些情况下,例如在迁移脚本中,我们可能会渲染上述 CheckConstraint 的名称已经被转换了。为了确保名称不会被双重修改,新名称使用 conv() 标记应用。我们可以明确使用如下:

代码语言:javascript复制
m = MetaData(naming_convention={
    "ck": "ck_%(table_name)s_%(constraint_name)s"
})
t = Table('t', m, Column('x', Integer),
                CheckConstraint('x > 5', name=conv('ck_t_x5')))

在上面的例子中,conv() 标记表示此处的约束名称是最终的,名称将呈现为 "ck_t_x5" 而不是 "ck_t_ck_t_x5"

另请参阅

配置约束命名约定

索引

索引可以匿名创建(使用自动生成的名称 ix_<column label>)为单列使用内联 index 关键字,在 Column 上,该关键字也修改了 unique 的用法,将唯一性应用于索引本身,而不是添加一个单独的 UNIQUE 约束。对于具有特定名称或涵盖多个列的索引,请使用 Index 结构,该结构需要一个名称。

下面我们展示了一个具有多个关联 Index 对象的 Table。DDL 为“CREATE INDEX”在表的创建语句之后发布:

代码语言:javascript复制
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)

mytable.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 内部“内联”定义,使用字符串名称来标识列:

代码语言:javascript复制
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() 方法:

代码语言:javascript复制
i = Index("someindex", mytable.c.col5)
i.create(engine)
CREATE  INDEX  someindex  ON  mytable  (col5) 
函数索引

Index 支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 ColumnElement.desc() 修改器:

代码语言:javascript复制
from sqlalchemy import Index

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

或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower() 函数创建“不区分大小写”的索引:

代码语言:javascript复制
from sqlalchemy import func, Index

Index("someindex", func.lower(mytable.c.somecol))
```### 函数索引

`Index` 支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 `ColumnElement.desc()` 修改器:

```py
from sqlalchemy import Index

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

或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower() 函数创建“不区分大小写”的索引:

代码语言:javascript复制
from sqlalchemy import func, Index

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

索引 API

对象名称

描述

索引

一个表级索引。

代码语言:javascript复制
class sqlalchemy.schema.Index

一个表级索引。

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

例如:

代码语言:javascript复制
sometable = Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100))
            )

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

对于一个简单的、单列索引,添加 Column 也支持 index=True

代码语言:javascript复制
sometable = Table("sometable", metadata,
                Column("name", String(50), index=True)
            )

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

代码语言:javascript复制
Index("some_index", sometable.c.name, sometable.c.address)

功能性索引也得到支持,通常通过与绑定到表的Column对象一起使用func构造来实现:

代码语言:javascript复制
Index("some_index", func.lower(sometable.c.name))

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

代码语言:javascript复制
Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100)),
                Index("some_index", "name", "address")
        )

要支持此形式中的功能性或基于表达式的索引,可以使用text()构造:

代码语言:javascript复制
from sqlalchemy import text

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

另请参阅

索引 - 有关Index的一般信息。

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

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

集群索引支持 - MSSQL 特定选项适用于Index构造。

成员

init(), argument_for(), create(), ddl_if(), dialect_kwargs, dialect_options, drop(), info, kwargs

类签名

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

代码语言:javascript复制
method __init__(name: str | None, *expressions: _DDLColumnArgument, unique: bool = False, quote: bool | None = None, info: _InfoType | None = None, _table: Table | None = None, _column_flag: bool = False, **dialect_kw: Any) → None

构造一个索引对象。

参数:

  • name – 索引的名称
  • *expressions – 要包含在索引中的列表达式。这些表达式通常是Column的实例,但也可以是最终指向Column的任意 SQL 表达式。
  • unique=False – 仅限关键字参数;如果为 True,则创建一个唯一索引。
  • quote=None – 仅限关键字参数;是否对索引的名称应用引号。工作方式与Column.quote相同。
  • info=None – 可选数据字典,将填充到此对象的SchemaItem.info 属性中。
  • **dialect_kw – 上述未提及的额外关键字参数是方言特定的,并以<dialectname>_<argname>的形式传递。有关个别方言的文档参数的详细信息,请参阅方言的文档。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 - 参数的默认值。
代码语言:javascript复制
method create(bind: _CreateDropBind, checkfirst: bool = False) → None

对于此 Index,使用给定的 ConnectionEngine 发出 CREATE 语句以进行连接。

参见

MetaData.create_all()

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法 HasConditionalDDL

将条件 DDL 规则应用于此模式项。

这些规则的工作方式类似于 ExecutableDDLElement.execute_if() 可调用对象,其附加功能是可以在 DDL 编译阶段检查条件,例如 CreateTable 构造。HasConditionalDDL.ddl_if() 目前也适用于 Index 构造以及所有 Constraint 构造。

参数:

  • dialect - 方言的字符串名称,或一组字符串名称以指示多个方言类型。
  • callable_ - 使用与 ExecutableDDLElement.execute_if.callable_ 中描述的相同形式构造的可调用对象。
  • state - 如果存在,将传递给可调用对象的任意对象。

从版本 2.0 开始新增。

参见

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

作为方言特定选项的关键字参数集合,用于这个构造函数。

这里的参数以其原始的 <dialect>_<kwarg> 格式存在。只包括实际传递的参数;不像 DialectKWArgs.dialect_options 集合,该集合包含此方言已知的所有选项,包括默认值。

集合也是可写的;接受形式为 <dialect>_<kwarg> 的键,其值将被组装成选项列表。

另请参阅

DialectKWArgs.dialect_options - 嵌套的字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

作为方言特定选项的关键字参数集合,用于这个构造函数。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 平坦的字典形式

代码语言:javascript复制
method drop(bind: _CreateDropBind, checkfirst: bool = False) → None

使用给定的 ConnectionEngine 进行连接性,为此 Index 发出 DROP 语句。

另请参阅

MetaData.drop_all().

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。 , 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)

代码语言:javascript复制
注意,在上面的示例中,`Index` 结构是外部创建的,与其对应的表使用 `Column` 对象直接创建。`Index` 也支持在 `Table` 内部“内联”定义,使用字符串名称来标识列:

```py
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() 方法:

代码语言:javascript复制
i = Index("someindex", mytable.c.col5)
i.create(engine)
CREATE  INDEX  someindex  ON  mytable  (col5) 
函数索引

Index 支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 ColumnElement.desc() 修改器:

代码语言:javascript复制
from sqlalchemy import Index

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

或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower() 函数创建“不区分大小写”的索引:

代码语言:javascript复制
from sqlalchemy import func, Index

Index("someindex", func.lower(mytable.c.somecol))
```### 函数索引

`Index` 支持 SQL 和函数表达式,与目标后端支持的一样。要针对列使用降序值创建索引,可以使用 `ColumnElement.desc()` 修改器:

```py
from sqlalchemy import Index

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

或者使用支持函数索引的后端,比如 PostgreSQL,可以使用 lower() 函数创建“不区分大小写”的索引:

代码语言:javascript复制
from sqlalchemy import func, Index

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

索引 API

对象名称

描述

索引

一个表级索引。

代码语言:javascript复制
class sqlalchemy.schema.Index

一个表级索引。

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

例如:

代码语言:javascript复制
sometable = Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100))
            )

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

对于一个简单的、单列索引,添加 Column 也支持 index=True

代码语言:javascript复制
sometable = Table("sometable", metadata,
                Column("name", String(50), index=True)
            )

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

代码语言:javascript复制
Index("some_index", sometable.c.name, sometable.c.address)

功能性索引也得到支持,通常通过与绑定到表的Column对象一起使用func构造来实现:

代码语言:javascript复制
Index("some_index", func.lower(sometable.c.name))

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

代码语言:javascript复制
Table("sometable", metadata,
                Column("name", String(50)),
                Column("address", String(100)),
                Index("some_index", "name", "address")
        )

要支持此形式中的功能性或基于表达式的索引,可以使用text()构造:

代码语言:javascript复制
from sqlalchemy import text

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

另请参阅

索引 - 有关Index的一般信息。

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

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

集群索引支持 - MSSQL 特定选项适用于Index构造。

成员

init(), argument_for(), create(), ddl_if(), dialect_kwargs, dialect_options, drop(), info, kwargs

类签名

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

代码语言:javascript复制
method __init__(name: str | None, *expressions: _DDLColumnArgument, unique: bool = False, quote: bool | None = None, info: _InfoType | None = None, _table: Table | None = None, _column_flag: bool = False, **dialect_kw: Any) → None

构造一个索引对象。

参数:

  • name – 索引的名称
  • *expressions – 要包含在索引中的列表达式。这些表达式通常是Column的实例,但也可以是最终指向Column的任意 SQL 表达式。
  • unique=False – 仅限关键字参数;如果为 True,则创建一个唯一索引。
  • quote=None – 仅限关键字参数;是否对索引的名称应用引号。工作方式与Column.quote相同。
  • info=None – 可选数据字典,将填充到此对象的SchemaItem.info 属性中。
  • **dialect_kw – 上述未提及的额外关键字参数是方言特定的,并以<dialectname>_<argname>的形式传递。有关个别方言的文档参数的详细信息,请参阅方言的文档。
代码语言:javascript复制
classmethod argument_for(dialect_name, argument_name, default)

继承自 DialectKWArgs.argument_for() 方法的 DialectKWArgs

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

例如:

代码语言:javascript复制
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 - 参数的默认值。
代码语言:javascript复制
method create(bind: _CreateDropBind, checkfirst: bool = False) → None

对于此 Index,使用给定的 ConnectionEngine 发出 CREATE 语句以进行连接。

参见

MetaData.create_all()

代码语言:javascript复制
method ddl_if(dialect: str | None = None, callable_: DDLIfCallable | None = None, state: Any | None = None) → Self

继承自 HasConditionalDDL.ddl_if() 方法 HasConditionalDDL

将条件 DDL 规则应用于此模式项。

这些规则的工作方式类似于 ExecutableDDLElement.execute_if() 可调用对象,其附加功能是可以在 DDL 编译阶段检查条件,例如 CreateTable 构造。HasConditionalDDL.ddl_if() 目前也适用于 Index 构造以及所有 Constraint 构造。

参数:

  • dialect - 方言的字符串名称,或一组字符串名称以指示多个方言类型。
  • callable_ - 使用与 ExecutableDDLElement.execute_if.callable_ 中描述的相同形式构造的可调用对象。
  • state - 如果存在,将传递给可调用对象的任意对象。

从版本 2.0 开始新增。

参见

控制约束和索引的 DDL 生成 - 背景和用法示例

代码语言:javascript复制
attribute dialect_kwargs

继承自 DialectKWArgs.dialect_kwargs 属性的 DialectKWArgs

作为方言特定选项的关键字参数集合,用于这个构造函数。

这里的参数以其原始的 <dialect>_<kwarg> 格式存在。只包括实际传递的参数;不像 DialectKWArgs.dialect_options 集合,该集合包含此方言已知的所有选项,包括默认值。

集合也是可写的;接受形式为 <dialect>_<kwarg> 的键,其值将被组装成选项列表。

另请参阅

DialectKWArgs.dialect_options - 嵌套的字典形式

代码语言:javascript复制
attribute dialect_options

继承自 DialectKWArgs.dialect_options 属性的 DialectKWArgs

作为方言特定选项的关键字参数集合,用于这个构造函数。

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

代码语言:javascript复制
arg = my_object.dialect_options['postgresql']['where']

版本 0.9.2 中的新功能。

另请参阅

DialectKWArgs.dialect_kwargs - 平坦的字典形式

代码语言:javascript复制
method drop(bind: _CreateDropBind, checkfirst: bool = False) → None

使用给定的 ConnectionEngine 进行连接性,为此 Index 发出 DROP 语句。

另请参阅

MetaData.drop_all().

代码语言:javascript复制
attribute info

继承自 SchemaItem.info 属性的 SchemaItem

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

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

代码语言:javascript复制
attribute kwargs

继承自 DialectKWArgs.kwargs 属性的 DialectKWArgs

DialectKWArgs.dialect_kwargs 的同义词。

0 人点赞