对于在INSERT和UPDATE语句期间发生的列级事件,SQLAlchemy提供了非常丰富的特性集。选项包括:
在插入和更新操作期间用作默认值的标量值
在插入和更新操作时执行的python函数
嵌入在INSERT语句中的SQL表达式(或在某些情况下提前执行)
嵌入在UPDATE语句中的SQL表达式
插入期间使用的服务器端默认值
更新期间使用的服务器端触发器标记
所有插入/更新默认值的一般规则是,只有当没有特定列的值作为 execute()
参数;否则,使用给定值。
最简单的默认类型是用作列默认值的标量值::
Table("mytable", meta,
Column("somecolumn", Integer, default=12)
)
上面,如果没有提供其他值,则值“12”将在插入期间绑定为列值。
标量值也可能与update语句关联,尽管这并不常见(因为update语句通常寻找动态默认值)::
Table("mytable", meta,
Column("somecolumn", Integer, onupdate=25)
)
这个 Column.default
和 Column.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
功能 now
到 Column.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.default
和 Column.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
属性,它提供将多个值子句组织到单个参数字典中的服务。
这个 Column.default
和 Column.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.default
和 Column.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
集合包含插入行的主键值列表(这样,单列和复合列主键以相同的格式表示的列表)。
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()
方法可以与 Insert
或 Update
构造以指示应返回这些值。
有关使用的详细信息 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
当 Sequence
与 Column
作为其 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
将继承 MetaData.schema
为目标指定的参数 MetaData
影响创建/删除DDL(如果有)的生成。
这个 Sequence.create()
和 Sequence.drop()
方法自动使用绑定到 MetaData
对象,如果有的话。
这个 MetaData.create_all()
和 MetaData.drop_all()
方法将为此发出create/drop Sequence
,即使 Sequence
不与任何 Table
/ Column
这是其中的一员 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()
方法。下面我们也说明了同样的情况 Sequence
与 Column
同时作为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
直接,这再次确保 Sequence
与 MetaData
包含默认架构(如果有)的集合。
sqlalchemy.schema.
ColumnDefault
(arg, **kwargs)¶基地: sqlalchemy.schema.DefaultGenerator
列上的普通默认值。
这可能对应于常量、可调用函数或SQL子句。
ColumnDefault
每当 default
, onupdate
论点 Column
被使用。一 ColumnDefault
也可以按位置传递。
例如,以下内容:
Column('foo', Integer, default=50)
等于:
Column('foo', Integer, ColumnDefault(50))
sqlalchemy.schema.
DefaultClause
(arg, for_update=False, _reflected=False)¶基地: sqlalchemy.schema.FetchedValue
DDL指定的默认列值。
DefaultClause
是一个 FetchedValue
当发出“create table”时,也会生成一个“default”子句。
DefaultClause
每当 server_default
, server_onupdate
论点 Column
被使用。一 DefaultClause
也可以按位置传递。
例如,以下内容:
Column('foo', Integer, server_default="50")
等于:
Column('foo', Integer, DefaultClause("50"))
sqlalchemy.schema.
DefaultGenerator
(for_update=False)¶基地: sqlalchemy.schema._NotAColumnExpr
, sqlalchemy.schema.SchemaItem
列的基类 违约 价值观。
sqlalchemy.schema.
FetchedValue
(for_update=False)¶基地: sqlalchemy.schema._NotAColumnExpr
, sqlalchemy.sql.expression.SchemaEventTarget
透明数据库端默认值的标记。
使用 FetchedValue
当数据库被配置为为为列提供一些自动默认值时。
例如。::
Column('foo', Integer, FetchedValue())
将指示某些触发器或默认生成器将为 foo
插入期间的列。
sqlalchemy.schema.
PassiveDefault
(*arg, **kw)¶基地: sqlalchemy.schema.DefaultClause
DDL指定的默认列值。
0.6 版后已移除: PassiveDefault
已弃用,将在将来的版本中删除。请参考 DefaultClause
.
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“执行” Engine
或 Connection
,为目标数据库呈现相应的“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¶ -- 布尔值,当 True
或 False
,显式强制打开或关闭模式名称的引用。当其违约时 None
根据大小写和保留字进行正常报价规则。
quote_schema¶ -- 设置 schema
姓名。
metadata¶ -- 可选择的 MetaData
对象 Sequence
将与关联。一 Sequence
与 MetaData
获得以下功能: * 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
. 只有当 Sequence
与 MetaData
通过这个参数。…参阅: 将序列与元数据关联 -充分讨论 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表达式中。