列 INSERT/UPDATE 默认值

列 INSERT 和 UPDATE 默认值是指在针对某行的 INSERT 或 UPDATE 语句执行时,为该行中特定列创建默认值的函数,前提是该语句未为该列提供值。也就是说,如果一个表有一个名为“timestamp”的列,并且执行了一个 INSERT 语句,但该语句不包含此列的值,则 INSERT 默认值将创建一个新值(例如当前时间),该值将用作要 INSERT 到“timestamp”列中的值。如果语句确实包含此列的值,则默认值不会生效。

列默认值可以是服务器端函数或常量值,这些函数或常量值在数据库中以及 DDL 中的模式中定义,也可以是在 SQLAlchemy 发出的 INSERT 或 UPDATE 语句中直接呈现的 SQL 表达式;它们也可以是客户端 Python 函数或常量值,这些函数或常量值在数据传递到数据库之前由 SQLAlchemy 调用。

注意

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

SQLAlchemy 提供了关于在 INSERT 和 UPDATE 语句期间为非现有值生成默认值函数的各种功能。选项包括

  • 在 INSERT 和 UPDATE 操作期间用作默认值的标量值

  • 在 INSERT 和 UPDATE 操作时执行的 Python 函数

  • 嵌入在 INSERT 语句中的 SQL 表达式(或在某些情况下预先执行)

  • 嵌入在 UPDATE 语句中的 SQL 表达式

  • 在 INSERT 期间使用的服务器端默认值

  • 在 UPDATE 期间使用的服务器端触发器的标记

所有 insert/update 默认值的一般规则是,它们仅在未将特定列的值作为 execute() 参数传递时才生效;否则,将使用给定的值。

标量默认值

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

Table("mytable", metadata_obj, Column("somecolumn", Integer, default=12))

上面,“12”值将在 INSERT 期间绑定为列值,前提是没有提供其他值。

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

Table("mytable", metadata_obj, Column("somecolumn", Integer, onupdate=25))

Python 执行的函数

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

# 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(包括 Column.autoincrement 标志)的 API 文档,以及本章稍后关于 Sequence 的部分,请参阅标准主键生成技术的背景信息。

为了说明 onupdate,我们将 Python datetime 函数 now 分配给 Column.onupdate 属性

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),
)

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

上下文相关的默认函数

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

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 语句中

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 子查询的结果。last_modified 列将在为此表发出 UPDATE 语句时填充 SQL UTC_TIMESTAMP() MySQL 函数的值。

注意

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

Column.defaultColumn.onupdate 指定的默认和更新 SQL 表达式在发生 INSERT 或 UPDATE 语句时由 SQLAlchemy 显式调用,通常内联呈现在 DML 语句中,但以下列出的某些情况除外。这与“服务器端”默认值不同,后者是表 DDL 定义的一部分,例如,作为“CREATE TABLE”语句的一部分,这可能更常见。对于服务器端默认值,请参阅下一节 服务器调用的 DDL 显式默认表达式

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

当使用单个参数集执行语句时(即,它不是“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 语句中

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")),
)

上面表的 create 调用将生成

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。

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

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

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 构造一起使用,以指示应返回这些值。

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

警告

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。有关此构造的背景信息,请参阅 标识列 (GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY) 部分。

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

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() 将包括

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

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 进程

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 端 默认生成器时,当为所属的 Table 发出类似的 DDL(例如当使用 MetaData.create_all() 为一系列表生成 DDL 时)时,Sequence 也将受到 “CREATE SEQUENCE” 和 “DROP SEQUENCE” DDL 的影响。

Sequence 也可以直接与 MetaData 构造关联。这允许 Sequence 在多个 Table 中同时使用,并允许继承 MetaData.schema 参数。有关背景信息,请参阅 将 Sequence 与 MetaData 关联 部分。

