列插入/更新默认值¶

对于在INSERT和UPDATE语句期间发生的列级事件,SQLAlchemy提供了非常丰富的特性集。选项包括:

所有插入/更新默认值的一般规则是,只有当没有特定列的值作为 execute() 参数;否则,使用给定值。

标量缺省值

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

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

上面,如果没有提供其他值,则值“12”将在插入期间绑定为列值。

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

Table("mytable", meta,
    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", meta,
    Column('id', Integer, primary_key=True, default=mydefault),
)

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

为了说明OnUpdate,我们分配了python datetime 功能 nowColumn.onupdate 属性:

import datetime

t = Table("mytable", meta,
    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 , the datetime.datetime.now() 执行python函数,其返回值用作 last_updated . 注意,我们提供 now 作为函数本身而不调用它(即后面没有括号),SQLAlchemy将在语句执行时执行函数。

上下文相关的默认函数

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

def mydefault(context):
    return context.get_current_parameters()['counter'] + 12

t = Table('mytable', meta,
    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() 方法),对每一组参数也调用一次用户定义函数。

当调用函数时,特殊方法 DefaultExecutionContext.get_current_parameters() 可从上下文对象(的子类 DefaultExecutionContext )此方法将列键字典返回表示insert或update语句的完整值集的值。在多值插入构造的情况下,对应于单个values子句的参数子集与完整参数字典隔离,并单独返回。

1.2 新版功能: 补充 DefaultExecutionContext.get_current_parameters() 方法,在仍然存在的情况下改进 DefaultExecutionContext.current_parameters 属性,它提供将多个值子句组织到单个参数字典中的服务。

客户端调用的SQL表达式

这个 Column.defaultColumn.onupdate 也可以传递关键字SQL表达式,在大多数情况下,这些表达式在insert或update语句中以内联方式呈现:

t = Table("mytable", meta,
    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 在大多数情况下)在insert语句中, key 列中包含从另一个表中选择子查询的结果。这个 last_modified 将用SQL的值填充列 UTC_TIMESTAMP() 当为此表发出update语句时,mysql函数。

注解

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

默认和更新由指定的SQL表达式 Column.defaultColumn.onupdate 当发生insert或update语句时,由sqlAlchemy显式调用,通常在dml语句内内联呈现,下面列出的某些情况除外。这与“服务器端”默认值不同,后者是表的DDL定义的一部分,例如,作为“create table”语句的一部分,后者可能更常见。有关服务器端默认值,请参阅下一节 服务器调用了DDL显式默认表达式 .

当SQL表达式由 Column.default 与主键列一起使用时,在某些情况下,SQLAlchemy必须“预执行”默认的生成SQL函数,这意味着它在单独的select语句中被调用,并且结果值作为参数传递给insert。这仅适用于请求返回此主键值的insert语句的主键列,其中返回或 cursor.lastrowid 不能使用。安 Insert 用于指定 inline 标志将始终以内联方式呈现默认表达式。

当使用一组参数(即,它不是“ExecuteMany”样式的执行)执行语句时,返回的 ResultProxy 将包含可通过访问的集合 ResultProxy.postfetch_cols() 其中包含所有 Column 具有内联执行默认值的对象。类似地,绑定到语句的所有参数(包括所有预执行的python和sql表达式)都存在于 ResultProxy.last_inserted_params()ResultProxy.last_updated_params() 关于收藏 ResultProxy . 这个 ResultProxy.inserted_primary_key 集合包含插入行的主键值列表(这样,单列和复合列主键以相同的格式表示的列表)。

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

SQL表达式默认值的变量是 Column.server_default ,在 Table.create() 操作:

t = Table('test', meta,
    Column('abc', String(20), server_default='abc'),
    Column('created_at', DateTime, server_default=func.sysdate()),
    Column('index_value', Integer, server_default=text("0"))
)

上面表的创建调用将产生:

CREATE TABLE test (
    abc varchar(20) default 'abc',
    created_at datetime default sysdate,
    index_value integer default 0
)

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

就像客户端生成的表达式一样, Column.server_default 通常可以容纳SQL表达式,但是可以预期这些表达式通常是简单的函数和表达式,而不是像嵌入的select这样更复杂的情况。

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

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

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

这个 FetchedValue 指示器不会影响为创建表呈现的DDL。相反,它将列标记为在执行insert或update语句的过程中由数据库填充新值的列,并且对于支持数据库,可以使用该列指示该列应是该语句的返回或输出子句的一部分。然后,诸如SQLAlchemy orm之类的工具利用这个标记来了解如何在这样的操作之后获取列的值。尤其是, ValuesBase.return_defaults() 方法可以与 InsertUpdate 构造以指示应返回这些值。

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

定义序列

SQLAlchemy表示使用 Sequence 对象,这被认为是“列默认”的特殊情况。它只对那些明确支持序列的数据库有影响,这些数据库目前包括PostgreSQL、Oracle和Firebird。这个 Sequence 否则将忽略对象。

这个 Sequence 可以作为插入操作期间要使用的“默认”生成器放在任何列上,也可以配置为在更新操作期间根据需要触发。它通常与单个整数主键列一起使用:

table = Table("cartitems", meta,
    Column(
        "cart_id",
        Integer,
        Sequence('cart_id_seq', metadata=meta), primary_key=True),
    Column("description", String(40)),
    Column("createdate", DateTime())
)

在上面,表“cartems”与名为“cart_id_seq”的序列关联。当“cartems”发生insert语句,并且“cart_id”列没有传递值时,“cart_id_seq”序列将用于生成值。通常,sequence函数嵌入在insert语句中,它与返回结合在一起,以便新生成的值可以返回到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

SequenceColumn 作为其 Python-side 默认生成器 Sequence 当为拥有者发出类似的DDL时,也将服从“创建序列”和“删除序列”DDL。 Table . 这是一个有限范围的便利功能,不适合继承 MetaData ,例如默认架构。因此,最好的做法是 Sequence 哪个是本地的 Column / Table ,它与 MetaData 使用 Sequence.metadata 参数。见剖面图 将序列与元数据关联 关于这方面的更多背景。

将序列与序列列关联

PostgreSQL的串行数据类型是一种自动递增类型,它意味着在发出create table时隐式创建PostgreSQL序列。如果A Column 指定显式 Sequence 对象,它还为 Sequence.optional 布尔标记 Sequence 在PostgreSQL下不会生效,串行数据类型会正常进行。相反, Sequence 仅在与其他序列支持数据库(当前为Oracle和Firebird)一起使用时生效。

独立执行序列

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

with my_engine.connect() as conn:
    seq = Sequence('some_sequence')
    nextid = conn.execute(seq)

为了嵌入 Sequence 在SQL语句(如select或insert)中,使用 Sequence.next_value() 方法,它将在语句编译时呈现适用于目标后端的SQL函数:

>>> my_seq = Sequence('some_sequence')
>>> stmt = select([my_seq.next_value()])
>>> print stmt.compile(dialect=postgresql.dialect())
SELECT nextval('some_sequence') AS next_value_1

将序列与元数据关联

多年来,sqlAlchemy文档引用了将 Sequence 表格如下:

table = Table("cartitems", meta,
    Column("cart_id", Integer, Sequence('cart_id_seq'),
           primary_key=True),
    Column("description", String(40)),
    Column("createdate", DateTime())
)

虽然以上是一个突出的惯用模式,但建议 Sequence 在大多数情况下,与 MetaData ,使用 Sequence.metadata 参数::

table = Table("cartitems", meta,
    Column(
        "cart_id",
        Integer,
        Sequence('cart_id_seq', metadata=meta), primary_key=True),
    Column("description", String(40)),
    Column("createdate", DateTime())
)

这个 Sequence 对象是一个第一类模式构造,可以独立于数据库中的任何表存在,也可以在表之间共享。因此,sqlAlchemy不会隐式修改 Sequence 当它与 Column 对象作为Python端或服务器端默认生成器。当为 Sequence 定义为同时要创建或删除表本身的python端生成器,这是一个方便的特性,并不意味着 Sequence 完全与 MetaData 对象。

显式关联 Sequence 具有 MetaData 允许以下行为:

因为绝大多数案件 Sequence 期待 Sequence 由关联方完全“拥有” Table 并且像默认模式这样的选项被传播,设置 Sequence.metadata 应将参数视为最佳实践。

将序列关联为服务器端默认值

注解

以下技术只适用于PostgreSQL数据库。它不适用于Oracle。

前面的部分说明了如何将 Sequence 用一个 Column 作为 python端默认生成器 ::

Column(
    "cart_id", Integer, Sequence('cart_id_seq', metadata=meta),
    primary_key=True)

在上述情况下, Sequence 当相关的 Table 以创建/删除为准。但是,序列将 not 在发出create table时,作为列的服务器端默认值出现。

如果我们希望序列用作服务器端默认值,这意味着即使我们从SQL命令行向表发出INSERT命令,也会发生这种情况,我们可以使用 Column.server_default 与序列的值生成函数一起使用的参数,可从 Sequence.next_value() 方法。下面我们也说明了同样的情况 SequenceColumn 同时作为python端默认生成器和服务器端默认生成器:

cart_id_seq = Sequence('cart_id_seq', metadata=meta)
table = Table("cartitems", meta,
    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)
    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语句,当发出此语句时,sqlAlchemy会自动使用该语句。但是,如果返回不用于特定的插入,那么sqlAlchemy更愿意在insert语句本身之外“预执行”序列,这仅在序列作为python-side默认生成器函数包含时有效。

该示例还将 Sequence 与包围 MetaData 直接,这再次确保 SequenceMetaData 包含默认架构(如果有)的集合。

参见

序列/序列/标识 -在PostgreSQL方言文档中

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

默认对象API

class sqlalchemy.schema.ColumnDefault(arg, **kwargs)

基地: sqlalchemy.schema.DefaultGenerator

列上的普通默认值。

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

ColumnDefault 每当 defaultonupdate 论点 Column 被使用。一 ColumnDefault 也可以按位置传递。

例如,以下内容:

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

等于:

Column('foo', Integer, ColumnDefault(50))
class sqlalchemy.schema.DefaultClause(arg, for_update=False, _reflected=False)

基地: sqlalchemy.schema.FetchedValue

DDL指定的默认列值。

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(for_update=False)

基地: sqlalchemy.schema._NotAColumnExprsqlalchemy.schema.SchemaItem

列的基类 违约 价值观。

class sqlalchemy.schema.FetchedValue(for_update=False)

基地: sqlalchemy.schema._NotAColumnExprsqlalchemy.sql.expression.SchemaEventTarget

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

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

例如。::

Column('foo', Integer, FetchedValue())

将指示某些触发器或默认生成器将为 foo 插入期间的列。

class sqlalchemy.schema.PassiveDefault(*arg, **kw)

基地: sqlalchemy.schema.DefaultClause

DDL指定的默认列值。

0.6 版后已移除: PassiveDefault 已弃用,将在将来的版本中删除。请参考 DefaultClause .

class sqlalchemy.schema.Sequence(name, start=None, increment=None, minvalue=None, maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, schema=None, cache=None, order=None, optional=False, quote=None, metadata=None, quote_schema=None, for_update=False)

基地: sqlalchemy.schema.DefaultGenerator

表示命名的数据库序列。

这个 Sequence 对象表示数据库序列的名称和配置参数。它还表示一个构造,可以由一个sqlAlchemy“执行” EngineConnection ,为目标数据库呈现相应的“next value”函数并返回结果。

这个 Sequence 通常与主键列关联::

some_table = Table(
    'some_table', metadata,
    Column('id', Integer, Sequence('some_table_seq'),
    primary_key=True)
)

当为上述发出“创建表”时 Table 如果目标平台支持序列,则也将发出create sequence语句。对于不支持序列的平台, Sequence 忽略构造。

__init__(name, start=None, increment=None, minvalue=None, maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, schema=None, cache=None, order=None, optional=False, quote=None, metadata=None, quote_schema=None, for_update=False)

构建一个 Sequence 对象。

参数
  • name -- 序列的名称。

  • start -- 序列的起始索引。当create sequence命令作为“start with”子句的值发送到数据库时,将使用此值。如果 None ,省略了该子句,在大多数平台上,该子句指示的起始值为1。

  • increment -- 序列的增量值。当create sequence命令作为“increment by”子句的值发送到数据库时,使用该值。如果 None ,该子句被省略,在大多数平台上,它表示增量为1。

  • minvalue -- 序列的最小值。当将create sequence命令作为“minvalue”子句的值发送到数据库时,将使用此值。如果 None ,省略该子句,在大多数平台上,该子句分别表示升序序列和降序序列的最小值1和-2^63-1。…添加的版本:1.0.7

  • maxvalue -- 序列的最大值。当将create sequence命令作为“maxvalue”子句的值发送到数据库时,将使用此值。如果 None ,省略该子句,在大多数平台上,它分别表示升序和降序序列的最大值2^63-1和-1。…添加的版本:1.0.7

  • nominvalue -- 序列没有最小值。当将create sequence命令作为“no minvalue”子句的值发送到数据库时,将使用此值。如果 None ,省略该子句,在大多数平台上,该子句分别表示升序序列和降序序列的最小值1和-2^63-1。…添加的版本:1.0.7

  • nomaxvalue -- 序列没有最大值。当create sequence命令作为“no maxvalue”子句的值发送到数据库时,将使用此值。如果 None ,省略该子句,在大多数平台上,它分别表示升序和降序序列的最大值2^63-1和-1。…添加的版本:1.0.7

  • cycle -- 允许序列在分别由升序或降序到达maxvalue或minvalue时换行。当将create sequence命令作为“cycle”子句发送到数据库时,将使用此值。如果达到限制,则生成的下一个数字将分别是minvalue或maxvalue。如果cycle=false(默认值),则在序列达到最大值后对nextval的任何调用都将返回错误。…添加的版本:1.0.7

  • schema -- 序列的可选架构名称(如果位于非默认架构中)。当 MetaData 也存在与 Table.schema .

  • cache -- 可选整数值;预先计算的序列中未来值的数目。呈现Oracle和PostgreSQL理解的缓存关键字。…添加版本:1.1.12

  • order -- 可选的布尔值;如果为true,则呈现ORDER关键字,Oracle可以理解该关键字,指示序列的顺序是确定的。可能需要使用OracleRAC提供确定性排序。…添加的版本:1.1.12

  • optional -- 布尔值,当 True ,表示 Sequence 对象只需要在后端显式生成,而后端不提供生成主键标识符的其他方法。目前,它实质上意味着,“不要在PostgreSQL后端创建这个序列,在那里序列关键字会自动为我们创建一个序列”。

  • quote -- 布尔值,当 TrueFalse ,显式强制打开或关闭模式名称的引用。当其违约时 None 根据大小写和保留字进行正常报价规则。

  • quote_schema -- 设置 schema 姓名。

  • metadata -- 可选择的 MetaData 对象 Sequence 将与关联。一 SequenceMetaData 获得以下功能: * The Sequence will inherit the MetaData.schema parameter specified to the target MetaData, which affects the production of CREATE / DROP DDL, if any. * 这个 Sequence.create()Sequence.drop() 方法自动使用绑定到 MetaData 对象(如果有)。* MetaData.create_all()MetaData.drop_all() 方法将为此发出create/drop Sequence ,即使 Sequence 不与任何 Table / Column 这是其中的一员 MetaData . 只有当 SequenceMetaData 通过这个参数。…参阅: 将序列与元数据关联 -充分讨论 Sequence.metadata 参数。

  • for_update -- 表明这一点 Sequence ,当与 Column 当语句中该列没有其他值时,应为该列的表上的update语句而不是insert语句调用。

bind

返回与此默认值关联的可连接项。

create(bind=None, checkfirst=True)

在数据库中创建此序列。

drop(bind=None, checkfirst=True)

从数据库中删除此序列。

next_value(func)

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