SQLAlchemy针对在INSERT和UPDATE语句期间发生的列级事件提供了非常丰富的功能集。选项包括:
所有插入/更新默认值的一般规则是,只有当特定列的值不作为execute()
参数传递时才会生效。否则,使用给定的值。
最简单的默认值是一个用作列默认值的标量值:
Table("mytable", meta,
Column("somecolumn", Integer, default=12)
)
上面,如果没有提供其他值,则在INSERT期间将值“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在大多数情况下会自动使用这些功能。有关Column
的API文档,包括Column.autoincrement
标志以及本章后面Sequence
中有关标准主要背景的部分密钥生成技术。
To illustrate onupdate, we assign the Python datetime
function now
to the Column.onupdate
attribute:
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
传递值时,将执行datetime.datetime.now()
Python函数并将其返回值用作last_updated
请注意,我们现在now
作为函数本身而不调用它(即没有下面的括号) - SQLAlchemy将在语句执行时执行该函数。
由Column.default
和Column.onupdate
使用的Python函数也可以使用当前语句的上下文来确定一个值。语句的context是一个内部SQLAlchemy对象,它包含有关正在执行的语句的所有信息,包括其源表达式,与其关联的参数以及游标。与默认生成有关的上下文的典型用例是访问在该行上插入或更新的其他值。要访问上下文,请提供一个接受单个context
参数的函数:
def mydefault(context):
return context.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。
虽然传递给默认函数的上下文对象具有许多属性,但current_parameters
成员是仅在执行默认函数时才提供的特殊成员,用于从其现有值中派生默认值。For a single statement that is executing many sets of bind parameters, the user-defined function is called for each set of parameters, and current_parameters
will be provided with each individual parameter set for each execution.
“default”和“onupdate”关键字也可以通过SQL表达式,包括select语句或直接函数调用:
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=keyvalues.select(keyvalues.c.type='type1', limit=1)),
# define 'last_modified' to use the current_timestamp SQL function on update
Column('last_modified', DateTime, onupdate=func.utc_timestamp())
)
Above, the create_date
column will be populated with the result of the now()
SQL function (which, depending on backend, compiles into NOW()
or CURRENT_TIMESTAMP
in most cases) during an INSERT statement, and the key
column with the result of a SELECT subquery from another table. 当为此表发出UPDATE语句时,last_modified
列将填充UTC_TIMESTAMP()
的值,该函数是MySQL特有的函数。
请注意,当使用func
函数时,与使用Python datetime函数不同,我们do调用函数,即括号“()” - 这是因为我们在这种情况下需要的是函数的返回值,它是将被呈现到INSERT或UPDATE语句中的SQL表达式结构。
上述SQL函数通常在执行INSERT或UPDATE语句时“inline”执行,也就是说,执行一条语句,将给定的表达式或子查询嵌入到语句的VALUES或SET子句中。尽管在某些情况下,函数在事先SELECT语句中“预执行”。当以下所有情况都属实时,会发生这种情况:
cursor.lastrowid
存取器(或等价物);目前包括PostgreSQL,Oracle和Firebird,以及一些MySQL方言。implicit_returning
标志设置为False
。支持RETURNING的方言目前包括Postgresql,Oracle,Firebird和MS-SQL。Insert()
或Update()
结构中未设置inline=True
标志,并且该语句没有定义明确的 returns()子句。除非出于性能考虑,否则默认生成子句“预执行”不是通常需要考虑的事项。
当使用一组参数执行语句(即,它不是“executemany”样式执行)时,返回的ResultProxy
将包含可通过ResultProxy.postfetch_cols()
其中包含具有内联执行的缺省值的所有Column
对象的列表。Similarly, all parameters which were bound to the statement, including all Python and SQL expressions which were pre-executed, are present in the ResultProxy.last_inserted_params()
or ResultProxy.last_updated_params()
collections on ResultProxy
. ResultProxy.inserted_primary_key
集合包含插入行的主键值列表(列表使得单列和组合列主键以相同的格式表示)。
SQL表达式默认的变体是Column.server_default
,它在Table.create()
操作期间被放置在CREATE TABLE语句中:
t = Table('test', meta,
Column('abc', String(20), server_default='abc'),
Column('created_at', DateTime, server_default=text("sysdate"))
)
创建上述表格的调用将产生:
CREATE TABLE test (
abc varchar(20) default 'abc',
created_at datetime default sysdate
)
Column.server_default
的行为类似于常规SQL默认行为;如果它放在数据库的主键列上,但没有“后取”ID的方法,并且该语句不是“内联”的,则SQL表达式将被预先执行;否则,SQLAlchemy会让数据库端的默认值正常启动。
可以使用FetchedValue
作为标记来调出具有由数据库触发器或其他外部过程设置的值的列:
t = Table('test', meta,
Column('abc', String(20), server_default=FetchedValue()),
Column('def', String(20), server_onupdate=FetchedValue())
)
更改为0.8.0b2,0.7.10版本: FetchedValue
上的for_update
参数在指定为server_onupdate
如果使用旧版本,请将上面的onupdate指定为server_onupdate=FetchedValue(for_update=True)
。
这些标记在创建表时不会发出“default”子句,但是它们将静态的server_default
子句设置为相同的内部标志,为高级工具提供了一个提示:“post-fetch “应在插入或更新后执行这些行。
注意
将FetchedValue
与主键列结合使用通常是不恰当的,特别是在使用ORM或需要ResultProxy.inserted_primary_key
属性的任何其他场景时。这是因为“post-fetch”操作要求主键值已经可用,以便可以在主键上选择该行。
对于服务器生成的主键值,所有数据库都提供特殊的访问器或其他技术来获取表的“最后插入的主键”列。这些机制不受FetchedValue
的影响。对于使用触发器生成主键值的特殊情况,并且正在使用的数据库不支持RETURNING
子句,可能需要放弃使用触发器,而是应用SQL表达式或用作“预执行”表达式:
t = Table('test', meta,
Column('abc', MyType, default=func.generate_new_value(), primary_key=True)
)
Where above, when Table.insert()
is used, the func.generate_new_value()
expression will be pre-executed in the context of a scalar SELECT
statement, and the new value will be applied to the subsequent INSERT
, while at the same time being made available to the ResultProxy.inserted_primary_key
attribute.
SQLAlchemy使用Sequence
对象表示数据库序列,这被认为是“列缺省”的特例。它只对数据库有明确的支持,这些数据库目前包括Postgresql,Oracle和Firebird。Sequence
对象被忽略。
Sequence
可以作为INSERT操作期间使用的“默认”生成器放置在任何列上,也可以配置为在UPDATE操作期间根据需要触发。它通常与单个整数主键列结合使用:
table = Table("cartitems", meta,
Column("cart_id", Integer, Sequence('cart_id_seq'), primary_key=True),
Column("description", String(40)),
Column("createdate", DateTime())
)
在上面,表“cartitems”与名为“cart_id_seq”的序列相关联。当针对“cartitems”发生INSERT语句并且没有为“cart_id”列传递值时,将使用“cart_id_seq”序列来生成一个值。
当Sequence
与表关联时,为该表颁发的CREATE和DROP语句也将为该序列对象发出CREATE / DROP,从而将序列对象与其父表“捆绑”。
Sequence
对象还实现了特殊的功能以适应Postgresql的SERIAL数据类型。PG中的SERIAL类型自动生成一个在插入过程中隐式使用的序列。这意味着如果一个Table
对象在其主键列上定义了一个Sequence
,以便它可以与Oracle和Firebird一起使用,那么Sequence
将进入PG通常使用的“隐式”序列的方式。对于这个用例,将标志optional=True
添加到Sequence
对象 - 这表明仅当数据库提供时才应使用Sequence
没有其他选项可用于生成主键标识符。
Sequence
对象也可以像SQL表达式那样独立执行,具有调用其“下一个值”功能的效果:
seq = Sequence('some_sequence')
nextid = connection.execute(seq)
当我们如上所述将Sequence
与Column
相关联时,此关联仅为in-Python only关联。将为我们的Table
生成的CREATE TABLE不会引用此序列。如果我们希望将序列用作服务器端缺省值,即使我们从SQL命令行向表中发出INSERT命令,也可以使用Column.server_default
参数与序列的值生成函数一起使用,可以从Sequence.next_value()
方法获得:
cart_id_seq = Sequence('cart_id_seq')
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())
)
上面的元数据将在Postgresql上生成一个CREATE TABLE语句,如下所示:
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的默认值放在上面,也就是说,它在Column
定义中提到了两次。根据所使用的后端,这可能不是严格必要的,例如在Postgresql后端,Core将使用RETURNING
访问新生成的主键值。However, for the best compatibility, Sequence
was originally intended to be a Python-side directive first and foremost so it’s probably a good idea to specify it in this way as well.
sqlalchemy.schema。
ColumnDefault
( arg,** kwargs T5> ) T6> ¶ T7>基础:sqlalchemy.schema.DefaultGenerator
列上的普通默认值。
这可以对应于常量,可调用函数或SQL子句。
ColumnDefault
is generated automatically whenever the default
, onupdate
arguments of Column
are used. 一个ColumnDefault
也可以在位置上传递。
例如,以下内容:
Column('foo', Integer, default=50)
相当于:
Column('foo', Integer, ColumnDefault(50))
sqlalchemy.schema.
DefaultClause
(arg, for_update=False, _reflected=False)¶基础:sqlalchemy.schema.FetchedValue
DDL指定的DEFAULT列值。
DefaultClause
is a FetchedValue
that also generates a “DEFAULT” clause when “CREATE TABLE” is emitted.
DefaultClause
is generated automatically whenever the server_default
, server_onupdate
arguments of Column
are used. 一个DefaultClause
也可以在位置上传递。
例如,以下内容:
Column('foo', Integer, server_default="50")
相当于:
Column('foo', Integer, DefaultClause("50"))
sqlalchemy.schema。
DefaultGenerator
( for_update = False / T5> ¶ T6>基础:sqlalchemy.schema._NotAColumnExpr
,sqlalchemy.schema.SchemaItem
列默认值的基类。
sqlalchemy.schema。 T1> FetchedValue T2> ( T3> FOR_UPDATE =假 T4> )< / T5> ¶ T6>
基础:sqlalchemy.schema._NotAColumnExpr
,sqlalchemy.sql.expression.SchemaEventTarget
透明数据库默认的标记。
当数据库配置为为列提供一些自动默认值时,使用FetchedValue
。
例如。:
Column('foo', Integer, FetchedValue())
将指出某个触发器或默认生成器将在INSERT期间为foo
列创建新值。
也可以看看
sqlalchemy.schema。
PassiveDefault
( * arg,**千瓦 T5> ) T6> ¶ T7>基础:sqlalchemy.schema.DefaultClause
DDL指定的DEFAULT列值。
从版本0.6开始弃用: PassiveDefault
已弃用。使用DefaultClause
。
sqlalchemy.schema.
Sequence
(name, start=None, increment=None, minvalue=None, maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, schema=None, optional=False, quote=None, metadata=None, quote_schema=None, for_update=False)¶基础:sqlalchemy.schema.DefaultGenerator
表示一个命名的数据库序列。
Sequence
对象表示数据库序列的名称和配置参数。它还表示一个可以由SQLAlchemy Engine
或Connection
执行的构造,为目标数据库呈现适当的“下一个值”函数并返回结果。
Sequence
通常与主键列关联:
some_table = Table(
'some_table', metadata,
Column('id', Integer, Sequence('some_table_seq'),
primary_key=True)
)
当针对上述Table
发出CREATE TABLE时,如果目标平台支持序列,则也会发出CREATE SEQUENCE语句。对于不支持序列的平台,忽略Sequence
结构。
__init__
(name, start=None, increment=None, minvalue=None, maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, schema=None, optional=False, quote=None, metadata=None, quote_schema=None, for_update=False)¶构建一个Sequence
对象。
参数: |
|
---|
create
(bind=None, checkfirst=True)¶在数据库中创建这个序列。
drop
(bind=None, checkfirst=True)¶从数据库中删除这个序列。
next_value T0> ( T1> ) T2> ¶ T3>
返回一个next_value
函数元素,该元素将为任何SQL表达式中的Sequence
提供适当的增量函数。