在 SERIAL 列上关联 Sequence

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

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 将对 cart_id 列使用 SERIAL 数据类型,并且 cart_id_seq 序列将被忽略。但是,在 Oracle 数据库上,cart_id_seq 序列将被显式创建。

提示

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

独立执行 Sequence

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

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 函数。

>>> 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 关联。

seq = Sequence("my_general_seq", metadata=metadata_obj, start=1)

然后,可以像往常一样将这样的序列与列关联。

table = Table(
    "cartitems",
    metadata_obj,
    seq,
    Column("description", String(40)),
    Column("createdate", DateTime()),
)

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

SequenceMetaData 显式关联允许以下行为:

将 Sequence 关联为服务器端默认值

注意

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

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

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 如何与 Column 关联,既作为 Python 端默认生成器,又作为服务器端默认生成器。

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:

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 上,它将发出为:

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)
)

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

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

另请参阅

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

RETURNING 支持 - 在 Oracle 数据库方言文档中

计算列 (GENERATED ALWAYS AS)

1.3.11 版本新增。

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

示例:

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 将如下所示:

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” 关键字,但是如果目标后端不支持该关键字,则会引发错误;将其保留为未设置状态将使用目标后端的工作默认值。

Computed 构造是 FetchedValue 对象的子类,并将自身设置为目标 Column 的 “服务器默认值” 和 “服务器端 onupdate” 生成器,这意味着在生成 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 共享,以控制数据库行为。

示例:

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 将如下所示:

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:

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 指定的 DEFAULT 列值。

DefaultGenerator

默认值的基类。

FetchedValue

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

Identity

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

Sequence

表示命名的数据库序列。

class sqlalchemy.schema.Computed

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

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

from sqlalchemy import Computed

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

有关完整详细信息,请参阅下面链接的文档。

1.3.11 版本新增。

成员

__init__(), copy()

method sqlalchemy.schema.Computed.__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,或目标数据库的等效项(如果支持)。

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

method sqlalchemy.schema.Computed.copy(*, target_table: Table | None = None, **kw: Any) Computed

Deprecated since version 1.4: Computed.copy() 方法已弃用,将在未来版本中删除。

class sqlalchemy.schema.ColumnDefault

列上的普通默认值。

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

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

例如,以下代码:

Column("foo", Integer, default=50)

等效于:

Column("foo", Integer, ColumnDefault(50))
class sqlalchemy.schema.DefaultClause

DDL 指定的 DEFAULT 列值。

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

DefaultClause 在使用 server_defaultserver_onupdate 参数的 Column 时会自动生成。 DefaultClause 也可以作为位置参数传递。

例如,以下代码:

Column("foo", Integer, server_default="50")

等效于:

Column("foo", Integer, DefaultClause("50"))
class sqlalchemy.schema.DefaultGenerator

默认值的基类。

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

class sqlalchemy.schema.FetchedValue

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

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

例如:

Column("foo", Integer, FetchedValue())

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

类签名

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

class sqlalchemy.schema.Sequence

表示命名的数据库序列。

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

Sequence 通常与主键列关联

some_table = Table(
    "some_table",
    metadata,
    Column(
        "id",
        Integer,
        Sequence("some_table_seq", start=1),
        primary_key=True,
    ),
)

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

类签名

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

