├── faq ├── index.html ├── metadata_schema.html └── sqlexpressions.html ├── core ├── expression_api.html ├── api_basics.html ├── types.html ├── serializer.html ├── engines_connections.html ├── index.html ├── schema.html └── inspection.html ├── orm ├── extending.html ├── extensions │ ├── index.html │ ├── declarative │ │ ├── index.html │ │ └── basic_use.html │ └── horizontal_shard.html ├── scalar_mapping.html ├── loading_objects.html ├── mapper_config.html ├── relationships.html ├── constructors.html ├── session.html ├── exceptions.html └── index.html ├── changelog └── index.html ├── dialects ├── sybase.html └── index.html └── intro.html /faq/index.html: -------------------------------------------------------------------------------- 1 |
“常见问题”部分收集了大量常见问题和众所周知的问题。
-------------------------------------------------------------------------------- /core/expression_api.html: -------------------------------------------------------------------------------- 1 |本节介绍SQL表达式语言的API参考。有关其用法的完整介绍,请参阅SQL Expression Language Tutorial。
SQLAlchemy提供了各种可用的ORM扩展,它们为核心行为增加了额外的功能。
扩展几乎完全基于公共核心和ORM API,应鼓励用户阅读其源代码以进一步理解其行为。特别是“水平分割”,“混合属性”和“突变跟踪”扩展非常简洁。
-------------------------------------------------------------------------------- /core/api_basics.html: -------------------------------------------------------------------------------- 1 |以下各节讨论如何将表列和SQL表达式映射到单个对象属性。
有关映射对象的一般加载的注释和功能。
有关查询SQLAlchemy ORM的深入介绍,请参阅Object Relational Tutorial。
SQLAlchemy更新日志和迁移指南现在集成在主文档中。
本节介绍可用于映射器的各种配置模式。它假定你已经完成了Object Relational Tutorial并知道如何构建和使用基本的映射器和关系。
Serializer / Deserializer对象与SQLAlchemy查询结构一起使用,允许“上下文”反序列化。
任何基于sqlalchemy.sql的SQLAlchemy查询结构。*或sqlalchemy.orm。*可以使用。映射器,表格,列,会话等结构引用的内容不是以序列化形式持久化的,而是在反序列化时与查询结构重新关联。
用法与标准Python pickle模块的用法几乎相同:
from sqlalchemy.ext.serializer import loads, dumps
2 | metadata = MetaData(bind=some_engine)
3 | Session = scoped_session(sessionmaker())
4 |
5 | # ... define mappers
6 |
7 | query = Session.query(MyClass).
8 | filter(MyClass.somedata=='foo').order_by(MyClass.sortkey)
9 |
10 | # pickle the query
11 | serialized = dumps(query)
12 |
13 | # unpickle. Pass in metadata + scoped_session
14 | query2 = loads(serialized, metadata, Session)
15 |
16 | print query2.all()与使用生腌菜时类似的限制适用;映射类本身必须是可以选择的,这意味着它们可以从模块级命名空间导入。
序列化器模块仅适用于查询结构。它不需要:
MetaData对象,通常是在某个先前时间点从现有数据库反映的对象。串行器模块专门用于相反的情况,其中表元数据已经存在于内存中。sqlalchemy.ext.serializer.Serializer(*args, **kw)¶sqlalchemy.ext.serializer.Deserializer(file, metadata=None, scoped_session=None, engine=None)¶sqlalchemy.ext.serializer.dumps(obj, protocol=0)¶sqlalchemy.ext.serializer.loads(data, metadata=None, scoped_session=None, engine=None)¶声明性系统是SQLAlchemy ORM提供的通常使用的系统,用于定义映射到关系数据库表的类。但是,正如Classical Mappings所述,Declarative实际上是一系列在SQLAlchemy mapper()结构之上的扩展。
虽然文档通常提到了大多数示例的声明,但以下各节将提供有关声明API如何与基本mapper()和Core Table系统交互的详细信息,如以及如何使用mixin等系统构建复杂模式。
水平分片支持。
定义了一个基本的“水平分割”系统,它允许会话跨多个数据库分发查询和持久性操作。
有关使用示例,请参阅源分布中包含的Horizontal Sharding示例。
sqlalchemy.ext.horizontal_shard.ShardedSession(shard_chooser, id_chooser, query_chooser, shards=None, query_cls=<class 'sqlalchemy.ext.horizontal_shard.ShardedQuery'>, **kwargs)¶基础:sqlalchemy.orm.session.Session
__init__(shard_chooser, id_chooser, query_chooser, shards=None, query_cls=<class 'sqlalchemy.ext.horizontal_shard.ShardedQuery'>, **kwargs)¶构建ShardedSession。
| 参数: |
|
|---|
本节介绍relationship()函数并深入讨论其用法。有关关系的介绍,请从Object Relational Tutorial开始,然后进入Building a Relationship。
注意
Sybase方言在当前的SQLAlchemy版本上运行,但没有经常测试,并且可能有许多问题和警告,目前尚未处理。
通过Python-Sybase驱动程序支持Sybase数据库。
Documentation and download information (if applicable) for Python-Sybase is available at: http://python-sybase.sourceforge.net/
python-sybase驱动程序目前似乎不支持任何类型的非ASCII字符串。
通过PyODBC驱动程序支持Sybase数据库。
PyODBC的文档和下载信息(如果适用)可在以下网址获得:http://pypi.python.org/pypi/pyodbc/
pyodbc驱动程序当前支持使用Unicode或多字节字符串的这些Sybase类型:
CHAR
2 | NCHAR
3 | NVARCHAR
4 | TEXT
5 | VARCHAR目前不支持的是:
UNICHAR
6 | UNITEXT
7 | UNIVARCHAR通过mxODBC驱动程序支持Sybase数据库。
mxODBC的文档和下载信息(如果适用)可在以下网址获得:http://www.egenix.com/
注意
这种方言只是一个存根,目前可能不起作用。
The breadth of SQLAlchemy’s SQL rendering engine, DBAPI integration, transaction integration, and schema description services are documented here. 与ORM的以领域为中心的使用模式相反,SQL表达式语言提供了一个以模式为中心的使用范例。
-------------------------------------------------------------------------------- /dialects/index.html: -------------------------------------------------------------------------------- 1 |方言是SQLAlchemy用来与各种类型的DBAPI实现和数据库进行通信的系统。以下部分包含参考文档和特定于每个后端用法的注释,以及各种DBAPI的注释。
所有方言都要求安装适当的DBAPI驱动程序。
在版本0.8中更改:从SQLAlchemy 0.8开始,几种方言已移至外部项目,新数据库的方言也将作为外部项目发布。这里的基本原理是保持基本的SQLAlchemy安装和测试套件的增长非常大。
诸如SQLite,MySQL,Postgresql,Oracle,SQL Server和Firebird等“经典”方言目前仍将保留在Core中。
在版本1.0中更改: Drizzle方言已被移入第三方系统。
当前SQLAlchemy的外部方言项目包括:
“阁楼”中的方言是早些时候为SQLAlchemy贡献的,但自那时以来很少受到关注或需求,现在迁移到自己的仓库中,最多只是半工作状态。对这些方言感兴趣的社区成员应该可以自由选择他们当前的代码库,并转入工作库。
映射不会对该类的构造函数(__init__)方法施加任何限制或要求。您可以自由地为您希望的函数请求任何参数,为ORM未知的实例分配属性,并且通常在编写Python类的构造函数时执行通常要做的任何其他操作。
当从数据库行重新创建对象时,SQLAlchemy ORM不会调用__init__。ORM的过程有点类似于Python标准库的pickle模块,调用低级别的__new__方法,然后直接在实例上静静地恢复属性,而不是调用__init__
如果您需要在数据库加载的实例准备就绪之前对其进行设置,那么可以使用@reconstructor修饰器将方法标记为__init__每次加载或重建实例时,SQLAlchemy都会在没有参数的情况下调用此方法。这对于重新创建通常在__init__中分配的瞬态属性非常有用:
from sqlalchemy import orm
2 |
3 | class MyMappedClass(object):
4 | def __init__(self, data):
5 | self.data = data
6 | # we need stuff on all instances, but not in the database.
7 | self.stuff = []
8 |
9 | @orm.reconstructor
10 | def init_on_load(self):
11 | self.stuff = []在执行obj = MyMappedClass()时,Python将__init__ normal和data参数是必需的。当像query(MyMappedClass).one()那样在Query操作期间加载实例时,会调用init_on_load。
任何方法都可以标记为reconstructor(),甚至可以标记为__init__方法。SQLAlchemy将调用没有参数的重构器方法。该实例的标量(非集合)数据库映射属性将可用于该函数中。急切加载的集合通常还不可用,通常只包含第一个元素。在此阶段对对象所做的ORM状态更改将不会记录下一次flush()操作,因此重构器中的活动应保守。
reconstructor()是一个更大的“实例级”事件系统的快捷方式,可以使用事件API进行订阅 - 请参阅InstanceEvents事件。
sqlalchemy.orm。 T0> 重建 T1> ( T2> FN T3> ) T4> ¶ T5 >装饰方法作为'重建'钩子。
Designates a method as the “reconstructor”, an __init__-like method that will be called by the ORM after the instance has been loaded from the database or otherwise reconstituted.
重构器将被调用,不带任何参数。该实例的标量(非集合)数据库映射属性将可用于该函数中。急切加载的集合通常还不可用,通常只包含第一个元素。在此阶段对对象所做的ORM状态更改将不会记录下一次flush()操作,因此重构器中的活动应保守。
orm.mapper()函数和declarative扩展是ORM的主要配置接口。一旦配置了映射,持久化操作的主要用法界面就是Session。
本节引用描述和检查数据库模式的全面系统SQLAlchemy 模式元数据。
SQLAlchemy的查询和对象映射操作的核心由数据库元数据支持,它由描述表和其他模式级对象的Python对象组成。这些对象是三种主要操作类型的核心 - 发出CREATE和DROP语句(称为DDL),构建SQL查询以及表达关于数据库中已存在的结构的信息。
数据库元数据可以通过使用诸如Table,Column,ForeignKey和Sequence,所有这些都是从sqlalchemy.schema包导入的。它也可以由SQLAlchemy使用名为reflection的进程生成,这意味着您从一个对象(如Table)开始,为其指定一个名称,然后指示SQLAlchemy加载与特定发动机源相关的所有附加信息。
SQLAlchemy的数据库元数据结构的一个关键特性是它们被设计成用于与真实DDL非常相似的声明式风格。因此,对于那些在创建真正的模式生成脚本方面有一定背景的人来说,他们最直观。
-------------------------------------------------------------------------------- /orm/exceptions.html: -------------------------------------------------------------------------------- 1 |SQLAlchemy ORM异常。
sqlalchemy.orm.exc。 T0> ConcurrentModificationError T1> ¶ T2>sqlalchemy.orm.exc。 DetachedInstanceError ¶尝试访问分离的映射实例上的卸载属性。
sqlalchemy.orm.exc。 FlushError ¶flush()期间检测到无效条件。
sqlalchemy.orm.exc。 MultipleResultsFound ¶单个数据库结果是必需的,但不止一个被发现。
sqlalchemy.orm.exc.NO_STATE = (<type 'exceptions.AttributeError'>, <type 'exceptions.KeyError'>)¶工具实现可能引发的异常类型。
sqlalchemy.orm.exc。 NoResultFound ¶数据库结果是必需的,但没有找到。
sqlalchemy.orm.exc。 ObjectDeletedError ( 状态,msg =无 T5> ) T6> ¶ T7>刷新操作无法检索与对象的已知主键标识相对应的数据库行。
刷新操作在对象上访问过期属性或使用Query.get()检索检索到的对象时检测为过期。基于主键为目标行发出SELECT;如果没有行被返回,则引发此异常。
这个异常的真正含义就是,不存在与持久对象关联的主键标识符的行。该行可能已被删除,或者在某些情况下主键已更新为新值,而不在ORM的目标对象管理之外。
sqlalchemy.orm.exc。 ObjectDereferencedError ¶由于垃圾收集对象,操作无法完成。
sqlalchemy.orm.exc。 StaleDataError ¶遇到数据库状态的操作未被记录。
导致这种情况发生的条件包括:
刷新可能试图更新或删除行,并且在UPDATE或DELETE语句期间意外数量的行被匹配。请注意,当使用version_id_col时,UPDATE或DELETE语句中的行也会与当前已知的版本标识符进行匹配。
具有版本_id_col的映射对象被刷新,并且从数据库返回的版本号与对象本身的版本号不匹配。
一个对象与其父对象分离,但是该对象先前被附加到了垃圾收集的不同父对象身上,并且如果新父对象实际上是最近的“父对象”,则不能做出决定。
New in version 0.7.4.
sqlalchemy.orm.exc。 UnmappedClassError ( cls,msg =无 T5> ) T6> ¶ T7>为未知类别请求映射操作。
sqlalchemy.orm.exc。 UnmappedColumnError ¶在未知列上请求映射操作。
sqlalchemy.orm.exc。 UnmappedError ¶基础包含预期映射不存在的异常。
sqlalchemy.orm.exc。 UnmappedInstanceError ( obj,msg =无 T5> ) T6> ¶ T7>为未知实例请求映射操作。
这里介绍并充分描述了对象关系映射器。如果您想使用为您自动构建的高级SQL以及Python对象的自动持久性,请首先阅读本教程。
-------------------------------------------------------------------------------- /core/inspection.html: -------------------------------------------------------------------------------- 1 |检查模块提供了inspect()函数,该函数在Core和ORM中传递有关各种SQLAlchemy对象的运行时信息。
inspect()函数是SQLAlchemy的公共API的入口点,用于查看内存中对象的配置和构造。根据传递给inspect()的对象的类型,返回值可以是提供已知接口的相关对象,或者在许多情况下它将返回对象本身。
inspect()的基本原理是双重的。One is that it replaces the need to be aware of a large variety of “information getting” functions in SQLAlchemy, such as Inspector.from_engine(), orm.attributes.instance_state(), orm.class_mapper(), and others. 另一个原因是,inspect()的返回值保证服从一个记录的API,因此允许构建在SQLAlchemy配置之上的第三方工具以前向兼容的方式构建。
0.8版中的新功能从版本0.8开始引入inspect()系统。
sqlalchemy.inspection.inspect(subject, raiseerr=True)¶为给定的目标生成检查对象。
在某些情况下,返回的值可能与给定的对象相同,例如传递Mapper对象。在其他情况下,它将是给定对象的注册检查类型的实例,例如,如果传递engine.Engine,则返回一个Inspector对象。
| 参数: |
|
|---|
以下列出了许多最常见的检查目标。
Connectable(即Engine,Connection) - 返回一个Inspector对象。ClauseElement - all SQL expression components, including Table, Column, serve as their own inspection objects, meaning any of these objects passed to inspect() return themselves.object - 给定的对象将由ORM检查映射 - 如果是,则返回表示对象映射状态的InstanceState。InstanceState还通过AttributeState接口提供对每个属性状态的访问,以及通过History访问任何属性的每次刷新“历史记录”目的。type(即类) - 给定的类将由ORM检查映射 - 如果是,则返回该类的Mapper。inspect(), such as inspect(MyClass.some_attribute), returns a QueryableAttribute object, which is the descriptor associated with a mapped class. This descriptor refers to a MapperProperty, which is usually an instance of ColumnProperty or RelationshipProperty, via its QueryableAttribute.property attribute.AliasedClass - 返回一个AliasedInsp对象。table.drop() / metadata.drop_all() ¶时,这通常对应于两个条件:1.使用对表锁确实严格的PostgreSQL,以及2.您的连接仍处于打开状态,其中包含表中的锁,并且与用于DROP语句的连接不同。下面是最小版本的模式:
connection = engine.connect()
2 | result = connection.execute(mytable.select())
3 |
4 | mytable.drop(engine)以上,连接池连接仍被检出;此外,上面的结果对象还保持与此连接的链接。如果使用“隐式执行”,则结果将保持此连接处于打开状态,直到结果对象关闭或所有行耗尽。
对mytable.drop(engine)的调用会尝试在从Engine采购的第二个连接上发出DROP TABLE,该连接将被锁定。
解决方法是在发出DROP TABLE之前关闭所有连接:
connection = engine.connect()
5 | result = connection.execute(mytable.select())
6 |
7 | # fully read result sets
8 | result.fetchall()
9 |
10 | # close connections
11 | connection.close()
12 |
13 | # now locks are removed
14 | mytable.drop(engine)一般ALTER支持不直接出现在SQLAlchemy中。对于特殊的DDL,可以使用DDL和相关的结构。有关此主题的讨论,请参阅core_ddl。
更全面的选择是使用模式迁移工具,例如Alembic或SQLAlchemy-Migrate;请参阅Altering Schemas through Migrations以便进行讨论。
这可以通过MetaData.sorted_tables函数使用:
metadata = MetaData()
15 | # ... add Table objects to metadata
16 | ti = metadata.sorted_tables:
17 | for t in ti:
18 | print(t)现代SQLAlchemy具有代表DDL操作的子句结构。这些可以像任何其他SQL表达式一样呈现为字符串:
from sqlalchemy.schema import CreateTable
19 |
20 | print(CreateTable(mytable))要获取特定于某个引擎的字符串:
print(CreateTable(mytable).compile(engine))还有一种特殊的Engine形式,可以让您使用以下配方转储整个元数据创建序列:
def dump(sql, *multiparams, **params):
21 | print(sql.compile(dialect=engine.dialect))
22 | engine = create_engine('postgresql://', strategy='mock', executor=dump)
23 | metadata.create_all(engine, checkfirst=False)Alembic工具还支持“离线”SQL生成模式,可将数据库迁移呈现为SQL脚本。
Table和Column不适合直接子类化。但是,有一些简单的方法可以使用创建函数获取构建行为,以及与模式对象之间的关联有关的行为,例如约束约定或使用附件事件的命名约定。在命名约定中可以看到许多这些技术的一个例子。
SQLAlchemy对象关系配置涉及Table,mapper()和类对象的组合以定义映射类。declarative allows all three to be expressed at once within the class declaration. 尽可能使用常规SQLAlchemy模式和ORM结构,因此“古典”ORM使用和声明性之间的配置保持高度相似。
举一个简单的例子:
from sqlalchemy.ext.declarative import declarative_base
2 |
3 | Base = declarative_base()
4 |
5 | class SomeClass(Base):
6 | __tablename__ = 'some_table'
7 | id = Column(Integer, primary_key=True)
8 | name = Column(String(50))在上面,declarative_base()可调用返回一个新的基类,所有映射类都应该继承它。当类定义完成时,将会生成一个新的Table和mapper()。
生成的表和映射器可以通过SomeClass类中的__table__和__mapper__属性访问:
# access the mapped Table
9 | SomeClass.__table__
10 |
11 | # access the Mapper
12 | SomeClass.__mapper__在前面的示例中,Column对象会自动使用它们所分配的属性的名称进行命名。
要使用与其映射属性不同的名称明确命名列,只需为该列命名即可。Below, column “some_table_id” is mapped to the “id” attribute of SomeClass, but in SQL will be represented as “some_table_id”:
class SomeClass(Base):
13 | __tablename__ = 'some_table'
14 | id = Column("some_table_id", Integer, primary_key=True)属性可以在其构造后添加到类中,并将它们根据需要添加到基础Table和mapper()定义中:
SomeClass.data = Column('data', Unicode)
15 | SomeClass.related = relationship(RelatedInfo)使用声明式构造的类可以与使用mapper()显式映射的类自由交互。
尽管不是必需的,但建议所有表共享相同的底层MetaData对象,以便可以毫无问题地解决字符串配置的ForeignKey引用。
declarative_base()基类包含一个MetaData对象,其中收集了新定义的Table对象。此对象旨在直接访问MetaData特定的操作。例如,为所有表发出CREATE语句:
engine = create_engine('sqlite://')
16 | Base.metadata.create_all(engine)declarative_base() can also receive a pre-existing MetaData object, which allows a declarative setup to be associated with an already existing traditional collection of Table objects:
mymetadata = MetaData()
17 | Base = declarative_base(metadata=mymetadata)作为一个方便的功能,declarative_base()在接受关键字参数的类上设置一个默认构造函数,并将它们分配给指定的属性:
e = Engineer(primary_language='python')声明在内部创建映射到声明表时使用mapper()函数。mapper()的选项直接通过__mapper_args__类属性传递。与往常一样,引用局部映射列的参数可以直接从类声明中引用它们:
from datetime import datetime
18 |
19 | class Widget(Base):
20 | __tablename__ = 'widgets'
21 |
22 | id = Column(Integer, primary_key=True)
23 | timestamp = Column(DateTime, nullable=False)
24 |
25 | __mapper_args__ = {
26 | 'version_id_col': timestamp,
27 | 'version_id_generator': lambda v:datetime.now()
28 | }有关将属性声明性映射到SQL表达式的示例,请参阅SQL Expressions as Mapped Attributes。
SQLAlchemy的SQL工具包和ORM是一套python数据库操作的综合工具包。它有多个不同领域的功能,可以单独使用或组合使用。其主要组件如下图所示,包含组件层次上的依赖关系。

