SQLAlchemy 1.1文档
定制DDL ¶
In the preceding sections we’ve discussed a variety of schema constructs including Table
, ForeignKeyConstraint
, CheckConstraint
, and Sequence
. Throughout, we’ve relied upon the create()
and create_all()
methods of Table
and MetaData
in order to issue data definition language (DDL) for all constructs. 在发布时,调用预定义的操作顺序,并且创建每个表的DDL被无条件地创建,包括与其相关联的所有约束和其他对象。对于需要特定于数据库的DDL的更复杂场景,SQLAlchemy提供了两种技术,可用于根据任何条件添加任何DDL,可以伴随标准的表生成或自身。
自定义DDL ¶
使用DDL
结构最容易实现自定义DDL短语。这个构造像所有其他的DDL元素一样工作,除了它接受一个字符串,它是要发射的文本:
event.listen(
metadata,
"after_create",
DDL("ALTER TABLE users ADD CONSTRAINT "
"cst_user_name_length "
" CHECK (length(user_name) >= 8)")
)
创建DDL结构库的更全面的方法是使用自定义编译 - 有关详细信息,请参阅Custom SQL Constructs and Compilation Extension。
控制DDL序列¶
先前引入的DDL
构造也具有基于对数据库的检查有条件调用的能力。该功能可以使用DDLElement.execute_if()
方法。例如,如果我们想创建一个触发器,但只能在Postgresql后端上,我们可以这样调用它:
mytable = Table(
'mytable', metadata,
Column('id', Integer, primary_key=True),
Column('data', String(50))
)
trigger = DDL(
"CREATE TRIGGER dt_ins BEFORE INSERT ON mytable "
"FOR EACH ROW BEGIN SET NEW.data='ins'; END"
)
event.listen(
mytable,
'after_create',
trigger.execute_if(dialect='postgresql')
)
DDLElement.execute_if.dialect
关键字也接受字符串方言名称的元组:
event.listen(
mytable,
"after_create",
trigger.execute_if(dialect=('postgresql', 'mysql'))
)
event.listen(
mytable,
"before_drop",
trigger.execute_if(dialect=('postgresql', 'mysql'))
)
DDLElement.execute_if()
方法也可以用于可接收数据库连接的可调用函数。在下面的例子中,我们使用它来有条件地创建CHECK约束,首先在Postgresql目录中查看它是否存在:
def should_create(ddl, target, connection, **kw):
row = connection.execute(
"select conname from pg_constraint where conname='%s'" %
ddl.element.name).scalar()
return not bool(row)
def should_drop(ddl, target, connection, **kw):
return not should_create(ddl, target, connection, **kw)
event.listen(
users,
"after_create",
DDL(
"ALTER TABLE users ADD CONSTRAINT "
"cst_user_name_length CHECK (length(user_name) >= 8)"
).execute_if(callable_=should_create)
)
event.listen(
users,
"before_drop",
DDL(
"ALTER TABLE users DROP CONSTRAINT cst_user_name_length"
).execute_if(callable_=should_drop)
)
sqlusers.create(engine)
CREATE TABLE users (
user_id SERIAL NOT NULL,
user_name VARCHAR(40) NOT NULL,
PRIMARY KEY (user_id)
)
select conname from pg_constraint where conname='cst_user_name_length'
ALTER TABLE users ADD CONSTRAINT cst_user_name_length CHECK (length(user_name) >= 8)
sqlusers.drop(engine)
select conname from pg_constraint where conname='cst_user_name_length'
ALTER TABLE users DROP CONSTRAINT cst_user_name_length
DROP TABLE users
使用内置的DDLElement类¶
sqlalchemy.schema
包包含提供DDL表达式的SQL表达式结构。例如,要产生一个CREATE TABLE
语句:
from sqlalchemy.schema import CreateTable
sqlengine.execute(CreateTable(mytable))
CREATE TABLE mytable (
col1 INTEGER,
col2 INTEGER,
col3 INTEGER,
col4 INTEGER,
col5 INTEGER,
col6 INTEGER
)
在上面,CreateTable
构造像任何其他表达式构造一样工作(如select()
,table.insert()
等)。所有SQLAlchemy的面向DDL的构造都是DDLElement
基类的子类;这是对应于CREATE和DROP以及ALTER的所有对象的基础,不仅在SQLAlchemy中,而且在Alembic Migrations中也是如此。可用构造的完整引用位于DDL Expression Constructs API中。
用户定义的DDL结构也可以创建为DDLElement
本身的子类。Custom SQL Constructs and Compilation Extension中的文档有几个例子。
上一节Controlling DDL Sequences中描述的事件驱动的DDL系统也可以与其他DDLElement
对象一起使用。However, when dealing with the built-in constructs such as CreateIndex
, CreateSequence
, etc, the event system is of limited use, as methods like Table.create()
and MetaData.create_all()
will invoke these constructs unconditionally. 在未来的SQLAlchemy发行版中,包含条件执行的DDL事件系统将考虑目前在所有情况下调用的内置构造。
我们可以用AddConstraint
和DropConstraint
结构来说明一个事件驱动的例子,因为事件驱动系统可以用于CHECK和UNIQUE约束,像我们在DDLElement.execute_if()
的前一个例子:
def should_create(ddl, target, connection, **kw):
row = connection.execute(
"select conname from pg_constraint where conname='%s'" %
ddl.element.name).scalar()
return not bool(row)
def should_drop(ddl, target, connection, **kw):
return not should_create(ddl, target, connection, **kw)
event.listen(
users,
"after_create",
AddConstraint(constraint).execute_if(callable_=should_create)
)
event.listen(
users,
"before_drop",
DropConstraint(constraint).execute_if(callable_=should_drop)
)
sqlusers.create(engine)
CREATE TABLE users (
user_id SERIAL NOT NULL,
user_name VARCHAR(40) NOT NULL,
PRIMARY KEY (user_id)
)
select conname from pg_constraint where conname='cst_user_name_length'
ALTER TABLE users ADD CONSTRAINT cst_user_name_length CHECK (length(user_name) >= 8)
sqlusers.drop(engine)
select conname from pg_constraint where conname='cst_user_name_length'
ALTER TABLE users DROP CONSTRAINT cst_user_name_length
DROP TABLE users
While the above example is against the built-in AddConstraint
and DropConstraint
objects, the main usefulness of DDL events for now remains focused on the use of the DDL
construct itself, as well as with user-defined subclasses of DDLElement
that aren’t already part of the MetaData.create_all()
, Table.create()
, and corresponding “drop” processes.
DDL表达式构造API ¶
-
sqlalchemy.schema.
sort_tables
(tables, skip_fn=None, extra_dependencies=None)¶ 根据依赖关系排序
Table
对象的集合。这是一个依赖排序的排序,它将发射
Table
对象,以便它们将遵循其依赖的Table
对象。根据ForeignKeyConstraint
对象的存在以及Table.add_is_dependent_on()
添加的显式依赖关系,表依赖于另一个表。警告
The
sort_tables()
function cannot by itself accommodate automatic resolution of dependency cycles between tables, which are usually caused by mutually dependent foreign key constraints. 要解决这些循环,可以将ForeignKeyConstraint.use_alter
参数应用于这些约束,或者使用sql.sort_tables_and_constraints()
函数来打破涉及分开循环。参数: - tables¶ – a sequence of
Table
objects. - skip_fn¶ – optional callable which will be passed a
ForeignKey
object; if it returns True, this constraint will not be considered as a dependency. Note this is different from the same parameter insort_tables_and_constraints()
, which is instead passed the owningForeignKeyConstraint
object. - extra_dependencies ¶ - 表格的2元组序列,也将被视为相互依赖。
- tables¶ – a sequence of
-
sqlalchemy.schema.
sort_tables_and_constraints
(tables, filter_fn=None, extra_dependencies=None)¶ 对
Table
/ForeignKeyConstraint
对象的集合进行排序。这是一个依赖排序的排序,它将发出
(Table, [ForeignKeyConstraint, ...]) t0的元组>使得每个
RemainingTable
遵循其依赖的Table
对象。ForeignKeyConstraint
objects that are separate due to dependency rules not satisifed by the sort are emitted afterwards as(None, [ForeignKeyConstraint ...])
.Tables are dependent on another based on the presence of
ForeignKeyConstraint
objects, explicit dependencies added byTable.add_is_dependent_on()
, as well as dependencies stated here using theskip_fn
and/orextra_dependencies
parameters.参数: - tables¶ – a sequence of
Table
objects. - filter_fn¶ – optional callable which will be passed a
ForeignKeyConstraint
object, and returns a value based on whether this constraint should definitely be included or excluded as an inline constraint, or neither. 如果它返回False,那么这个约束肯定会被包含作为一个不受ALTER约束的依赖;如果为True,则仅在结尾处包含作为ALTER结果。返回无意味着约束被包含在基于表格的结果中,除非它被检测为依赖周期的一部分。 - extra_dependencies ¶ - 表格的2元组序列,也将被视为相互依赖。
版本1.0.0中的新功能
也可以看看
- tables¶ – a sequence of
- class
sqlalchemy.schema。
DDLElement
¶ 基础:
sqlalchemy.sql.expression.Executable
,sqlalchemy.schema._DDLCompiles
DDL表达式构造的基类。
This class is the base for the general purpose
DDL
class, as well as the various create/drop clause constructs such asCreateTable
,DropTable
,AddConstraint
, etc.DDLElement
与Events中介绍的SQLAlchemy事件紧密集成。一个实例本身就是一个接收可调用的事件:event.listen( users, 'after_create', AddConstraint(constraint).execute_if(dialect='postgresql') )
__ call __
( target,bind,** kw T5> ¶ T6>以ddl_listener的身份执行DDL。
针对 T0> ( T1> 靶 T2> ) T3> ¶ T4>
针对特定模式项目返回此DDL的副本。
结合 T0> ¶ T1>
callable _
=无 ¶
方言
=无 ¶
-
execute
(bind=None, target=None)¶ 立即执行此DDL。
如果未提供,则使用分配给
.bind
属性的Connectable
或Connectable
执行DDL语句。如果DDL在标准上有条件的on
参数: - bind¶ – Optional, an
Engine
orConnection
. 如果未提供,则必须在.bind
属性中存在有效的Connectable
。 - target ¶ - 可选,默认为None。执行调用的目标SchemaItem。将被传递给
on
callable(如果有),并且还可以为该语句提供字符串扩展数据。有关更多信息,请参阅execute_at
。
- bind¶ – Optional, an
-
execute_at
(event_name, target)¶ 将此DDL的执行链接到SchemaItem的DDL生命周期。
从版本0.7开始弃用:请参阅
DDLEvents
以及DDLElement.execute_if()
。将此
DDLElement
链接到Table
或MetaData
实例,并在该架构项创建或删除时执行该实例。DDL语句将使用与表创建/删除本身相同的连接和事务上下文来执行。该语句的.bind
属性被忽略。参数: DDLElement实例可以链接到任意数量的模式项目。
execute_at
建立在MetaData
和Table
对象的append_ddl_listener
接口上。警告:创建或删除独立的表也会触发任何DDL设置为
execute_at
表的元数据。这可能会在未来的版本中发生变化。
execute_if
( dialect = None,callable_ = None,state = None ) T5> ¶ T6>返回可执行此DDLElement的可调用对象。
用于提供事件监听的包装:
event.listen( metadata, 'before_create', DDL("my_ddl").execute_if(dialect='postgresql') )
参数: - dialect ¶ -
可能是一个字符串,元组或可调用谓词。如果是字符串,则会将其与正在执行的数据库方言的名称进行比较:
DDL('something').execute_if(dialect='postgresql')
如果一个元组指定多个方言名称:
DDL('something').execute_if(dialect=('postgresql', 'mysql'))
- callable _ ¶ -
一个可调用的对象,它将被调用四个位置参数以及可选的关键字参数:
DDL: 这个DDL元素。 目标: Table
或MetaData
对象是此事件的目标。如果DDL是明确执行的,可能是None。绑定: 用于DDL执行的 Connection
表: 可选关键字参数 - 要在MetaData.create_all()或drop_all()方法调用中创建/删除的Table对象的列表。 州: 可选的关键字参数 - 将成为传递给此函数的 state
参数。checkfirst: Keyword argument, will be True if the ‘checkfirst’ flag was set during the call to create()
,create_all()
,drop()
,drop_all()
.如果callable返回一个真值,则会执行DDL语句。
- state¶ – any value which will be passed to the callable_ as the
state
keyword argument.
- dialect ¶ -
on
=无 ¶
目标
=无 ¶
- class
sqlalchemy.schema。
DDL
( 语句,on =无context = None,bind = None ) ¶ 基础:
sqlalchemy.schema.DDLElement
一个文字DDL语句。
指定要由数据库执行的文字SQL DDL。DDL对象充当DDL事件侦听器,可以使用
Table
或MetaData
对象作为目标来订阅DDLEvents
中列出的事件。基本模板支持允许单个DDL实例处理多个表的重复任务。例子:
from sqlalchemy import event, DDL tbl = Table('users', metadata, Column('uid', Integer)) event.listen(tbl, 'before_create', DDL('DROP TRIGGER users_trigger')) spow = DDL('ALTER TABLE %(table)s SET secretpowers TRUE') event.listen(tbl, 'after_create', spow.execute_if(dialect='somedb')) drop_spow = DDL('ALTER TABLE users SET secretpowers FALSE') connection.execute(drop_spow)
在Table事件上进行操作时,可以使用以下
statement
字符串替换:%(table)s - the Table name, with any required quoting applied %(schema)s - the schema name, with any required quoting applied %(fullname)s - the Table name including schema, quoted if needed
DDL的“上下文”(如果有的话)将与上述标准替换结合使用。上下文中出现的键将覆盖标准替换。
-
__init__
(statement, on=None, context=None, bind=None)¶ 创建一个DDL语句。
参数: - 语句 ¶ -
要执行的字符串或unicode字符串。语句将用Python的字符串格式化操作符处理。请参阅
context
参数和execute_at
方法。语句中的文字'%'必须转义为'%%'。
SQL绑定参数在DDL语句中不可用。
- on ¶ -
从版本0.7开始弃用:请参阅
DDLElement.execute_if()
。可选的过滤标准。可能是一个字符串,元组或可调用谓词。如果是字符串,则会将其与正在执行的数据库方言的名称进行比较:
DDL('something', on='postgresql')
如果一个元组指定多个方言名称:
DDL('something', on=('postgresql', 'mysql'))
如果是可调用的,则会调用四个位置参数以及可选的关键字参数:
DDL: 这个DDL元素。 事件: 触发此DDL的事件的名称,例如'after-create'如果显式执行DDL,则为None。 目标: Table
或MetaData
对象是此事件的目标。如果DDL是明确执行的,可能是None。连接: 用于DDL执行的 Connection
表: 可选关键字参数 - 要在MetaData.create_all()或drop_all()方法调用中创建/删除的Table对象的列表。 如果callable返回一个真值,则会执行DDL语句。
- 上下文 ¶ - 可选字典,默认为None。这些值将可用于DDL语句中的字符串替换。
- 绑定 ¶ - 可选。一个
Connectable
,当execute()
没有绑定参数时被调用时默认使用。
- 语句 ¶ -
-
- class
sqlalchemy.schema.
_CreateDropBase
(element, on=None, bind=None)¶ 基础:
sqlalchemy.schema.DDLElement
表示CREATE和DROP或等价物的DDL结构的基类。
_CreateDropBase的常见主题是单个
element
属性,它指向要创建或删除的元素。
- class
sqlalchemy.schema.
CreateTable
(element, on=None, bind=None, include_foreign_key_constraints=None)¶ 基础:
sqlalchemy.schema._CreateDropBase
表示一个CREATE TABLE语句。
-
__init__
(element, on=None, bind=None, include_foreign_key_constraints=None)¶ 创建一个
CreateTable
结构。参数:
-
- class
sqlalchemy.schema.
DropTable
(element, on=None, bind=None)¶ 基础:
sqlalchemy.schema._CreateDropBase
表示DROP TABLE语句。
- class
sqlalchemy.schema。
CreateColumn
( 元素 ) t5 > ¶ T6> 基础:
sqlalchemy.schema._DDLCompiles
将
Column
表示为通过CreateTable
结构呈现在CREATE TABLE语句中。通过使用Custom SQL Constructs and Compilation Extension中介绍的编译器扩展来扩展
CreateColumn
,可以在CREATE TABLE语句的生成过程中支持自定义列DDL。典型的集成是检查传入的
Column
对象,并在找到特定标志或条件时重定向编译:from sqlalchemy import schema from sqlalchemy.ext.compiler import compiles @compiles(schema.CreateColumn) def compile(element, compiler, **kw): column = element.element if "special" not in column.info: return compiler.visit_create_column(element, **kw) text = "%s SPECIAL DIRECTIVE %s" % ( column.name, compiler.type_compiler.process(column.type) ) default = compiler.get_column_default_string(column) if default is not None: text += " DEFAULT " + default if not column.nullable: text += " NOT NULL" if column.constraints: text += " ".join( compiler.process(const) for const in column.constraints) return text
上述构造可以应用于
Table
,如下所示:from sqlalchemy import Table, Metadata, Column, Integer, String from sqlalchemy import schema metadata = MetaData() table = Table('mytable', MetaData(), Column('x', Integer, info={"special":True}, primary_key=True), Column('y', String(50)), Column('z', String(20), info={"special":True}) ) metadata.create_all(conn)
以上,我们添加到
Column.info
集合的指令将被我们的自定义编译方案检测到:CREATE TABLE mytable ( x SPECIAL DIRECTIVE INTEGER NOT NULL, y VARCHAR(50), z SPECIAL DIRECTIVE VARCHAR(20), PRIMARY KEY (x) )
当生成
CREATE TABLE
时,CreateColumn
结构也可用于跳过某些列。这是通过创建有条件地返回None
的编译规则来完成的。这基本上是如何产生与在Column
上使用system=True
参数相同的效果,它将列标记为隐式存在的“系统”列。例如,假设我们希望产生一个
Table
,该表跳过Postgresql后端对Postgresqlxmin
列的渲染,但是在其他后端确实呈现它,预期触发规则。条件编译规则可以仅在Postgresql上跳过此名称:from sqlalchemy.schema import CreateColumn @compiles(CreateColumn, "postgresql") def skip_xmin(element, compiler, **kw): if element.element.name == 'xmin': return None else: return compiler.visit_create_column(element, **kw) my_table = Table('mytable', metadata, Column('id', Integer, primary_key=True), Column('xmin', Integer) )
以上,一个
CreateTable
结构将产生一个CREATE TABLE
,其中只包含id
字符串中的列;xmin
列将被省略,但仅针对Postgresql后端。0.8.3版中的新功能
CreateColumn
构造支持通过从自定义编译规则返回None
跳过列。0.8版新增:添加了
CreateColumn
结构以支持自定义列创建样式。
- class
sqlalchemy.schema.
CreateSequence
(element, on=None, bind=None)¶ 基础:
sqlalchemy.schema._CreateDropBase
表示一个CREATE SEQUENCE语句。
- class
sqlalchemy.schema.
DropSequence
(element, on=None, bind=None)¶ 基础:
sqlalchemy.schema._CreateDropBase
表示DROP SEQUENCE语句。
- class
sqlalchemy.schema.
CreateIndex
(element, on=None, bind=None)¶ 基础:
sqlalchemy.schema._CreateDropBase
表示CREATE INDEX语句。
- class
sqlalchemy.schema.
DropIndex
(element, on=None, bind=None)¶ 基础:
sqlalchemy.schema._CreateDropBase
代表DROP INDEX语句。
- class
sqlalchemy.schema。
AddConstraint
( 元素,/ t5>,** kw ) ¶ 基础:
sqlalchemy.schema._CreateDropBase
表示ALTER TABLE ADD CONSTRAINT语句。
- class
sqlalchemy.schema。
DropConstraint
( 元素,cascade = False ,** kw ) ¶ 基础:
sqlalchemy.schema._CreateDropBase
表示一个ALTER TABLE DROP CONSTRAINT语句。
- class
sqlalchemy.schema。
CreateSchema
( name,quote =无,** kw ) ¶ 基础:
sqlalchemy.schema._CreateDropBase
表示CREATE SCHEMA语句。
New in version 0.7.4.
这里的参数是模式的字符串名称。
__ init __
( name,quote =无,** kw ) T5> ¶ T6>创建一个新的
CreateSchema
结构。
- class
sqlalchemy.schema。
DropSchema
( name,quote =无cascade = False,** kw ) ¶ 基础:
sqlalchemy.schema._CreateDropBase
代表DROP SCHEMA语句。
这里的参数是模式的字符串名称。
New in version 0.7.4.
-
__init__
(name, quote=None, cascade=False, **kw)¶ 创建一个新的
DropSchema
结构。
-