method sqlalchemy.schema.Sequence.__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。

    Changed in version 2.0: Sequence.start 参数是发出 “START WITH” 所必需的。 这与 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^63-1。

  • maxvalue – 序列的最大值。此值在向数据库发出 CREATE SEQUENCE 命令时用作 “MAXVALUE” 子句的值。如果为 None,则省略该子句,这在大多数平台上表示升序和降序序列的最大值分别为 2^63-1 和 -1。

  • nominvalue – 序列无最小值。此值在向数据库发出 CREATE SEQUENCE 命令时用作 “NO MINVALUE” 子句的值。如果为 None,则省略该子句,这在大多数平台上表示升序和降序序列的最小值分别为 1 和 -2^63-1。

  • nomaxvalue – 序列无最大值。此值在向数据库发出 CREATE SEQUENCE 命令时用作 “NO MAXVALUE” 子句的值。如果为 None,则省略该子句,这在大多数平台上表示升序和降序序列的最大值分别为 2^63-1 和 -1。

  • cycle – 允许序列在升序或降序序列分别达到 maxvalue 或 minvalue 时回绕。此值在向数据库发出 CREATE SEQUENCE 命令时用作 “CYCLE” 子句。如果达到限制,则生成的下一个数字将分别为 minvalue 或 maxvalue。如果 cycle=False(默认值),则在序列达到其最大值后对 nextval 的任何调用都将返回错误。

  • schema – 序列的可选模式名称,如果位于默认模式之外的模式中。当 MetaData 也存在时,选择模式名称的规则与 Table.schema 的规则相同。

  • cache – 可选整数值;预先计算的序列中未来值的数量。渲染 Oracle 数据库和 PostgreSQL 理解的 CACHE 关键字。

  • order – 可选布尔值;如果为 True,则渲染 Oracle 数据库理解的 ORDER 关键字,指示序列是确定性排序的。可能需要使用 Oracle RAC 提供确定性排序。

  • data_type

    序列返回的类型,对于允许我们在 INTEGER、BIGINT 等之间进行选择的方言(例如,mssql)。

    New in version 1.4.0. (1.4.0 版本新增)

  • optional – 布尔值,当为 True 时,表示此 Sequence 对象只需要在不提供其他方式来生成主键标识符的后端上显式生成。目前,它基本上意味着,“不要在 PostgreSQL 后端上创建此序列,其中 SERIAL 关键字会自动为我们创建一个序列”。

  • quote – 布尔值,当为 TrueFalse 时,显式强制 Sequence.name 的引号开或关。当保留其默认值 None 时,将根据大小写和保留字进行正常的引号规则。

  • quote_schema – 设置 schema 名称的引号首选项。

  • metadata

    可选的 MetaData 对象,此 Sequence 将与之关联。与 MetaData 关联的 Sequence 获得以下功能

    只有当 Sequence 通过此参数显式地与 MetaData 关联时,上述行为才会发生。

    另请参阅

    将 Sequence 与 MetaData 关联 - 关于 Sequence.metadata 参数的完整讨论。

  • for_update – 指示此 Sequence 在与 Column 关联时,应该为该列的表的 UPDATE 语句而不是 INSERT 语句调用,当语句中该列没有其他值时。

method sqlalchemy.schema.Sequence.create(bind: _CreateDropBind, checkfirst: bool = True) None

在数据库中创建此序列。

method sqlalchemy.schema.Sequence.drop(bind: _CreateDropBind, checkfirst: bool = True) None

从数据库中删除此序列。

method sqlalchemy.schema.Sequence.next_value() Function[int]

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

class sqlalchemy.schema.Identity

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

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

from sqlalchemy import Identity

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

有关完整详细信息,请参阅下面链接的文档。

1.4 版本新增。

成员

__init__(), copy()

类签名

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

method sqlalchemy.schema.Identity.__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 以指定 ON NULL,与 always=False 标识列结合使用。此选项仅在某些后端(如 Oracle Database)上受支持。

  • start – 序列的起始索引。

  • increment – 序列的增量值。

  • minvalue – 序列的最小值。

  • maxvalue – 序列的最大值。

  • nominvalue – 序列没有最小值。

  • nomaxvalue – 序列没有最大值。

  • cycle – 允许序列在达到 maxvalue 或 minvalue 时回绕。

  • cache – 可选的整数值;序列中预先计算的未来值的数量。

  • order – 可选的布尔值;如果为 true,则呈现 ORDER 关键字。

method sqlalchemy.schema.Identity.copy(**kw: Any) Identity

Deprecated since version 1.4: Identity.copy() 方法已弃用,并将在未来版本中移除。