如上图所示,SQLAlchemy 最重要的两个部分是 ORM 和 SQL 表达式语言。SQL表达式可以独立于ORM使用。使用 ORM 时,SQL 表达式语言仍然是公开 API 的一部分,因为它在对象关系配置和查询中使用。
文档分为三个部分: SQLAlchemy ORM、SQLAlchemy 核心和 方言(Dialects).
在 SQLAlchemy ORM中, 对象关系映射被充分引入和描述。新用户可以从对象关系教程开始。如果你想要了解自动构建高级SQL以及管理Python对象,推荐阅读此教程。
在 SQLAlchemy Core 中,主要介绍了SQLAlchemy 的 SQL、数据库集成和描述服务, 这部分的核心是 SQL 表达语言。SQL 表达式是独立于 ORM 包的一套自成一体的工具集, 它可以用来创建易于使用的 SQ 表达式,该 SQL 表达式可通过编程创建、修改和执行,返回游标结果集。对比 ORM 使用域为中心的方式,表达语言提供模式为中心的架构。新用户请从 SQL 表达式教程开始。SQLAlchemy 引擎,链接和池服务同样在SQLAlchemy Core中有描述。
Dialects介绍了所有 SQLAlchemy 支持的数据库和 DBAPI 后端。
主要关于ORM的工作代码示例包含在SQLAlchemy发行版中.所有包含的示例应用程序的描述在ORM Examples.中。
还有各种各样的示例涉及核心SQLAlchemy构造以及维基上的ORM, 参见Theatrum Chemicum。
SQLAlchemy已经针对以下平台进行了测试:
在0.9版本中更改: Python 2.6现在是支持的最小Python版本。
目前不支持的平台包括Jython,IronPython。曾经已经支持 Jython,并且可能会在将来的版本中支持,这取决于Jython本身的状态。
SQLAlchemy安装是通过基于setuptools的标准Python方法,通过直接引用setup.py或通过使用pip或其他setuptools,兼容的方法。
在版本1.1中更改: setup.py文件现在需要setuptools;不再支持简单的distutils安装。
当pip可用时,可以从Pypi下载并在一个步骤中安装该分发:
pip install SQLAlchemy该命令将从Python Cheese Shop下载最新的发布的版SQLAlchemy并将其安装到您的系统中。
为了安装最新的prerelease版本,比如1.1.0b1,pip要求使用--pre标志:
pip install --pre SQLAlchemy如上所述,如果最新版本是预发行版本,则将安装它而不是最新发布的版本。
SQLAlchemy包含C扩展,它提供了额外的速度提升来处理结果集。这些扩展在cPython的2.xx和3.xx系列上均受支持。
setup.py will automatically build the extensions if an appropriate platform is detected. 如果C扩展的构建失败,由于缺少编译器或其他问题,安装过程将输出警告消息,并在完成报告最终状态时重新运行没有C扩展的构建。
要运行构建/安装而不尝试编译C扩展,可以指定DISABLE_SQLALCHEMY_CEXT环境变量。对于这种情况的用例要么是针对特殊的测试环境,要么是通常的“重建”机制无法解决的罕见情况下的兼容性/构建问题:
export DISABLE_SQLALCHEMY_CEXT=1; python setup.py install在版本1.1中更改:遗留的--without-cextensions标志已从安装程序中删除,因为它依赖于setuptools的不推荐使用的功能。
SQLAlchemy直接在Python 2或Python 3上运行,并且可以在任何环境中安装,无需任何调整或代码转换。
SQLAlchemy旨在与针对特定数据库构建的DBAPI实现一起运行,并包含对最流行数据库的支持。The individual database sections in Dialects enumerate the available DBAPIs for each database, including external links.
本文档涵盖了SQLAlchemy版本1.1。如果您正在使用已安装SQLAlchemy的系统,请从您的Python提示符中检查版本,如下所示:
>>> import sqlalchemy
2 | >>> sqlalchemy.__version__ # doctest: +SKIP
3 | 1.1.0Notes on what’s changed from 1.0 to 1.1 is available here at What’s New in SQLAlchemy 1.1?.
在绝大多数情况下,SQLAlchemy语句或Query的“字符串化”非常简单:
print(str(statement))这适用于ORM Query以及任何select()或其他语句。此外,要将语句编译为特定的方言或引擎,如果语句本身尚未绑定到某个语句,您可以将它传递给ClauseElement.compile():
print(statement.compile(someengine))或者没有Engine:
from sqlalchemy.dialects import postgresql
2 | print(statement.compile(dialect=postgresql.dialect()))当给定ORM Query对象时,为了获得ClauseElement.compile()方法,我们只需要首先访问statement访问器:
statement = query.statement
3 | print(statement.compile(someengine))上述表单将在传递给Python DBAPI时呈现SQL语句,其中包括绑定参数不以内联方式呈现。SQLAlchemy通常不绑定绑定参数,因为这是由Python DBAPI适当地处理的,更不用说绕过绑定参数可能是现代Web应用程序中使用最广泛的安全漏洞。SQLAlchemy在某些情况下(例如发出DDL)的能力有限。为了访问这个功能,可以使用传递给compile_kwargs的literal_binds标志:
from sqlalchemy.sql import table, column, select
4 |
5 | t = table('t', column('x'))
6 |
7 | s = select([t]).where(t.c.x == 5)
8 |
9 | print(s.compile(compile_kwargs={"literal_binds": True}))上面的方法有一点要注意,它只支持基本类型,例如整数和字符串,而且如果直接使用没有预设值的bindparam(),它将不会能够将其串联起来。
要支持对不支持类型的内联文字渲染,请为包含TypeDecorator.process_literal_param()方法的目标类型实现一个TypeDecorator:
from sqlalchemy import TypeDecorator, Integer
10 |
11 |
12 | class MyFancyType(TypeDecorator):
13 | impl = Integer
14 |
15 | def process_literal_param(self, value, dialect):
16 | return "my_fancy_formatting(%s)" % value
17 |
18 | from sqlalchemy import Table, Column, MetaData
19 |
20 | tab = Table('mytable', MetaData(), Column('x', MyFancyType()))
21 |
22 | print(
23 | tab.select().where(tab.c.x > 5).compile(
24 | compile_kwargs={"literal_binds": True})
25 | )产出如下产出:
SELECT mytable.x
26 | FROM mytable
27 | WHERE mytable.x > my_fancy_formatting(5).col.in_([])产生col != col ?为什么不1=0?¶关于这个问题的一点介绍。SQL中的IN运算符给出了要与列进行比较的元素列表,但通常不会接受空列表,即可以这样说:
column IN (1, 2, 3)这是无效的说:
column IN ()SQLAlchemy的Operators.in_()运算符在给出一个空列表时产生这个表达式:
column != column从版本0.6开始,它也会产生一个警告,指出将会呈现效率较低的比较操作。这个表达式是唯一一个既是数据库不可知的,又能产生正确结果的表达式。
例如,“通过比较1 = 0或1!= 1来评估为假”的幼稚方法不能正确处理空值。表达式如下:
NOT column != column当“列”为空时不会返回一行,但是不考虑列的表达式:
NOT 1=0将。
更接近该商标的是以下CASE表达式:
CASE WHEN column IS NOT NULL THEN 1=0 ELSE NULL END我们不使用这个表达式,因为它的冗长,而且在WHERE子句中它也不被Oracle接受 - 取决于你如何说出它,你会得到“ORA-00905:missing keyword”或者“ORA-00920 :无效的关系运算符“。它的效率还不如完全没有子句的情况下渲染SQL(或者根本不发布SQL,如果语句只是简单的搜索)。
因此,最好的方法是在零长度的参数列表中避免使用IN。相反,如果不应返回行,请不要首先发出查询。警告最好使用Python警告过滤器提升为完全错误状态(请参阅http://docs.python.org/library/warnings.html)。