Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

使用引擎和接头

本节详细介绍了 EngineConnection 以及相关对象。重要的是要注意,当使用sqlAlchemy ORM时,通常不会访问这些对象;相反,这些对象 Session 对象用作数据库的接口。但是,对于围绕直接使用文本SQL语句和/或SQL表达式构造而构建的应用程序,而不需要ORM的更高级别管理服务的参与,则 EngineConnection 是国王(还是王后?)-继续阅读。

基本用法

回忆起 引擎配置 那是 Engine 通过创建 create_engine() 呼叫:

engine = create_engine('mysql://scott:tiger@localhost/test')

的典型用法 create_engine() 是每个特定数据库URL一次,在单个应用程序进程的生命周期内全局保存。单一的 Engine 管理许多个人 DBAPI 代表进程的连接,并打算以并发方式调用。这个 Enginenot 与DBAPI同义 connect 函数,它只表示一个连接资源 Engine 仅在应用程序的模块级创建一次,而不是每个对象或每个函数调用时,效率最高。

最基本的功能 Engine 提供访问 Connection ,然后可以调用SQL语句。向数据库发出文本语句如下所示:

from sqlalchemy import text

with engine.connect() as connection:
    result = connection.execute(text("select username from users"))
    for row in result:
        print("username:", row['username'])

上面, Engine.connect() 方法返回 Connection 对象,并在Python上下文管理器中使用它(例如 with: 声明)the Connection.close() 方法在块末尾自动调用。这个 Connection 是一个 代理 对象获取实际的DBAPI连接。DBAPI连接是在 Connection 创建。

返回的对象称为 CursorResult ,它引用DBAPI游标,并提供用于获取与DBAPI游标类似的行的方法。DBAPI光标将由 CursorResult 当它的所有结果行(如果有)用完时。一 CursorResult 它不返回任何行,例如UPDATE语句的行(不返回任何行),在构造后立即释放光标资源。

Connection 在结束时关闭 with: 块,引用的DBAPI连接是 released 到连接池。从数据库本身的角度来看,假设连接池有空间存储此连接以备下次使用,那么连接池实际上不会“关闭”连接。当连接返回池以供重新使用时,池机制将发出一个 rollback() 调用DBAPI连接,以便删除所有事务状态或锁,并且该连接已准备好供下次使用。

2.0 版后已移除: 这个 CursorResult 对象在SQLAlchemy 2.0中被替换为 Result .

上面的示例演示了文本SQL字符串的执行,应该使用 text() 构造来指示我们希望使用文本SQL。这个 Connection.execute() 方法当然可以容纳更多的内容,包括中描述的各种SQL表达式构造。 SQL表达式语言教程(1.x API) .

使用事务

注解

本节介绍如何在直接处理事务时使用事务 EngineConnection 物体。使用SQLAlchemy ORM时,用于事务控制的公共API通过 Session 对象,它使用 Transaction 对象内部。见 管理交易 更多信息。

这个 Connection 对象提供 Connection.begin() 返回 Transaction 对象。就像 Connection 它本身通常在Python中使用 with: 块以便管理其作用域:

with engine.connect() as connection:
    with connection.begin():
        r1 = connection.execute(table1.select())
        connection.execute(table1.insert(), {"col1": 7, "col2": "this is some data"})

上面的块可以通过使用 Engine.begin() 方法 Engine ::

# runs a transaction
with engine.begin() as connection:
    r1 = connection.execute(table1.select())
    connection.execute(table1.insert(), {"col1": 7, "col2": "this is some data"})

各自管理的区块 .begin() 方法的行为使得在块完成时提交事务。如果引发异常,则会回滚事务,并向外传播异常。

用于表示事务的基础对象是 Transaction 对象。此对象由 Connection.begin() 方法,包括方法 Transaction.commit()Transaction.rollback() . 推荐使用上下文管理器调用表单(它自动调用这些方法)作为最佳实践。

事务块的嵌套

1.4 版后已移除: SQLAlchemy的“事务嵌套”特性是一个在1.4版本中不推荐使用的遗留特性,它将在SQLAlchemy 2.0中删除。这个模式已经被证明有点太笨拙和复杂了,除非应用程序围绕行为创建了更多的一流框架。见以下小节 作为反模式的任意事务嵌套 .

这个 Transaction 对象还通过跟踪最外层的begin/commit对来处理“嵌套”行为。在本例中,两个函数都在 Connection 但只有最外面的 Transaction 对象在提交时实际生效。

# method_a starts a transaction and calls method_b
def method_a(connection):
    with connection.begin():  # open a transaction
        method_b(connection)

# method_b also starts a transaction
def method_b(connection):
    with connection.begin(): # open a transaction - this runs in the
                             # context of method_a's transaction
        connection.execute(text("insert into mytable values ('bat', 'lala')"))
        connection.execute(mytable.insert(), {"col1": "bat", "col2": "lala"})

# open a Connection and call method_a
with engine.connect() as conn:
    method_a(conn)

上面, method_a 先被调用,它调用 connection.begin() . 然后它呼叫 method_b . 什么时候? method_b 电话 connection.begin() ,它只是递增一个计数器,当它调用 commit() . 如果任一 method_amethod_b 电话 rollback() ,将回滚整个事务。在以下时间之前未提交事务 method_a 调用 commit() 方法。这种“嵌套”行为允许创建功能,这些功能“保证”如果一个事务不可用,将使用该事务,但如果一个事务存在,将自动参与封闭事务。

作为反模式的任意事务嵌套

有了多年的经验,上面的“嵌套”模式并没有被证明是非常流行的,而且在Openstack这样的大型项目中已经观察到,它往往是复杂的。

组织应用程序的最理想方法是只有一个或至少很少的一个点来划分所有数据库事务的“开始”和“提交”。这也是ORM在 我什么时候做一个 Session ,什么时候提交,什么时候关闭? . 要使上一节中的示例适应此实践,如下所示:

# method_a calls method_b
def method_a(connection):
    method_b(connection)

# method_b uses the connection and assumes the transaction
# is external
def method_b(connection):
    connection.execute(text("insert into mytable values ('bat', 'lala')"))
    connection.execute(mytable.insert(), {"col1": "bat", "col2": "lala"})

# open a Connection inside of a transaction and call method_a
with engine.begin() as conn:
    method_a(conn)

也就是说, method_a()method_b() 根本不要处理事务的细节;连接的事务作用域是定义的 外部的 与连接具有SQL对话的函数。

可以看出,上面的代码行数较少,缩进较少,这往往与较低的代码相关 cyclomatic complexity . 上述代码的组织方式如下: method_a()method_b() 总是从事务开始的点调用。该示例的前一个版本具有一个 method_a() 和A method_b() 他们试图对这一事实保持不可知论,这表明他们已经准备好应对至少两倍于他们的潜在代码路径。

从“嵌套”模式迁移

由于SQLAlchemy的内在嵌套模式被认为是遗留的,一个由于遗留或新颖的原因仍然寻求拥有一个能够自动构建事务的上下文的应用程序,应该通过使用自定义Python上下文管理器来维护该功能。下面的“seealso”部分也提供了一个类似的ORM示例。

为了为使用此模式的应用程序提供向后兼容性,可以使用以下上下文管理器或基于装饰器的类似实现::

import contextlib

@contextlib.contextmanager
def transaction(connection):
    if not connection.in_transaction():
        with connection.begin():
            yield connection
    else:
        yield connection

上面的contextmanager将用作:

# method_a starts a transaction and calls method_b
def method_a(connection):
    with transaction(connection):  # open a transaction
        method_b(connection)

# method_b either starts a transaction, or uses the one already
# present
def method_b(connection):
    with transaction(connection):  # open a transaction
        connection.execute(text("insert into mytable values ('bat', 'lala')"))
        connection.execute(mytable.insert(), {"col1": "bat", "col2": "lala"})

# open a Connection and call method_a
with engine.connect() as conn:
    method_a(conn)

也可以采取类似的方法,以便根据需要建立连接;下面的方法具有一个一次性上下文管理器,它访问封闭状态,以测试连接是否已经存在:

import contextlib

def connectivity(engine):
    connection = None

    @contextlib.contextmanager
    def connect():
        nonlocal connection

        if connection is None:
            connection = engine.connect()
            with connection:
                with connection.begin():
                    yield connection
        else:
            yield connection

    return connect

使用上面的方法看起来像:

# method_a passes along connectivity context, at the same time
# it chooses to establish a connection by calling "with"
def method_a(connectivity):
    with connectivity():
        method_b(connectivity)

# method_b also wants to use a connection from the context, so it
# also calls "with:", but also it actually uses the connection.
def method_b(connectivity):
    with connectivity() as connection:
        connection.execute(text("insert into mytable values ('bat', 'lala')"))
        connection.execute(mytable.insert(), {"col1": "bat", "col2": "lala"})

# create a new connection/transaction context object and call
# method_a
method_a(connectivity(engine))

上面的上下文管理器不仅充当一个“事务”上下文,而且还作为一个上下文来管理与特定的 Engine . 使用ORM时 Session ,此连接管理由 Session 本身。ORM连接模式概述见 管理交易 .

参见

从“子事务”模式迁移 -ORM版本

库级(例如仿真)自动提交

1.4 版后已移除: SQLAlchemy Core的“autocommit”功能已被弃用,并且不会出现在SQLAlchemy的2.0版本中。DBAPI级别的AUTOCOMMIT现在已经广泛使用,它提供了优异的性能,并且透明地进行。看到了吗 库级(但不是驱动程序级)“自动提交”从核心和ORM中删除 背景。

注解

本节讨论SQLAlchemy中自动调用 .commit() 方法,但这是针对 本身就是事务性的 . 有关真正的自动提交,请参阅下一节 设置事务隔离级别,包括DBAPI Autocommit .

上一个事务示例说明了如何使用 Transaction 以便多个执行可以参与同一事务。如果不使用 Transaction ?虽然一些DBAPI实现提供了各种特殊的“非事务”模式,但根据PEP-0249,DBAPI的核心行为是 事务始终在进行中 ,仅提供 rollback()commit() 方法但不 begin() . SQLAlchemy假定任何给定DBAPI都是这样。

考虑到这一需求,SQLAlchemy实现了自己的“自动提交”功能,该功能可以在所有后端完全一致地工作。这是通过检测表示数据更改操作的语句(即插入、更新、删除)以及数据定义语言(DDL)语句(如创建表、更改表)来实现的,然后在没有事务进行时自动发出提交。检测是基于 autocommit=True 语句的执行选项。如果该语句是纯文本语句且未设置标志,则使用正则表达式检测特定后端的插入、更新、删除以及各种其他命令:

conn = engine.connect()
conn.execute(text("INSERT INTO users VALUES (1, 'john')"))  # autocommits

“自动提交”功能仅在“否”时有效 Transaction 已另行声明。这意味着该特性通常不与ORM一起使用,因为 Session 默认情况下,对象始终保持 Transaction .

使用Generative可以完全控制“自动提交”行为 Connection.execution_options() 方法提供于 ConnectionEngine ,使用“autocommit”标志打开或关闭所选作用域的自动提交。例如,A text() 表示提交的存储过程的构造可能会使用它,以便select语句将发出commit::

with engine.connect().execution_options(autocommit=True) as conn:
    conn.execute(text("SELECT my_mutating_procedure()"))

设置事务隔离级别,包括DBAPI Autocommit

大多数dbapi支持可配置事务的概念 isolation 水平。这通常是四个级别“未提交读”、“已提交读”、“可重复读”和“可序列化”。它们通常在DBAPI连接开始一个新事务之前应用于它,注意大多数DBAPI将在SQL语句首次发出时隐式地开始该事务。

支持隔离级别的DBAPI通常还支持真正的“自动提交”概念,这意味着DBAPI连接本身将被置于非事务性自动提交模式。这通常意味着自动向数据库发出“BEGIN”的典型DBAPI行为不再发生,但也可能包括其他指令。SQLAlChemy对待“自动提交”的概念与对待任何其他隔离级别一样;因为它是一个不仅失去“读提交”而且失去原子性的隔离级别。

小技巧

值得注意的是,我们将在下面的部分中进一步讨论这一点,地址为 了解DBAPI级别的自动提交隔离级别 与任何其他隔离级别一样,该“自动提交”隔离级别 not 影响的“事务性”行为。 Connection 对象,该对象继续调用DBAPI .commit().rollback() 方法(它们在自动提交下不起作用),对于这些方法, .begin() 方法假定DBAPI将隐式启动事务(这意味着SQLAlChemy的“BEGIN” 不更改自动提交模式 )。

SQLAlchemy方言应该支持这些隔离级别,并尽可能地自动提交。这些级别是通过一系列贯穿核心的“执行选项”参数和方法来设置的,例如 Connection.execution_options() 方法。该参数称为 Connection.execution_options.isolation_level 这些值是字符串,通常是以下名称的子集:

# possible values for Connection.execution_options(isolation_level="<value>")

"AUTOCOMMIT"
"READ COMMITTED"
"READ UNCOMMITTED"
"REPEATABLE READ"
"SERIALIZABLE"

并非每个DBAPI都支持每个值;如果某个后端使用了不受支持的值,则会引发错误。

例如,要在特定连接上强制执行可重复读取,请启动事务:

with engine.connect().execution_options(isolation_level="REPEATABLE READ") as connection:
    with connection.begin():
        connection.execute(<statement>)

注解

对象的返回值 Connection.execution_options() 方法是SQLAlChemy 1.x系列下的所谓“分支”连接,当不使用 create_engine.future 模式,它是原始文件的浅层副本 Connection 对象。尽管如此, isolation_level 执行选项适用于原始 Connection 对象和所有“分支”的整体。

在使用时 create_engine.future 模式(即 2.0 style 用法),这些所谓的“分支”连接的概念被移除,并且 Connection.execution_options() 返回 same Connection 对象,而不创建任何副本。

这个 Connection.execution_options.isolation_level 选项也可以设置为整个发动机范围,这通常是可取的。这是通过在 create_engine.execution_options 参数到 create_engine() ::

from sqlalchemy import create_engine

eng = create_engine(
    "postgresql://scott:tiger@localhost/test",
    execution_options={
        "isolation_level": "REPEATABLE READ"
    }
)

使用上述设置,DBAPI连接将被设置为使用 "REPEATABLE READ" 为开始的每个新事务设置隔离级别。

经常选择在不同隔离级别中运行操作的应用程序可能希望创建一个潜在客户的多个“子引擎” Engine ,每个都将配置为不同的隔离级别。一个这样的用例是一个应用程序,它的操作分为“事务性”和“只读”操作,一个单独的 Engine 它利用了 "AUTOCOMMIT" 可与主机分离:

from sqlalchemy import create_engine

eng = create_engine("postgresql://scott:tiger@localhost/test")

autocommit_engine = eng.execution_options(isolation_level="AUTOCOMMIT")

上面, Engine.execution_options() 方法创建原始的浅拷贝 Engine . 两个 engautocommit_engine 共享相同的方言和连接池。但是,当从获取连接时,“自动提交”模式将在连接上设置 autocommit_engine .

当连接返回到连接池时,将无条件地恢复隔离级别设置(无论是哪一个)。

注解

这个 Connection.execution_options.isolation_level 参数不一定适用于语句级选项,例如 Executable.execution_options() . 这是因为必须在每个事务的基础上在DBAPI连接上设置该选项。

了解DBAPI级别的自动提交隔离级别

在父节中,我们介绍了 Connection.execution_options.isolation_level 参数以及如何使用它来设置数据库隔离级别,包括DBAPI级别的“自动提交”,SQLAlChemy将其视为另一个事务隔离级别。在本节中,我们将尝试阐明此方法的含义。

如果我们想要检查一个 Connection 对象,并使用它的“自动提交”模式,我们将按如下方式进行:

with engine.connect() as connection:
    connection.execution_options(isolation_level="AUTOCOMMIT")
    connection.execute(<statement>)
    connection.execute(<statement>)

上面说明了“DBAPI自动提交”模式的正常用法。不需要使用像这样的方法 Connection.begin()Connection.commit() (请注意,后者适用于 2.0 style 用法)。

What's important to note however is that the above autocommit mode is persistent on that particular Connection until we change it directly using isolation_level again. The isolation level is also reset on the DBAPI connection when we release the connection back to the connection pool. However, calling upon Connection.begin() will not change the isolation level, meaning we stay in autocommit. The example below illustrates this:

with engine.connect() as connection:
    connection = connection.execution_options(isolation_level="AUTOCOMMIT")

    # this begin() does nothing, isolation stays at AUTOCOMMIT
    with connection.begin() as trans:
        connection.execute(<statement>)
        connection.execute(<statement>)

当我们在打开日志记录的情况下运行类似上面的挡路时,日志记录将尝试指示虽然dbapi级别 .commit() 由于自动提交模式::

INFO sqlalchemy.engine.Engine BEGIN (implicit)
...
INFO sqlalchemy.engine.Engine COMMIT using DBAPI connection.commit(), DBAPI should ignore due to autocommit mode

同样,在使用 2.0 style create_engine.future 模式,则 Connection 将使用 autobegin 行为,意味着下面的模式将引发错误::

engine = create_engine(..., future=True)

with engine.connect() as connection:
    connection = connection.execution_options(isolation_level="AUTOCOMMIT")

    # "transaction" is autobegin (but has no effect due to autocommit)
    connection.execute(<statement>)

    # this will raise; "transaction" is already begun
    with connection.begin() as trans:
        connection.execute(<statement>)

这一切都是为了演示自动提交隔离级别设置是 completely independent from the begin/commit behavior of the SQLAlchemy Connection object 。“自动提交”模式不会与 Connection.begin() 以任何方式,并且 Connection 在执行与事务相关的自身状态更改时,不会参考此状态(除了在引擎日志记录中建议这些块未实际提交之外)。此设计的基本原理是维护与 Connection 其中,DBAPI自动提交模式可以独立更改,而不会在其他地方指示任何代码更改。

当连接释放回连接池时,隔离级别设置(包括自动提交模式)将自动重置。因此,最好避免尝试在单个 Connection 对象,因为这会导致过多的冗长。

要说明如何在特定模式下使用“自动提交”,请在单个 Connection 结账, Connection.execution_options.isolation_level 参数必须使用以前的隔离级别重新应用。我们可以将上面的挡路“正确”写为(请注意下面的2.0样式用法):

# if we wanted to flip autocommit on and off on a single connection/
# which... we usually don't.

engine = create_engine(..., future=True)

with engine.connect() as connection:

    connection.execution_options(isolation_level="AUTOCOMMIT")

    # run statement(s) in autocommit mode
    connection.execute(<statement>)

    # "commit" the autobegun "transaction" (2.0/future mode only)
    connection.commit()

    # switch to default isolation level
    connection.execution_options(isolation_level=connection.default_isolation_level)

    # use a begin block
    with connection.begin() as trans:
        connection.execute(<statement>)

要手动恢复我们使用的隔离级别,请执行以下操作 Connection.default_isolation_level 恢复默认隔离级别(假设这就是我们这里需要的)。但是,使用的体系结构可能是一个更好的主意 Connection 它已经在签入时自动处理隔离级别的重置。这个 首选 编写上述代码的方法是使用两个块::

engine = create_engine(..., future=True)

# use an autocommit block
with engine.connect().execution_options(isolation_level="AUTOCOMMIT") as connection:

    # run statement in autocommit mode
    connection.execute(<statement>)

# use a regular block
with engine.begin() as connection:
    connection.execute(<statement>)

总结一下:

  1. “DBAPI级别自动提交”隔离级别完全独立于 Connection 对象的“开始”和“提交”概念

  2. 使用个人 Connection 每个隔离级别的签出。避免尝试在单个连接签出时在“自动提交”之间来回更改;让引擎完成恢复默认隔离级别的工作

使用服务器端游标(即流结果)

有限数量的方言明确支持“服务器端游标”与“缓冲游标”的概念。虽然在SQLAlchemy的引擎和方言实现中,服务器端游标意味着各种不同的功能,但它只指特定结果集在从游标中提取之前是否在内存中完全缓冲,方法如下 cursor.fetchall() . SQLAlchemy不直接支持游标行为,如滚动;要将这些特性用于特定的DBAPI,请直接使用游标,如中所述 使用驱动程序SQL和原始DBAPI连接 .

有些DBAPI,如cx峎u Oracle DBAPI,只在内部使用服务器端游标。所有结果集在结果集的整个范围内基本上都是无缓冲区的,只利用固定大小的较小缓冲区,例如一次100行。

对于那些对缓冲或无缓冲结果有条件支持的方言,使用“无缓冲”或服务器端游标模式通常有一些警告。例如,当使用psycopg2方言时,如果服务器端游标与任何类型的DML或DDL语句一起使用,则会引发错误。当使用带有服务器端游标的MySQL驱动程序时,DBAPI连接处于更脆弱的状态,无法从错误条件中正常恢复,也不允许在游标完全关闭之前继续回滚。

因此,SQLAlchemy的方言将始终默认为不易出错的游标版本,这意味着对于PostgreSQL和MySQL方言来说,它默认为一个缓冲的“客户端”游标,在从游标调用任何fetch方法之前,会将完整的结果集拉入内存。这种操作模式适用于 绝大多数 通常情况下,无缓冲游标通常不起作用,除非应用程序以块的形式获取大量行,在这种情况下,可以在提取更多行之前完成对这些行的处理。

要在特定执行中使用服务器端游标,则 Connection.execution_options.stream_results 选项,可以在 Connection 对象、语句对象或下面提到的ORM级别上下文中。

当在语句中使用此选项时,通常应该使用如下方法 Result.partitions() 要一次处理结果集的小部分,同时还要为每次拉取获取足够的行,以便操作高效:

with engine.connect() as conn:
    result = conn.execution_options(stream_results=True).execute(text("select * from table"))

    for partition in result.partitions(100):
        _process_rows(partition)

如果 Result 直接迭代,使用默认的缓冲方案在内部获取行,该方案首先缓冲一小部分行,然后在每次提取时缓冲越来越大的缓冲区,达到预先配置的1000行限制。使用 max_row_buffer 执行选项:

with engine.connect() as conn:
    conn = conn.execution_options(stream_results=True, max_row_buffer=100)
    result = conn.execute(text("select * from table"))

    for row in result:
        _process_row(row)

方法将缓冲区的大小设置为固定大小。 Result.yield_per() 方法。使用多行调用此方法将导致所有结果提取方法都从给定大小的缓冲区中工作,仅在缓冲区为空时才提取新行::

with engine.connect() as conn:
    result = conn.execution_options(stream_results=True).execute(text("select * from table"))

    for row in result.yield_per(100):
        _process_row(row)

这个 stream_results ORM也提供此选项。使用ORM时,可以使用 Result.yield_per()Result.partitions() 方法应用于设置每次产生以下结果时要缓冲的ORM行数:

with orm.Session(engine) as session:
    result = session.execute(
        select(User).order_by(User_id).execution_options(stream_results=True),
    )
    for partition in result.partitions(100):
        _process_rows(partition)

注解

ORM结果集当前必须使用 Result.yield_per()Result.partitions() 以实现流式ORM结果。如果不使用这两种方法中的任何一种来设置在生成之前要提取的行数,则在生成行之前提取整个结果。这在将来的版本中可能会更改,以便由使用的自动缓冲区大小 Connection ORM结果也会发生这种情况。

在使用 1.x style ORM查询,使用 Query ,Year_PER可通过以下方式获得 Query.yield_per() -这还会设置 stream_results 执行选项::

for row in session.query(User).yield_per(100):
    # process row

无连接执行,隐式执行

2.0 版后已移除: SQLAlchemy中的“无连接”和“隐式”执行功能已被弃用,将在2.0版中删除。看到了吗 “隐式”和“无连接”执行,“绑定元数据”已删除 背景。

回想一下我们提到的第一节,执行时使用或不使用 Connection . "“无连接”执行是指 execute() 对象上的方法,该对象不是 Connection . 这是用 Engine.execute() 方法 Engine ::

result = engine.execute(text("select username from users"))
for row in result:
    print("username:", row['username'])

除了“无连接”执行之外,还可以使用 Executable.execute() 任意方法 Executable 构造,它是支持执行的SQL表达式对象的标记。SQL表达式对象本身引用了 EngineConnection 被称为 bind 以提供所谓的“隐式”执行服务。

给出如下表格:

from sqlalchemy import MetaData, Table, Column, Integer

metadata_obj = MetaData()
users_table = Table('users', metadata_obj,
    Column('id', Integer, primary_key=True),
    Column('name', String(50))
)

显式执行将SQL文本或构造的SQL表达式传递到 Connection.execute() 方法 Connection

engine = create_engine('sqlite:///file.db')
with engine.connect() as connection:
    result = connection.execute(users_table.select())
    for row in result:
        # ....

显式无连接执行将表达式传递给 Engine.execute() 方法 Engine

engine = create_engine('sqlite:///file.db')
result = engine.execute(users_table.select())
for row in result:
    # ....
result.close()

隐式执行也是无连接的,并使用 Executable.execute() 方法。此方法是 Executable 类,它引用的SQL语句足以对数据库调用。该方法使用了以下假设: EngineConnection 已经 跳跃 到表达式对象。我们所说的“绑定”是指 MetaData.bind 已用于关联一系列 Table 对象和所有从这些对象派生的具有特定引擎的SQL构造::

engine = create_engine('sqlite:///file.db')
metadata_obj.bind = engine
result = users_table.select().execute()
for row in result:
    # ....
result.close()

上面,我们将 Engine 用一个 MetaData 使用特殊属性的对象 MetaData.bind . 这个 select() 从中生成的构造 Table 对象有一个方法 Executable.execute() ,它将搜索 Engine 这是“绑定”到 Table .

总的来说,“绑定元数据”的使用有三个一般影响:

注解

现代SQLAlchemy没有强调“绑定元数据”和“隐式执行”的概念。虽然它们提供了一些便利,但是它们不再是任何API所需要的,也不再是必需的。

在多个应用程序中 Engine 对象存在,每个对象都与一组特定的表(即 垂直切分 )可以使用“绑定元数据”技术,以便 Table 可以参考适当的 Engine 自动;尤其是通过 Session 对象作为关联方式 Table 对象具有适当的 Engine ,作为使用直接由 Session .

但是,“隐式执行”技术根本不适合与ORM一起使用,因为它绕过了由 Session .

总的来说,在 绝大多数 在案例中,“绑定元数据”和“隐式执行”是 没有用 . 虽然“绑定的元数据”在ORM配置方面的用处微乎其微,但“隐式执行”是一种非常古老的使用模式,在大多数情况下,它比帮助更容易混淆,而且不鼓励使用它。这两种模式似乎都鼓励在应用程序设计中过度使用权宜之计的“捷径”,这将导致后来的问题。

现代的sqlAlchemy用法,尤其是ORM,一直强调在事务的上下文中工作;“隐式执行”概念使得将语句执行与特定事务关联起来的工作更加困难。这个 Executable.execute() 特定SQL语句上的方法通常意味着执行不是任何特定事务的一部分,这通常不是期望的效果。

在两个“无连接”示例中, Connection 是在幕后创造的;是 CursorResult 返回的 execute() 调用引用 Connection 用于发出SQL语句。当 CursorResult 是关闭的,基础 Connection 为我们关闭,导致DBAPI连接返回到池,事务性资源被删除。

模式名称的翻译

要支持将公共表集分布到多个模式中的多租户应用程序,请 Connection.execution_options.schema_translate_map 执行选项可用于重新调整一组 Table 对象以不同的架构名称呈现,不做任何更改。

给出表格:

user_table = Table(
    'user', metadata_obj,
    Column('id', Integer, primary_key=True),
    Column('name', String(50))
)

这个的“模式” Table 定义如下: Table.schema 属性是 None . 这个 Connection.execution_options.schema_translate_map 可以全部指定 Table 架构为的对象 None 而是将架构呈现为 user_schema_one ::

connection = engine.connect().execution_options(
    schema_translate_map={None: "user_schema_one"})

result = connection.execute(user_table.select())

上述代码将在以下表单的数据库上调用SQL::

SELECT user_schema_one.user.id, user_schema_one.user.name FROM
user_schema_one.user

也就是说,模式名由翻译后的名称替换。映射可以指定任意数量的目标->目标架构::

connection = engine.connect().execution_options(
    schema_translate_map={
        None: "user_schema_one",     # no schema name -> "user_schema_one"
        "special": "special_schema", # schema="special" becomes "special_schema"
        "public": None               # Table objects with schema="public" will render with no schema
    })

这个 Connection.execution_options.schema_translate_map 参数影响从SQL表达式语言生成的所有DDL和SQL构造,如从 TableSequence 物体。它确实 not 影响通过 text() 构造或通过传递给 Connection.execute() .

该功能生效 only 在这些情况下,模式的名称直接从 TableSequence ;它不会影响直接传递字符串架构名称的方法。根据此模式,它在“can create”/“can drop”检查中生效,这些检查由以下方法执行 MetaData.create_all()MetaData.drop_all() 调用,并在使用表反射时生效 Table 对象。然而它确实如此 not 影响当前的操作 Inspector 对象,因为模式名被显式传递给这些方法。

小技巧

要将架构转换功能与ORM一起使用,请执行以下操作 Session 的级别设置此选项。 Engine ,然后将引擎传递给 Session 。这个 Session 使用新的 Connection 对于每笔交易::

schema_engine = engine.execution_options(schema_translate_map = { ... } )

session = Session(schema_engine)

...

1.1 新版功能.

SQL编译缓存

1.4 新版功能: 现在,在Python中,alcorm语句和SQL核心查询的转换大大降低了计算开销。请参阅 透明的SQL编译缓存添加到Core、ORM中的所有DQL、DML语句中 .

SQLAlchemy为SQL编译器及其ORM变体提供了一个全面的缓存系统。此缓存系统在 Engine 并规定给定Core或ORM SQL语句的SQL编译过程,以及为该语句装配结果获取机制的相关计算,对于该语句对象和所有其他具有相同结构的对象只会发生一次,在特定结构保留在引擎的“编译缓存”中的持续时间内。通过“具有相同结构的语句对象”,这通常对应于在函数内构造并在每次函数运行时生成的SQL语句:

def run_my_statement(connection, parameter):
    stmt = select(table)
    stmt = stmt.where(table.c.col == parameter)
    stmt = stmt.order_by(table.c.id)
    return connection.execute(stmt)

上面的语句将生成类似于 SELECT id, col FROM table WHERE col = :col ORDER BY id ,注意到 parameter 因为Python是一个纯字符串,或者它不包含字符串形式的字符串,所以它不包含字符串形式的参数。上述内容的后续调用 run_my_statement() 函数将在 connection.execute() 要求提高性能。

注解

请注意,SQL编译缓存正在缓存 只传递给数据库的SQL字符串不是数据 由查询返回。它决不是一个数据缓存,不会影响为特定SQL语句返回的结果,也不意味着任何与提取结果行相关的内存使用。

虽然SQLAlchemy从1.x系列的早期就已经有了一个基本的语句缓存,并且还为ORM提供了“bakequery”扩展,但是这两个系统都需要大量的特殊API才能使缓存有效。新的缓存从1.4版开始是完全自动的,不需要改变编程风格就可以生效。

缓存是自动使用的,不需要任何配置更改,也不需要特殊步骤来启用它。以下各节详细介绍缓存的配置和高级使用模式。

配置

缓存本身是一个类似字典的对象,称为 LRUCache 当一个特定的“最近使用的字典”和“当一个特定的关键字的内部使用量达到最小值”时,删除“最近使用的一个子类”的“alchemy”。此缓存的大小默认为500,可以使用 create_engine.query_cache_size 参数::

engine = create_engine("postgresql://scott:tiger@localhost/test", query_cache_size=1200)

在将缓存缩减为目标大小之前,缓存的大小可以增长为给定大小的150%。因此,大小为1200以上的缓存可以增长到1800个元素,此时它将被修剪为1200个。

缓存的大小基于每个引擎呈现的每个唯一SQL语句的单个条目。从内核和ORM生成的SQL语句被同等对待。DDL语句通常不会被缓存。为了确定缓存正在做什么,引擎日志记录将包括有关缓存行为的详细信息,将在下一节中介绍。

使用日志记录估计缓存性能

上面的缓存大小1200实际上相当大。对于小型应用程序,100的大小可能就足够了。要估计缓存的最佳大小,假设目标主机上有足够的内存,则缓存的大小应基于可能为正在使用的目标引擎呈现的唯一SQL字符串的数量。最方便的方法是使用SQL回显,这是通过使用 create_engine.echo 标志,或使用Python日志记录;请参阅小节 配置日志记录 有关日志记录配置的背景信息。

作为示例,我们将检查以下程序生成的日志:

from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session

Base = declarative_base()


class A(Base):
    __tablename__ = "a"

    id = Column(Integer, primary_key=True)
    data = Column(String)
    bs = relationship("B")


class B(Base):
    __tablename__ = "b"
    id = Column(Integer, primary_key=True)
    a_id = Column(ForeignKey("a.id"))
    data = Column(String)


e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

s = Session(e)

s.add_all(
    [A(bs=[B(), B(), B()]), A(bs=[B(), B(), B()]), A(bs=[B(), B(), B()])]
)
s.commit()

for a_rec in s.query(A):
    print(a_rec.bs)

运行时,记录的每个SQL语句将在传递的参数左侧包含一个括号内的缓存统计标记。我们可以看到的四类信息概括如下:

  • [raw sql] -驱动程序或最终用户使用 Connection.exec_driver_sql() -缓存不适用

  • [no key] -statement对象是未缓存的DDL语句,或者statement对象包含不可缓存的元素,如用户定义的构造或任意大的值子句。

  • [generated in Xs] -声明是 缓存未命中 必须被编译,然后存储在缓存中。生成编译的构造花了X秒。数字X将以小数秒为单位。

  • [cached since Xs ago] -声明是 缓存命中 不需要重新编译。语句从X秒前就存储在缓存中。数字X将与应用程序运行的时间和语句被缓存的时间成正比,因此,例如24小时内为86400。

下面将更详细地描述每个徽章。

我们在上面的程序中看到的第一个语句将是SQLite方言检查“a”和“b”表的存在:

INFO sqlalchemy.engine.Engine PRAGMA temp.table_info("a")
INFO sqlalchemy.engine.Engine [raw sql] ()
INFO sqlalchemy.engine.Engine PRAGMA main.table_info("b")
INFO sqlalchemy.engine.Engine [raw sql] ()

对于以上两个SQLite PRAGMA语句,徽章显示 [raw sql] ,这表示驱动程序正在使用 Connection.exec_driver_sql() . 缓存不适用于这类语句,因为它们已经以字符串形式存在,而且由于SQLAlchemy没有提前解析SQL字符串,因此不知道将返回什么样的结果行。

我们看到的下一个语句是CREATE TABLE语句:

INFO sqlalchemy.engine.Engine
CREATE TABLE a (
  id INTEGER NOT NULL,
  data VARCHAR,
  PRIMARY KEY (id)
)

INFO sqlalchemy.engine.Engine [no key 0.00007s] ()
INFO sqlalchemy.engine.Engine
CREATE TABLE b (
  id INTEGER NOT NULL,
  a_id INTEGER,
  data VARCHAR,
  PRIMARY KEY (id),
  FOREIGN KEY(a_id) REFERENCES a (id)
)

INFO sqlalchemy.engine.Engine [no key 0.00006s] ()

对于这些声明,徽章上写着 [no key 0.00006s] . 这表明这两个特定的语句,缓存没有发生,因为DDL面向 CreateTable 构造未生成缓存键。DDL构造通常不参与缓存,因为它们通常不会被第二次重复,而且DDL也是数据库配置步骤,其中性能不是那么关键。

这个 [no key] 由于另一个原因,badge很重要,因为它可以为除某些当前不可缓存的特定子构造之外的可缓存SQL语句生成。这方面的示例包括不定义缓存参数的自定义用户定义SQL元素,以及一些生成任意长且不可复制的SQL字符串的构造,主要示例是 Values 在使用“多值插入”时 Insert.values() 方法。

到目前为止,我们的缓存仍然是空的。接下来的语句将被缓存,但是,段看起来像:

INFO sqlalchemy.engine.Engine INSERT INTO a (data) VALUES (?)
INFO sqlalchemy.engine.Engine [generated in 0.00011s] (None,)
INFO sqlalchemy.engine.Engine INSERT INTO a (data) VALUES (?)
INFO sqlalchemy.engine.Engine [cached since 0.0003533s ago] (None,)
INFO sqlalchemy.engine.Engine INSERT INTO a (data) VALUES (?)
INFO sqlalchemy.engine.Engine [cached since 0.0005326s ago] (None,)
INFO sqlalchemy.engine.Engine INSERT INTO b (a_id, data) VALUES (?, ?)
INFO sqlalchemy.engine.Engine [generated in 0.00010s] (1, None)
INFO sqlalchemy.engine.Engine INSERT INTO b (a_id, data) VALUES (?, ?)
INFO sqlalchemy.engine.Engine [cached since 0.0003232s ago] (1, None)
INFO sqlalchemy.engine.Engine INSERT INTO b (a_id, data) VALUES (?, ?)
INFO sqlalchemy.engine.Engine [cached since 0.0004887s ago] (1, None)

在上面,我们看到了两个基本上唯一的SQL字符串; "INSERT INTO a (data) VALUES (?)""INSERT INTO b (a_id, data) VALUES (?, ?)" . 因为SQLAlchemy对所有的文本值都使用绑定参数,即使这些语句对于不同的对象重复了很多次,因为参数是分开的,所以实际的SQL字符串保持不变。

注解

以上两个语句是由ORM工作单元流程生成的,实际上,它们将缓存在每个映射器本地的单独缓存中。然而,机械和术语是相同的。部门 禁用或使用备用字典缓存某些(或全部)语句 下面将描述面向用户的代码如何在每个语句的基础上使用备用缓存容器。

这两个语句第一次出现时,我们看到的缓存徽章是 [generated in 0.00011s] . 这表明该语句是 不在缓存中,在.00011s中编译为字符串,然后被缓存 . 当我们看到 [generated] 警徽,我们知道这意味着 缓存未命中 . 对于第一次出现的特定语句,这是预期的。但是,如果 [generated] 对于一个长时间运行的应用程序,通常会反复使用同一系列SQL语句,这可能表示 create_engine.query_cache_size 参数太小。当一个被缓存的语句由于LRU缓存修剪较少使用的项而从缓存中逐出时,它将显示 [generated] 下次使用时的徽章。

我们随后看到的这两个语句的后续出现的缓存标记如下所示 [cached since 0.0003533s ago] . 这表示语句 在缓存中找到,并且最初被放入缓存中。0003533秒前 . 需要注意的是 [generated][cached since] 徽章指的是秒数,它们的意思是不同的;在 [generated] ,该数字是编译语句所用时间的粗略计时,并且将是极少量的时间。在下列情况下 [cached since] ,这是语句在缓存中出现的总时间。这个应用程序可能已经运行了6个小时了 [cached since 21600 seconds ago] ,这是件好事。“cached since”的数字很高,这表明这些语句在很长一段时间内没有受到缓存未命中的影响。即使应用程序已经运行了很长一段时间,也经常有少量的“cached since”语句可能表明这些语句太频繁地受到缓存未命中的影响,并且 create_engine.query_cache_size 可能需要增加。

然后,我们的示例程序执行一些选择,在这里我们可以看到相同的“生成”然后“缓存”的模式,对于“a”表的选择以及“b”表的后续延迟加载:

INFO sqlalchemy.engine.Engine SELECT a.id AS a_id, a.data AS a_data
FROM a
INFO sqlalchemy.engine.Engine [generated in 0.00009s] ()
INFO sqlalchemy.engine.Engine SELECT b.id AS b_id, b.a_id AS b_a_id, b.data AS b_data
FROM b
WHERE ? = b.a_id
INFO sqlalchemy.engine.Engine [generated in 0.00010s] (1,)
INFO sqlalchemy.engine.Engine SELECT b.id AS b_id, b.a_id AS b_a_id, b.data AS b_data
FROM b
WHERE ? = b.a_id
INFO sqlalchemy.engine.Engine [cached since 0.0005922s ago] (2,)
INFO sqlalchemy.engine.Engine SELECT b.id AS b_id, b.a_id AS b_a_id, b.data AS b_data
FROM b
WHERE ? = b.a_id

在上面的程序中,完整的运行显示总共有四个不同的SQL字符串被缓存。表示缓存大小为 four 就足够了。这显然是一个非常小的大小,默认大小500可以保留为默认大小。

缓存使用多少内存?

上一节详细介绍了一些检查 create_engine.query_cache_size 需要更大一点。我们如何知道缓存是否不是太大?我们可能要设定的原因 create_engine.query_cache_size 不高于某个数字可能是因为我们有一个应用程序可能会使用大量不同的语句,例如一个从搜索UX动态构建查询的应用程序,我们不希望主机耗尽内存,例如,在过去的24小时内运行了十万个不同的查询,它们都被缓存了。

很难测量Python数据结构占用了多少内存,但是使用一个进程通过 top 当一系列连续的250条新语句被添加到缓存中时,表明一条中等大小的Core语句占用大约12K,而一条较小的ORM语句大约需要20K,其中包括对于ORM来说更大的结果获取结构。

禁用或使用备用字典缓存某些(或全部)语句

使用的内部缓存称为 LRUCache ,但这基本上只是一本字典。通过使用 Connection.execution_options.compiled_cache 选项作为执行选项。执行选项可以设置在语句上 EngineConnection ,以及在使用ORM时 Session.execute() 方法进行SQLAlchemy-2.0样式调用。例如,要运行一系列SQL语句并将它们缓存在特定的字典中:

my_cache = {}
with engine.connect().execution_options(compiled_cache=my_cache) as conn:
    conn.execute(table.select())

SQLAlchemy ORM使用上述技术来保存工作单元“刷新”进程中的每映射器缓存,这些缓存与在上配置的默认缓存分开 Engine ,以及一些关系加载器查询。

也可以使用此参数通过发送值禁用缓存 None ::

# disable caching for this connection
with engine.connect().execution_options(compiled_cache=None) as conn:
    conn.execute(table.select())

第三方方言的缓存

缓存特性要求方言的编译器在给定特定缓存键的情况下生成一般可重用的SQL结构。这意味着语句中的任何文字值,如SELECT的限制/偏移值,都不能在方言的编译方案中硬编码,因为编译后的字符串将不可重用。SQLAlChemy支持使用 BindParameter.render_literal_execute() 方法,该方法可应用于现有的 Select._limit_clauseSelect._offset_clause 属性由自定义编译器编写。

由于有许多第三方方言,其中许多方言可能会从SQL语句生成文字值,而没有利用较新的“文字执行”功能,因此SQLAlChemy从1.4.5版开始为方言添加了一个标记,称为 Dialect.supports_statement_cache 。此标志被测试为直接出现在方言类中,而不是任何超类中,因此即使是将现有的可缓存SQLAlChemy方言子类化为子类的第三方方言,如 sqlalchemy.dialects.postgresql.PGDialect 一旦根据需要更改了方言并测试了使用不同参数编译的SQL语句的可重用性,则仍必须指定此标志。

对于不支持此标志的所有第三方方言,此类方言的日志记录将指示 dialect does not support caching 。方言作者可以按如下方式应用该标志:

from sqlalchemy.engine.default import DefaultDialect

class MyDialect(DefaultDialect):
    supports_statement_cache = True

该标志还需要应用于方言的所有子类::

class MyDBAPIForMyDialect(MyDialect):
    supports_statement_cache = True

1.4.5 新版功能.

使用Lambdas为语句生成添加显著的速度增益

Deep Alchemy

这种技术通常是不必要的,除非在性能非常密集的场景中,而且是为有经验的Python程序员设计的。虽然相当简单,但它涉及到元编程概念,这些概念并不适合初级Python开发人员。lambda方法可以稍后应用到现有代码中,只需花费很少的精力。

通常表示为lambda的Python函数可用于生成可基于lambda函数本身的Python代码位置以及lambda内的闭包变量来高速缓存的SQL表达式。其基本原理是不仅允许缓存SQL表达式构造的SQL字符串编译形式(这是SQLAlChemy在不使用lambda系统时的正常行为),而且还允许缓存SQL表达式构造本身的Python内组合,这也有一定的Python开销。

lambda SQL表达式功能可以作为性能增强功能使用,也可以选择在 with_loader_criteria() orm选项,以便提供通用的SQL片段。

摘要

Lambda语句是使用 lambda_stmt() 函数,该函数返回 StatementLambdaElement ,它本身就是一个可执行语句构造。使用Python加法运算符将其他修饰符和条件添加到对象 + ,或者也可以选择 StatementLambdaElement.add_criteria() 方法,该方法允许更多选项。

假设 lambda_stmt() 构造在封闭的函数或方法中被调用,该函数或方法预计会在应用程序中多次使用,以便第一个函数或方法之外的后续执行可以利用被缓存的已编译SQL。当lambda在Python中的封闭函数内构造时,它还必须具有闭包变量,这些变量对整个方法很重要:

from sqlalchemy import lambda_stmt

def run_my_statement(connection, parameter):
    stmt = lambda_stmt(lambda: select(table))
    stmt += lambda s: s.where(table.c.col == parameter)
    stmt += lambda s: s.order_by(table.c.id)

    return connection.execute(stmt)

with engine.connect() as conn:
    result = run_my_statement(some_connection, "some parameter")

上图是三位 lambda 用于定义SELECT语句结构的可调用函数只调用一次,生成的SQL字符串缓存在引擎的编译缓存中。从那时起, run_my_statement() 函数可以被调用任意次,并且 lambda 其中的可调用函数将不会被调用,仅用作检索已编译的SQL的缓存键。

注解

需要注意的是,当不使用lambda系统时,已经有了SQL缓存。lambda系统只为通过缓存构建的SQL结构本身并使用更简单的缓存键调用的每个SQL语句添加额外的工作量减少层。

Lambdas快速指南

最重要的是,lambda SQL系统中的重点是确保为lambda生成的缓存键与它将生成的SQL字符串之间永远不会不匹配。这个 LamdaElement 相关对象将运行并分析给定的lambda,以便计算在每次运行时应该如何缓存它,试图检测任何潜在的问题。基本准则包括:

  • 支持任何类型的语句 -虽然预计 select() 构造是 lambda_stmt() 、DML语句,如 insert()update() 同样可用::

    def upd(id_, newname):
        stmt = lambda_stmt(lambda: users.update())
        stmt += lambda s: s.values(name=newname)
        stmt += lambda s: s.where(users.c.id==id_)
        return stmt
    
    with engine.begin() as conn:
        conn.execute(upd(7, "foo"))
  • 还直接支持ORM用例 -The lambda_stmt() 可以完全支持ORM功能,并可直接与一起使用 Session.execute() ::

    def select_user(session, name):
        stmt = lambda_stmt(lambda: select(User))
        stmt += lambda s: s.where(User.name == name)
    
        row = session.execute(stmt).first()
        return row
  • 自动适应绑定参数 详细说明:与SQLAlChemy以前的“烘焙查询”系统不同,lambda SQL系统支持Python文字值,这些值自动成为SQL绑定参数。这意味着即使给定的lambda只运行一次,成为绑定参数的值也是从 闭合 每次奔跑的羔羊:

    >>> def my_stmt(x, y):
    ...     stmt = lambda_stmt(lambda: select(func.max(x, y)))
    ...     return stmt
    ...
    >>> engine = create_engine("sqlite://", echo=True)
    >>> with engine.connect() as conn:
    ...     print(conn.scalar(my_stmt(5, 10)))
    ...     print(conn.scalar(my_stmt(12, 8)))
    ...
    
    SELECT max(?, ?) AS max_1 [generated in 0.00057s] (5, 10)
    10
    SELECT max(?, ?) AS max_1 [cached since 0.002059s ago] (12, 8)
    12

    上图, StatementLambdaElement 提取的值为 xy闭合 每次生成的lambda的 my_stmt() 被调用;它们作为参数值被替换到缓存的SQL结构中。

  • 理想情况下,lambda在所有情况下都应该生成相同的SQL结构 -避免在lambdas内部使用条件或自定义可调用,这可能会使其根据输入产生不同的SQL;如果一个函数可能有条件地使用两个不同的SQL片段,请使用两个单独的lambdas::

    # **Don't** do this:
    
    def my_stmt(parameter, thing=False):
        stmt = lambda_stmt(lambda: select(table))
        stmt += (
            lambda s: s.where(table.c.x > parameter) if thing
            else s.where(table.c.y == parameter)
        return stmt
    
    # **Do** do this:
    
    def my_stmt(parameter, thing=False):
        stmt = lambda_stmt(lambda: select(table))
        if thing:
            stmt += s.where(table.c.x > parameter)
        else:
            stmt += s.where(table.c.y == parameter)
        return stmt

    如果lambda不能生成一致的SQL结构,并且有些故障目前无法检测到,则可能会发生各种故障。

  • 不要在lambda中使用函数来生成绑定值 -绑定值跟踪方法要求SQL语句中要使用的实际值本地出现在lambda的闭包中。如果值是从其他函数生成的,并且 LambdaElement 如果尝试执行此操作,通常应引发错误::

    >>> def my_stmt(x, y):
    ...     def get_x():
    ...         return x
    ...     def get_y():
    ...         return y
    ...
    ...     stmt = lambda_stmt(lambda: select(func.max(get_x(), get_y())))
    ...     return stmt
    ...
    >>> with engine.connect() as conn:
    ...     print(conn.scalar(my_stmt(5, 10)))
    ...
    Traceback (most recent call last):
      # ...
    sqlalchemy.exc.InvalidRequestError: Can't invoke Python callable get_x()
    inside of lambda expression argument at
    <code object <lambda> at 0x7fed15f350e0, file "<stdin>", line 6>;
    lambda SQL constructs should not invoke functions from closure variables
    to produce literal values since the lambda SQL system normally extracts
    bound values without actually invoking the lambda or any functions within it.

    在上面,使用 get_x()get_y() ,如果它们是必要的,应该发生 外面 并分配给局部闭包变量::

    >>> def my_stmt(x, y):
    ...     def get_x():
    ...         return x
    ...     def get_y():
    ...         return y
    ...
    ...     x_param, y_param = get_x(), get_y()
    ...     stmt = lambda_stmt(lambda: select(func.max(x_param, y_param)))
    ...     return stmt
  • Avoid referring to non-SQL constructs inside of lambdas as they are not cacheable by default -此问题指的是 LambdaElement 从语句内的其他闭包变量创建缓存键。为了提供准确缓存键的最佳保证,位于lambda闭包中的所有对象都被认为是重要的,并且默认情况下将假设没有对象适合于缓存键。因此,下面的示例还将引发相当详细的错误消息:

    >>> class Foo:
    ...     def __init__(self, x, y):
    ...         self.x = x
    ...         self.y = y
    ...
    >>> def my_stmt(foo):
    ...     stmt = lambda_stmt(lambda: select(func.max(foo.x, foo.y)))
    ...     return stmt
    ...
    >>> with engine.connect() as conn:
    ...    print(conn.scalar(my_stmt(Foo(5, 10))))
    ...
    Traceback (most recent call last):
      # ...
    sqlalchemy.exc.InvalidRequestError: Closure variable named 'foo' inside of
    lambda callable <code object <lambda> at 0x7fed15f35450, file
    "<stdin>", line 2> does not refer to a cacheable SQL element, and also
    does not appear to be serving as a SQL literal bound value based on the
    default SQL expression returned by the function.  This variable needs to
    remain outside the scope of a SQL-generating lambda so that a proper cache
    key may be generated from the lambda's state.  Evaluate this variable
    outside of the lambda, set track_on=[<elements>] to explicitly select
    closure elements to track, or set track_closure_variables=False to exclude
    closure variables from being part of the cache key.

    上面的错误表明 LambdaElement 不会假设 Foo 传入的对象在所有情况下的行为都将继续相同。它也不会假设它可以使用 Foo 默认情况下作为缓存键的一部分;如果它使用 Foo 对象作为缓存键的一部分,如果有许多不同的 Foo 对象这会用重复的信息填满缓存,并且还会保存对所有这些对象的长期引用。

    解决上述情况的最佳方法是不参考 foo 在lambda内部,并引用它 外面 取而代之的是::

    >>> def my_stmt(foo):
    ...     x_param, y_param = foo.x, foo.y
    ...     stmt = lambda_stmt(lambda: select(func.max(x_param, y_param)))
    ...     return stmt

    在某些情况下,如果保证lambda的SQL结构不会根据输入更改,则传递 track_closure_variables=False 这将禁用除用于绑定参数的闭包变量之外的任何闭包变量跟踪:

    >>> def my_stmt(foo):
    ...     stmt = lambda_stmt(
    ...         lambda: select(func.max(foo.x, foo.y)),
    ...         track_closure_variables=False
    ...     )
    ...     return stmt

    还可以选择将对象添加到元素以显式形成缓存键的一部分,方法是使用 track_on 参数;使用此参数允许将特定值用作缓存键,并且还将防止考虑其他闭包变量。这对于正在构造的SQL的一部分源自可能具有许多不同值的某种上下文对象的情况很有用。在下面的示例中,SELECT语句的第一段将禁用跟踪 foo 变量,而第二个段将显式跟踪 self 作为缓存键的一部分::

    >>> def my_stmt(self, foo):
    ...     stmt = lambda_stmt(
    ...         lambda: select(*self.column_expressions),
    ...         track_closure_variables=False
    ...     )
    ...     stmt = stmt.add_criteria(
    ...         lambda: self.where_criteria,
    ...         track_on=[self]
    ...     )
    ...     return stmt

    使用 track_on 意味着给定的对象将长期存储在lambda的内部缓存中,并且只要缓存不清除这些对象(默认情况下使用包含1000个条目的LRU方案),这些对象将具有强引用。

缓存键生成

为了理解lambda SQL构造中出现的一些选项和行为,了解缓存系统是很有帮助的。

SQLAlChemy的缓存系统通常通过生成表示构造中所有状态的结构,从给定的SQL表达式构造生成缓存键:

>>> from sqlalchemy import select, column
>>> stmt = select(column('q'))
>>> cache_key = stmt._generate_cache_key()
>>> print(cache_key)  # somewhat paraphrased
CacheKey(key=(
  '0',
  <class 'sqlalchemy.sql.selectable.Select'>,
  '_raw_columns',
  (
    (
      '1',
      <class 'sqlalchemy.sql.elements.ColumnClause'>,
      'name',
      'q',
      'type',
      (
        <class 'sqlalchemy.sql.sqltypes.NullType'>,
      ),
    ),
  ),
  # a few more elements are here, and many more for a more
  # complicated SELECT statement
),)

上面的键存储在缓存中,缓存本质上是一个字典,值是一个结构,其中存储SQL语句的字符串形式,在本例中是短语“select q”。我们可以观察到,即使对于非常短的查询,缓存键也相当冗长,因为它必须表示与正在呈现和可能执行的内容可能不同的所有内容。

相比之下,lambda构造系统创建了不同类型的缓存键::

>>> from sqlalchemy import lambda_stmt
>>> stmt = lambda_stmt(lambda: select(column("q")))
>>> cache_key = stmt._generate_cache_key()
>>> print(cache_key)
CacheKey(key=(
  <code object <lambda> at 0x7fed1617c710, file "<stdin>", line 1>,
  <class 'sqlalchemy.sql.lambdas.StatementLambdaElement'>,
),)

上面,我们看到一个缓存键比非lambda语句的缓存键要短得多,而且 select(column("q")) 构造本身甚至不是必需的;Python lambda本身包含一个名为 __code__ 它指的是在应用程序的运行时内不可变且永久的Python代码对象。

当lambda还包括闭包变量时,在这些变量引用SQL结构(如列对象)的正常情况下,它们将成为缓存键的一部分,或者如果它们引用将作为绑定参数的文字值,则它们被放置在缓存键的单独元素中:

>>> def my_stmt(parameter):
...     col = column("q")
...     stmt = lambda_stmt(lambda: select(col))
...     stmt += lambda s: s.where(col == parameter)
...     return stmt

以上内容 StatementLambdaElement 包括两个lambda,这两个lambda都引用 col 关闭变量,因此缓存键将同时表示这两个段以及 column() 对象::

>>> stmt = my_stmt(5)
>>> key = stmt._generate_cache_key()
>>> print(key)
CacheKey(key=(
  <code object <lambda> at 0x7f07323c50e0, file "<stdin>", line 3>,
  (
    '0',
    <class 'sqlalchemy.sql.elements.ColumnClause'>,
    'name',
    'q',
    'type',
    (
      <class 'sqlalchemy.sql.sqltypes.NullType'>,
    ),
  ),
  <code object <lambda> at 0x7f07323c5190, file "<stdin>", line 4>,
  <class 'sqlalchemy.sql.lambdas.LinkedLambdaElement'>,
  (
    '0',
    <class 'sqlalchemy.sql.elements.ColumnClause'>,
    'name',
    'q',
    'type',
    (
      <class 'sqlalchemy.sql.sqltypes.NullType'>,
    ),
  ),
  (
    '0',
    <class 'sqlalchemy.sql.elements.ColumnClause'>,
    'name',
    'q',
    'type',
    (
      <class 'sqlalchemy.sql.sqltypes.NullType'>,
    ),
  ),
),)

缓存键的第二部分检索了调用语句时将使用的绑定参数:

>>> key.bindparams
[BindParameter('%(139668884281280 parameter)s', 5, type_=Integer())]

有关“lambda”缓存与性能比较的一系列示例,请参见 性能 性能示例。

引擎处理

这个 Engine 引用连接池,这意味着在正常情况下,存在打开的数据库连接,而 Engine 对象仍驻留在内存中。当一个 Engine 是垃圾收集的,其连接池不再由该引用 Engine ,并且假设它的所有连接都未签出,那么池及其连接也将被垃圾收集,这也会关闭实际的数据库连接。但除此之外, Engine 将保留打开的数据库连接,假定它使用 QueuePool .

这个 Engine 通常是在应用程序的整个生命周期中预先建立和维护的永久性固定装置。它是 not 目的是在每个连接的基础上创建和处理;相反,它是一个注册中心,既维护连接池,也维护数据库和DBAPI使用中的配置信息,以及每个数据库资源的某种程度的内部缓存。

但是,在许多情况下,需要 Engine 完全封闭。对于这些情况,依赖于Python垃圾收集通常不是一个好主意,而是 Engine 可以使用 Engine.dispose() 方法。这将处理引擎的底层连接池,并将其替换为空的新连接池。前提是 Engine 在此时被丢弃,不再使用 checked-in 它所指的连接也将完全关闭。

调用的有效用例 Engine.dispose() 包括:

  • 当一个程序想要释放连接池保留的任何剩余的签入连接,并且期望在将来的任何操作中不再连接到该数据库时。

  • 当程序使用多处理或 fork() 和一个 Engine 对象被复制到子进程, Engine.dispose() 应该调用,以便引擎在该分叉的本地创建全新的数据库连接。数据库连接通常是这样的 not 跨越流程边界。

  • 在测试套件或多租户场景中,许多临时的、短期的 Engine 可以创建和释放对象。

连接 签出not 当引擎被释放或垃圾收集时丢弃,因为应用程序在其他地方仍然强烈引用这些连接。然而,之后 Engine.dispose() 被调用,这些连接不再与 Engine ;当它们被关闭时,它们将被返回到它们现在的孤立连接池,一旦引用它的所有连接也不再在任何地方被引用,最终将被垃圾收集。由于这一过程不容易控制,强烈建议 Engine.dispose() 只有在签入所有已签出的连接或从其池中取消关联后才调用。

对于受 Engine 对象使用连接池是为了完全禁用池。这通常只会对新连接的使用产生适度的性能影响,这意味着当一个连接被签入时,它将完全关闭,而不会保留在内存中。见 切换池实现 有关如何禁用池的指南。

使用驱动程序SQL和原始DBAPI连接

使用简介 Connection.execute() 利用 text() 构造以说明如何调用文本SQL语句。在使用SQLAlchemy时,文本SQL实际上更像是一种例外而不是规范,因为核心表达式语言和ORM都抽象了SQL的文本表示。但是 text() 构造本身还提供了一些文本SQL的抽象,因为它规范了绑定参数的传递方式,并且支持参数和结果集行的数据类型行为。

直接向驱动程序调用SQL字符串

对于想要调用直接传递给底层驱动程序(称为 DBAPI )没有任何干涉 text() 构建 Connection.exec_driver_sql() 可使用的方法:

with engine.connect() as conn:
    conn.exec_driver_sql("SET param='bar'")

1.4 新版功能: 增加了 Connection.exec_driver_sql() 方法。

直接使用DBAPI游标

有些情况下,SQLAlchemy在访问某些 DBAPI 函数,例如调用存储过程以及处理多个结果集。在这些情况下,直接处理原始DBAPI连接也同样有利。

访问原始DBAPI连接的最常见方法是从已经存在的 Connection 直接对象。使用 Connection.connection 属性:

connection = engine.connect()
dbapi_conn = connection.connection

这里的DBAPI连接实际上是一个“代理”的原始连接池,但是这是一个在大多数情况下可以忽略的实现细节。因为DBAPI连接仍然包含在拥有的范围内 Connection 对象,最好利用 Connection 对象,用于大多数功能,如事务控制以及调用 Connection.close() 方法;如果直接在DBAPI连接上执行这些操作,则 Connection 将不知道这些状态变化。

克服由拥有者维护的DBAPI连接所施加的限制。 Connection ,DBAPI连接也可用,无需获取 Connection 首先,使用 Engine.raw_connection() 方法 Engine ::

dbapi_conn = engine.raw_connection()

这个DBAPI连接和以前一样也是一个“代理”形式。这种代理的目的现在很明显,当我们调用 .close() 此连接的方法,DBAPI连接通常不是实际关闭的,而是 released 返回引擎的连接池:

dbapi_conn.close()

尽管SQLAlchemy将来可能会为更多的DBAPI用例添加内置模式,但由于这些情况往往很少需要,并且它们在很大程度上取决于使用中的DBAPI类型,所以在任何情况下,直接DBAPI调用模式总是存在于需要的情况下。

参见

使用引擎时,如何获得原始DBAPI连接? -包括有关如何访问DBAPI连接以及使用异步驱动程序时的“驱动程序”连接的其他详细信息。

以下是DBAPI连接的一些方法。

调用存储过程和用户定义函数

SQLAlChemy支持以多种方式调用存储过程和用户定义函数。请注意,所有DBAPI都有不同的实践,因此您必须查阅底层DBAPI文档以了解与您的特定用法相关的细节。以下示例是假设的,可能不适用于您的底层DBAPI。

对于具有特殊语法或参数关注点的存储过程或函数,DBAPI级别 callproc 可能会与您的DBAPI一起使用。此模式的一个示例是:

connection = engine.raw_connection()
try:
    cursor_obj = connection.cursor()
    cursor_obj.callproc("my_procedure", ['x', 'y', 'z'])
    results = list(cursor_obj.fetchall())
    cursor_obj.close()
    connection.commit()
finally:
    connection.close()

注解

并非所有DBAPI都使用 callproc 总体使用细节会有所不同。上面的示例仅说明了使用特定DBAPI函数可能会是什么样子。

您的DBAPI可能没有 callproc 要求 or 可能需要使用另一种模式调用存储过程或用户定义函数,例如正常的SQLAlChemy连接使用。该使用模式的一个示例是, 在撰写本文档时 ,使用mental copg2 DBAPI在PostgreSQL数据库中执行存储过程,应使用正常连接用法调用该存储过程::

connection.execute("CALL my_procedure();")

上面的例子是假设的。在这些情况下,不能保证底层数据库支持“CALL”或“SELECT”,并且关键字可能会根据函数是存储过程还是用户定义函数而有所不同。在这些情况下,您应该参考底层DBAPI和数据库文档,以确定要使用的正确语法和模式。

多个结果集

多结果集支持可从原始DBAPI游标使用 nextset 方法:

connection = engine.raw_connection()
try:
    cursor_obj = connection.cursor()
    cursor_obj.execute("select * from table1; select * from table2")
    results_one = cursor_obj.fetchall()
    cursor_obj.nextset()
    results_two = cursor_obj.fetchall()
    cursor_obj.close()
finally:
    connection.close()

注册新方言

这个 create_engine() 函数调用使用SETUPTOOLS入口点定位给定方言。可以在setup.py脚本中为第三方方言建立这些入口点。例如,要创建新方言“foodialect://”,步骤如下:

  1. 创建名为 foodialect .

  2. 包应该有一个包含方言类的模块,该模块通常是 sqlalchemy.engine.default.DefaultDialect . 在这个例子中,假设它被称为 FooDialect 其模块通过 foodialect.dialect .

  3. 可以在setup.py中建立入口点,如下所示:

    entry_points="""
    [sqlalchemy.dialects]
    foodialect = foodialect.dialect:FooDialect
    """

如果方言在现有的SQLAlchemy支持的数据库之上为特定DBAPI提供支持,则可以提供名称,包括数据库限定。例如,如果 FooDialect 实际上是一个MySQL方言,入口点可以这样建立:

entry_points="""
[sqlalchemy.dialects]
mysql.foodialect = foodialect.dialect:FooDialect
"""

然后将访问上述入口点作为 create_engine("mysql+foodialect://") .

在进程中注册方言

SQLAlchemy还允许在当前进程中注册方言,而不需要单独安装。使用 register() 功能如下:

from sqlalchemy.dialects import registry
registry.register("mysql.foodialect", "myapp.dialect", "MyMySQLDialect")

以上将对 create_engine("mysql+foodialect://") 并加载 MyMySQLDialect 类从 myapp.dialect 模块。

连接/引擎API

Object Name Description

Connection

为打包的DB-API连接提供高级功能。

CreateEnginePlugin

一组钩子,用于增强 Engine 基于URL中入口点名称的对象。

Engine

连接一个 PoolDialect 一起提供数据库连接和行为的源。

ExceptionContext

封装有关正在进行的错误条件的信息。

NestedTransaction

表示“嵌套”或保存点事务。

RootTransaction

上的“根”事务。 Connection

Transaction

表示正在进行的数据库事务。

TwoPhaseTransaction

表示两阶段事务。

class sqlalchemy.engine.Connection(engine, connection=None, close_with_result=False, _branch_from=None, _execution_options=None, _dispatch=None, _has_events=None, _allow_revalidate=True)

为打包的DB-API连接提供高级功能。

这是SQLAlChemy 1.x.x版本Connection 班级。对于 2.0 style 版本,该版本具有一些API差异,请参见 Connection

这个 Connection 对象是通过调用 Engine.connect() 的方法。 Engine 对象,并为执行SQL语句和事务控制提供服务。

连接对象是 not 线程安全。虽然可以使用适当的同步访问在线程之间共享连接,但底层DBAPI连接仍然可能不支持线程之间的共享访问。有关详细信息,请查看DBAPI文档。

Connection对象表示从连接池签出的单个DBAPI连接。在这种状态下,连接池对连接没有影响,包括其过期或超时状态。为了使连接池能够正确地管理连接,连接应该返回到连接池(即。 connection.close() )当连接不使用时。

类签名

class sqlalchemy.engine.Connection (sqlalchemy.engine.Connectable)

method sqlalchemy.engine.Connection.__init__(engine, connection=None, close_with_result=False, _branch_from=None, _execution_options=None, _dispatch=None, _has_events=None, _allow_revalidate=True)

构建新连接。

method sqlalchemy.engine.Connection.begin()

开始事务并返回事务句柄。

返回的对象是 Transaction . 此对象表示事务的“范围”,当 Transaction.rollback()Transaction.commit() 方法被调用。

小技巧

这个 Connection.begin() 方法时调用 Engine.begin() 上下文管理器方法。引用特定于 Connection.begin() 方法也适用于使用 Engine.begin() 方法。

传统使用:嵌套调用 begin() 在同一时间 Connection 将返回新的 Transaction 对象,这些对象表示封闭事务的作用域内的模拟事务,即:

trans = conn.begin()   # outermost transaction
trans2 = conn.begin()  # "nested"
trans2.commit()        # does nothing
trans.commit()         # actually commits

呼叫 Transaction.commit() 只有通过最外层调用时才有效果 Transaction 对象,尽管 Transaction.rollback() 任何一种方法 Transaction 对象将回滚事务。

小技巧

上面的“嵌套”行为是特定于 1.x style 使用和将在SQLAlChemy 2.0中删除。有关以下内容的备注 2.0 style 使用,请参见 Connection.begin()

参见

Connection.begin_nested() -使用保存点

Connection.begin_twophase() -使用两阶段/xid事务

Engine.begin() - context manager available from Engine

method sqlalchemy.engine.Connection.begin_nested()

假设外部事务已经建立,则开始嵌套事务(即保存点)并返回事务句柄。

嵌套事务需要基础数据库中的保存点支持。层次结构中的任何事务都可以 commitrollback 但是,最外层的事务仍然控制整个 commitrollback 一个整体的交易。

The legacy form of Connection.begin_nested() method has alternate behaviors based on whether or not the Connection.begin() method was called previously. If Connection.begin() was not called, then this method will behave the same as the Connection.begin() method and return a RootTransaction object that begins and commits a real transaction - no savepoint is invoked. If Connection.begin() has been called, and a RootTransaction is already established, then this method returns an instance of NestedTransaction which will invoke and manage the scope of a SAVEPOINT.

小技巧

上述行为 Connection.begin_nested() 是特定于 1.x style 使用。在……里面 2.0 style 使用、 Connection.begin_nested() 方法而是自动开始可以使用“随用随用”方式提交的外部事务;请参见 Connection.begin_nested() 有关迁移详细信息,请参阅。

在 1.4.13 版更改: 的行为 Connection.begin_nested() 作为返回一个 RootTransaction 如果 Connection.begin() 在1.3.x版本中是这样的;在以前的1.4.x版本中,外部事务将是“自动开始的”,但不会被提交。

method sqlalchemy.engine.Connection.begin_twophase(xid=None)

开始两阶段或XA事务并返回事务句柄。

返回的对象是 TwoPhaseTransaction 除了提供的方法外, Transaction ,还提供 TwoPhaseTransaction.prepare() 方法。

参数

xid -- 两阶段事务ID。如果未提供,将生成随机ID。

method sqlalchemy.engine.Connection.close()

关闭此 Connection .

这将导致底层数据库资源的发布,即内部引用的DBAPI连接。DBAPI连接通常恢复到保持连接的状态。 Pool 被引用 Engine 产生了这个 Connection . DBAPI连接上存在的任何事务状态也会通过DBAPI连接无条件释放 rollback() 方法,无论 Transaction 与此相关的未解决对象 Connection .

Connection.close() 被称为 Connection 永久处于关闭状态,不允许进一步操作。

attribute sqlalchemy.engine.Connection.closed

如果此连接已关闭,则返回true。

method sqlalchemy.engine.Connection.connect(close_with_result=False)

返回此的分支版本 Connection .

1.4 版后已移除: 这个 Connection.connect() 方法在SQLAlchemy的1.x系列中被认为是遗留的,并将在2.0中删除。(SQLAlchemy 2.0的背景: 迁移到Alchemy

这个 Connection.close() 返回的方法 Connection 可以叫这个 Connection 将保持打开状态。

这种方法提供了使用对称性 Engine.connect() 包括用于上下文管理器。

attribute sqlalchemy.engine.Connection.connection

此连接管理的基础DB-API连接。

这是SQLAlChemy连接池代理连接,然后该连接具有属性 _ConnectionFairy.dbapi_connection 这指的是实际的驱动程序连接。

attribute sqlalchemy.engine.Connection.default_isolation_level

分配给此的默认隔离级别 Connection .

这是隔离级别设置, Connection 第一次通过 Engine.connect() 方法。此级别在 Connection.execution_options.isolation_level 用于更改PER上的设置 -Connection 基础。

不像 Connection.get_isolation_level() ,此属性是从方言获取的第一个连接提前设置的,因此在调用此访问器时不会调用SQL查询。

0.9.9 新版功能.

method sqlalchemy.engine.Connection.detach()

将基础DB-API连接与其连接池分离。

例如。::

with engine.connect() as conn:
    conn.detach()
    conn.execute(text("SET search_path TO schema1, schema2"))

    # work with connection

# connection is fully closed (since we used "with:", can
# also call .close())

这个 Connection 实例将保持可用。当关闭(或从如上所述的上下文管理器上下文退出)时,DB-API连接将完全关闭,而不会返回到其原始池。

此方法可用于将应用程序的其余部分与连接上的修改状态隔离(例如事务隔离级别或类似级别)。

method sqlalchemy.engine.Connection.exec_driver_sql(statement, parameters=None, execution_options=None)

执行SQL语句构造并返回 CursorResult .

参数
  • statement -- 要执行的语句str。绑定参数必须使用底层DBAPI的paramstyle,例如“qmark”、“pyformat”、“format”等。

  • parameters -- 表示要在执行中使用的绑定参数值。该格式是以下格式之一:命名参数的字典、位置参数的元组,或包含字典或元组的列表,以支持多个执行。E、 g.多个词典:conn.exec_驱动程序u sql(“插入表(id,value)值(%(id)s,%(value)s)”, [{“id”:1,“value”:“v1”}},{“id”:2,“value”:“v2”}] )单个词典:conn.exec_驱动程序u sql(“插入到表(id,value)值(%(id)s,%(value)s)”,dict(id=1,value=“v1”))单元组::conn.exec_驱动程序u sql(“插入表(id,value)值(?)?, ?)",(1,'v1'))。。注意:: Connection.exec_driver_sql() 方法不参与 ConnectionEvents.before_execute()ConnectionEvents.after_execute() 事件。拦截呼叫 Connection.exec_driver_sql() 使用 ConnectionEvents.before_cursor_execute()ConnectionEvents.after_cursor_execute() . …参阅: PEP 249

method sqlalchemy.engine.Connection.execute(statement, *multiparams, **params)

执行SQL语句构造并返回 CursorResult .

参数
  • statement -- 要执行的语句。可能是: 纯字符串(已弃用) 任何 ClauseElement 构造,它也是 Executable ,比如 select() 建造 * a FunctionElement, such as that generated by func, will be automatically wrapped in a SELECT statement, which is then executed. * 一 DDLElement 对象 * a DefaultGenerator object * 一 Compiled 对象。。已弃用::2.0正在将字符串传递给 Connection.execute() 已弃用,将在版本2.0中删除。使用 text() 构建与 Connection.execute() ,或者 Connection.exec_driver_sql() 方法调用驱动程序级别的SQL字符串。

  • *multiparams/**params -- 表示要在执行中使用的绑定参数值。通常,格式是传递给的一个或多个字典的集合 *multiparams:: conn.execute( table.insert(), {{"id":1, "value":"v1"}}, {{"id":2, "value":"v2"}} ) ...or individual key/values interpreted by * *params:: conn.execute( table.insert(), id=1, value="v1" ) In the case that a plain SQL string is passed, and the underlying DBAPI accepts positional bind parameters, a collection of tuples or individual values in * 可以传递multiparams::Conn.ecute(“INSERT INTO TABLE(id,VALUE)VALUES(?,?)”,(1,“v1”),(2,“v2”))CONNEXTE(“INSERT INTO TABLE(id,VALUE)VALUES(?,?)”,1,“v1”)以上注意事项,问号的用法“?”或其他符号取决于所使用的DBAPI接受的“paramstyle”,其可以是“qmark”、“named”、“pyformat”、“format”、“numeric”中的任何一个。看见 pep-249 有关参数样式的详细信息,请参见。若要以与DBAPI无关的方式执行使用绑定参数的文本SQL语句,请使用 text() 构造。。。已弃用::2.0不推荐使用元组或标量位置参数。所有参数都应该是DICT或DICT序列。使用 exec_driver_sql() 执行带有元组或标量位置参数的纯字符串。

method sqlalchemy.engine.Connection.execution_options(**opt)

为在执行期间生效的连接设置非SQL选项。

对于“future”样式的连接,此方法返回相同的 Connection 对象添加了新选项。

对于旧连接,此方法返回 Connection 它引用相同的基础DBAPI连接,但也定义了给定的执行选项,这些选项将在调用 execute() . 作为新的 Connection 引用相同的基础资源,通常最好确保立即丢弃副本,这在以下情况下是隐式的:

result = connection.execution_options(stream_results=True).\
                    execute(stmt)

注意,任何键/值都可以传递给 Connection.execution_options() ,它将存储在 _execution_options 字典 Connection . 例如,它适合于最终用户方案与事件侦听器通信。

当前由sqlacalchemy本身识别的关键字包括下面列出的所有关键字 Executable.execution_options() 以及其他特定于 Connection .

参数
  • autocommit -- 可用于:连接,语句。如果为True,则在“autocommit”模式下执行时,即在连接上没有开始显式事务时,将在执行后调用提交。注意这是 库级别,而不是DBAPI级别的自动提交 . 除非使用“AUTOCOMMIT”隔离级别,否则DBAPI连接将保留在实际事务中。。已弃用::1.4“autocommit”执行选项已弃用,将在SQLAlchemy 2.0中删除。看到了吗 库级(但不是驱动程序级)“自动提交”从核心和ORM中删除 供讨论。

  • compiled_cache -- 在:连接上可用。字典在哪里 CompiledConnection 将子句表达式编译为 Compiled 对象。此字典将取代在上配置的语句缓存 Engine 本身。如果设置为“无”,则禁用缓存,即使引擎已配置缓存大小。注意,它自己的一些操作,包括刷新操作。ORM内部使用的缓存将取代此处指定的缓存字典。

  • logging_token -- 可在以下位置获得: ConnectionEngine 。在连接记录的日志消息中添加由括号括起来的指定字符串标记,即通过 create_engine.echo 标志或通过 logging.getLogger("sqlalchemy.engine") 伐木者。这允许每个连接或每个子引擎的令牌可用,这对于调试并发连接方案很有用。。。版本添加::1.4.0b2..另请参阅:: 设置每个连接/子引擎令牌 -使用示例 create_engine.logging_name -将名称添加到Python记录器对象本身使用的名称。

  • isolation_level --

    可供选择: Connection .

    为此的生命周期设置事务隔离级别 Connection 对象。有效值包括 create_engine.isolation_level 传递给的参数 create_engine() . 这些级别是半数据库特定的;有关有效级别,请参阅各个方言文档。

    隔离级别选项通过在DBAPI连接上发出语句来应用隔离级别,并且 必然会整体影响原始连接对象 ,而不仅仅是调用返回的副本 Connection.execution_options() 方法。隔离级别将保持在给定的设置,直到DBAPI连接本身返回到连接池,即 Connection.close() 原方法 Connection 调用时,事件处理程序将在DBAPI连接上发出附加语句,以便恢复隔离级别更改。

    警告

    这个 isolation_level 执行选项应该 not 当事务已经建立时使用,即 Connection.begin() 已调用方法或类似方法。数据库无法更改正在进行的事务的隔离级别,不同的dbapis和/或sqlachemy方言可能隐式回滚或提交事务,或者根本不影响连接。

    注解

    这个 isolation_level 如果 Connection 无效,例如通过 Connection.invalidate() 方法,或者如果发生断开错误。失效后产生的新连接不会自动重新应用隔离级别。

  • no_parameters -- 什么时候? True 如果最终参数列表或字典完全为空,则将调用光标上的语句 cursor.execute(statement) ,根本不传递参数集合。一些DBAPI(如psycopg2和mysql python)仅在存在参数时才将百分号视为重要的符号;此选项允许代码生成包含百分号(可能还有其他字符)的SQL,这些百分号与DBAPI是否执行它或是否通过管道传输到稍后由命令行工具调用的脚本无关。

  • stream_results -- 可用于:连接,语句。如果可能的话,告诉方言结果应该是“流式”的,而不是预缓冲的。这是许多dbapi的一个限制。该标志目前在PostgreSQL和MySQL类别的方言子集中被理解,并且可能被其他第三方方言所支持。。另请参见: 使用服务器端游标(即流结果)

  • schema_translate_map -- 提供:连接,发动机。将架构名称映射到架构名称的字典,该字典将应用于 Table.schema 各元素 Table 当SQL或DDL表达式元素编译为字符串时遇到;将根据原始名称的映射中的存在来转换生成的架构名称。…版本已添加::1.1..参阅: 模式名称的翻译

method sqlalchemy.engine.Connection.get_execution_options()

获取将在执行期间生效的非SQL选项。

1.3 新版功能.

method sqlalchemy.engine.Connection.get_isolation_level()

返回分配给此的当前隔离级别 Connection .

这通常是由方言确定的默认隔离级别,除非 Connection.execution_options.isolation_level 已使用功能更改每个上的隔离级别 -Connection 基础。

此属性通常会执行实时SQL操作以获取当前隔离级别,因此返回的值是基础DBAPI连接的实际级别,而不管如何设置此状态。相比于 Connection.default_isolation_level 访问器,返回方言级别设置而不执行SQL查询。

0.9.9 新版功能.

method sqlalchemy.engine.Connection.get_nested_transaction()

返回当前正在进行的嵌套事务(如果有)。

1.4 新版功能.

method sqlalchemy.engine.Connection.get_transaction()

返回当前正在进行的根事务(如果有)。

1.4 新版功能.

method sqlalchemy.engine.Connection.in_nested_transaction()

如果事务正在进行,则返回true。

method sqlalchemy.engine.Connection.in_transaction()

如果事务正在进行,则返回true。

attribute sqlalchemy.engine.Connection.info

与此引用的基础DBAPI连接关联的信息字典 Connection ,允许用户定义的数据与连接关联。

这里的数据将与DBAPI连接一起使用,包括在它返回到连接池并在随后的实例中再次使用之后。 Connection .

method sqlalchemy.engine.Connection.invalidate(exception=None)

使与此关联的基础DBAPI连接失效 Connection .

将尝试立即关闭底层DBAPI连接;但是,如果此操作失败,将记录错误,但不会引发错误。无论close()是否成功,连接都将被丢弃。

下次使用时(其中“使用”通常指使用 Connection.execute() 方法或类似方法),此 Connection 将尝试使用 Pool 作为连接源(例如“重新连接”)。

如果交易正在进行(例如 Connection.begin() 方法)当 Connection.invalidate() 方法在dbapi级别被调用,当dbapi连接关闭时,与此事务关联的所有状态都将丢失。这个 Connection 将不允许重新连接继续,直到 Transaction 对象结束,方法是调用 Transaction.rollback() 方法;在此之前,继续使用 Connection 将提高 InvalidRequestError . 这是为了防止应用程序意外地继续正在进行的事务操作,尽管事务由于无效而丢失。

这个 Connection.invalidate() 方法和自动失效一样,将在连接池级别调用 PoolEvents.invalidate() 事件。

参数

exception -- 可选的 Exception 实例这就是无效的原因。传递给事件处理程序和日志记录函数。

attribute sqlalchemy.engine.Connection.invalidated

如果此连接无效,则返回true。

method sqlalchemy.engine.Connection.run_callable(callable_, *args, **kwargs)

给定一个可调用的对象或函数,执行它,传递 Connection 作为第一个论点。

1.4 版后已移除: 这个 Connection.run_callable() 方法已弃用,并将在将来的版本中删除。传递连接,直接调用可调用函数。

给定的 * ARGS和 * *Kwargs在 Connection 争论。

这个函数,以及 Engine.run_callable() ,允许使用 ConnectionEngine 对象,不需要知道正在处理哪个对象。

method sqlalchemy.engine.Connection.scalar(object_, *multiparams, **params)

执行并返回第一行的第一列。

基础结果/光标在执行后关闭。

method sqlalchemy.engine.Connection.scalars(object_, *multiparams, **params)

执行并返回标量结果集,该结果集从每行的第一列生成标量值。

此方法等效于调用 Connection.execute() 要获得一个 Result 对象,然后调用 Result.scalars() 方法来生成 ScalarResult 实例。

返回

一个 ScalarResult

1.4.24 新版功能.

method sqlalchemy.engine.Connection.schema_for_object(obj)

返回给定架构项的架构名称,同时考虑当前架构转换映射。

method sqlalchemy.engine.Connection.transaction(callable_, *args, **kwargs)

在事务边界内执行给定的函数。

1.4 版后已移除: 这个 Connection.transaction() 方法已弃用,将在将来的版本中删除。使用 Engine.begin() 而不是上下文管理器。

函数通过此 Connection 作为第一个参数,后跟给定的 * ARGS和 * *KWARG,例如:

def do_something(conn, x, y):
    conn.execute(text("some statement"), {'x':x, 'y':y})

conn.transaction(do_something, 5, 10)

函数内部的操作都是在单个 Transaction . 一旦成功,事务就被提交。如果引发异常,则在传播异常之前回滚事务。

注解

这个 transaction() 方法被python的用法取代 with: 语句,可用于 Connection.begin() ::

with conn.begin():
    conn.execute(text("some statement"), {'x':5, 'y':10})

以及与 Engine.begin() ::

with engine.begin() as conn:
    conn.execute(text("some statement"), {'x':5, 'y':10})

参见

Engine.begin() -引擎级事务上下文

Engine.transaction() - engine-level version of Connection.transaction()

class sqlalchemy.engine.CreateEnginePlugin(url, kwargs)

一组钩子,用于增强 Engine 基于URL中入口点名称的对象。

目的 CreateEnginePlugin 允许第三方系统应用引擎、池和方言级别的事件侦听器,而不需要修改目标应用程序;相反,插件名称可以添加到数据库URL。目标应用程序 CreateEnginePlugin 包括:

  • 连接和SQL性能工具,例如使用事件跟踪签出次数和/或语句花费的时间

  • 连接插件,如代理

雏形 CreateEnginePlugin 将一个记录器连接到 Engine 对象可能看起来像:

import logging

from sqlalchemy.engine import CreateEnginePlugin
from sqlalchemy import event

class LogCursorEventsPlugin(CreateEnginePlugin):
    def __init__(self, url, kwargs):
        # consume the parameter "log_cursor_logging_name" from the
        # URL query
        logging_name = url.query.get("log_cursor_logging_name", "log_cursor")

        self.log = logging.getLogger(logging_name)

    def update_url(self, url):
        "update the URL to one that no longer includes our parameters"
        return url.difference_update_query(["log_cursor_logging_name"])

    def engine_created(self, engine):
        "attach an event listener after the new Engine is constructed"
        event.listen(engine, "before_cursor_execute", self._log_event)


    def _log_event(
        self,
        conn,
        cursor,
        statement,
        parameters,
        context,
        executemany):

        self.log.info("Plugin logged cursor event: %s", statement)

插件的注册使用入口点的方式与方言类似:

entry_points={
    'sqlalchemy.plugins': [
        'log_cursor_plugin = myapp.plugins:LogCursorEventsPlugin'
    ]

使用上述名称的插件将从数据库URL调用,如下所示:

from sqlalchemy import create_engine

engine = create_engine(
    "mysql+pymysql://scott:tiger@localhost/test?"
    "plugin=log_cursor_plugin&log_cursor_logging_name=mylogger"
)

这个 plugin URL参数支持多个实例,因此一个URL可以指定多个插件;它们是按照URL中声明的顺序加载的:

engine = create_engine(
  "mysql+pymysql://scott:tiger@localhost/test?"
  "plugin=plugin_one&plugin=plugin_twp&plugin=plugin_three")

插件名称也可以直接传递给 create_engine() 使用 create_engine.plugins 论点:

engine = create_engine(
  "mysql+pymysql://scott:tiger@localhost/test",
  plugins=["myplugin"])

1.2.3 新版功能: 插件名称也可以指定为 create_engine() 作为清单

插件可以使用来自 URL 对象以及 kwargs 字典,它是传递给 create_engine() 打电话。”消费”这些参数包括当插件初始化时必须删除它们,这样参数就不会传递给 Dialect 构造函数,在那里他们将引发一个 ArgumentError 因为他们不知道方言。

从SQLAlchemy的1.4版本开始,参数应该继续从 kwargs 通过使用诸如 dict.pop . 来自 URL 对象的 CreateEnginePlugin.update_url() 方法,返回 URL 移除了特定参数的插件:

class MyPlugin(CreateEnginePlugin):
    def __init__(self, url, kwargs):
        self.my_argument_one = url.query['my_argument_one']
        self.my_argument_two = url.query['my_argument_two']
        self.my_argument_three = kwargs.pop('my_argument_three', None)

    def update_url(self, url):
        return url.difference_update_query(
            ["my_argument_one", "my_argument_two"]
        )

上面所示的参数将从 create_engine() 例如:

from sqlalchemy import create_engine

engine = create_engine(
  "mysql+pymysql://scott:tiger@localhost/test?"
  "plugin=myplugin&my_argument_one=foo&my_argument_two=bar",
  my_argument_three='bat'
)

在 1.4 版更改: 这个 URL 对象现在是不可变的;a CreateEnginePlugin 需要改变 URL 应实施新增 CreateEnginePlugin.update_url() 方法,在构建插件后调用。

对于迁移,按照以下方式构造插件,检查是否存在 CreateEnginePlugin.update_url() 方法来检测哪个版本正在运行:

class MyPlugin(CreateEnginePlugin):
    def __init__(self, url, kwargs):
        if hasattr(CreateEnginePlugin, "update_url"):
            # detect the 1.4 API
            self.my_argument_one = url.query['my_argument_one']
            self.my_argument_two = url.query['my_argument_two']
        else:
            # detect the 1.3 and earlier API - mutate the
            # URL directly
            self.my_argument_one = url.query.pop('my_argument_one')
            self.my_argument_two = url.query.pop('my_argument_two')

        self.my_argument_three = kwargs.pop('my_argument_three', None)

    def update_url(self, url):
        # this method is only called in the 1.4 version
        return url.difference_update_query(
            ["my_argument_one", "my_argument_two"]
        )

参见

URL对象现在是不可变的 -概述 URL 变更还包括关于 CreateEnginePlugin .

当引擎创建过程完成并生成 Engine 对象,它再次通过 CreateEnginePlugin.engine_created() 钩子。在这个钩子中,可以对引擎进行额外的更改,最典型的是涉及事件设置(例如,在 核心事件

1.1 新版功能.

method sqlalchemy.engine.CreateEnginePlugin.__init__(url, kwargs)

构建新的 CreateEnginePlugin .

插件对象在每次调用 create_engine() . 单一的 Engine 将传递给 CreateEnginePlugin.engine_created() 与此URL对应的方法。

参数
method sqlalchemy.engine.CreateEnginePlugin.engine_created(engine)

接收 Engine 对象完全构造后。

插件可以对引擎进行其他更改,例如注册引擎或连接池事件。

method sqlalchemy.engine.CreateEnginePlugin.handle_dialect_kwargs(dialect_cls, dialect_args)

解析和修改方言Kwargs

method sqlalchemy.engine.CreateEnginePlugin.handle_pool_kwargs(pool_cls, pool_args)

解析和修改池Kwargs

method sqlalchemy.engine.CreateEnginePlugin.update_url(url)

更新 URL .

一个新的 URL 应该归还。此方法通常用于使用来自 URL 必须删除,因为他们不会被方言识别。这个 URL.difference_update_query() 方法可用于删除这些参数。查看docstring CreateEnginePlugin 举个例子。

1.4 新版功能.

class sqlalchemy.engine.Engine(pool, dialect, url, logging_name=None, echo=None, query_cache_size=500, execution_options=None, hide_parameters=False)

连接一个 PoolDialect 一起提供数据库连接和行为的源。

这是 SQLAlChemy 1.x版Engine 。对于 2.0 style 版本,其中包括一些API差异,请参见 Engine

Engine 对象是使用 create_engine() 功能。

类签名

class sqlalchemy.engine.Engine (sqlalchemy.engine.Connectable, sqlalchemy.log.Identified)

method sqlalchemy.engine.Engine.begin(close_with_result=False)

返回一个上下文管理器 Connection 用一个 Transaction 建立。

例如。::

with engine.begin() as conn:
    conn.execute(
        text("insert into table (x, y, z) values (1, 2, 3)")
    )
    conn.execute(text("my_special_procedure(5)"))

操作成功后, Transaction 承诺。如果出现错误,则 Transaction 回滚。

仅限传统使用: close_with_result 标志通常是 False ,并指示 Connection 将在操作完成后关闭。当设置为时 True ,它表示 Connection 处于“单机使用”模式,其中 CursorResult 的第一次调用返回 Connection.execute() 将关闭 Connection 当那件事发生的时候 CursorResult 已用尽所有结果行。

参见

Engine.connect() -获得A Connection 从一个 Engine .

Connection.begin() -启动一个 Transaction 对于一个特定的 Connection .

method sqlalchemy.engine.Engine.clear_compiled_cache()

清除与方言关联的已编译缓存。

这适用 only 到通过建立的内置缓存 create_engine.query_cache_size 参数。它不会影响通过 Connection.execution_options.query_cache 参数。

1.4 新版功能.

method sqlalchemy.engine.Engine.connect(close_with_result=False)

返回一个新的 Connection 对象。

这个 Connection 对象是在内部使用DBAPI连接以便与数据库通信的外观。此连接是从连接保持中获得的 Pool 引用人: Engine . 当 Connection.close() 方法 Connection 对象,然后将基础DBAPI连接返回到连接池,在随后的对 Engine.connect() .

method sqlalchemy.engine.Engine.dispose()

释放此使用的连接池 Engine .

这有完全关闭所有 当前已签入 数据库连接。仍被签出的连接将 not 关闭,但它们将不再与此关联 Engine 因此,当它们单独关闭时,最终 Pool 它们与之相关联的将被垃圾收集,并且如果在签入时尚未关闭,它们将被完全关闭。

在释放旧连接池后立即创建新连接池。与所有SQLAlchemy连接池一样,只要 Engine 不再使用,不会建立新连接。

参见

引擎处理

attribute sqlalchemy.engine.Engine.driver

驱动程序名称 Dialect 在使用中 Engine .

method sqlalchemy.engine.Engine.execute(statement, *multiparams, **params)

执行给定的构造并返回 CursorResult .

1.4 版后已移除: 这个 Engine.execute() 方法在SQLAlchemy的1.x系列中被认为是遗留的,并将在2.0中删除。SQLAlchemy 2.0中的所有语句执行都由 Connection.execute() 方法 Connection ,或在ORM中 Session.execute() 方法 Session . (SQLAlchemy 2.0的背景: 迁移到Alchemy

这些参数与 Connection.execute() .

这里,A Connection 是使用 Engine.connect() 方法,以及使用该连接执行的语句。归还的人 CursorResult 标记为当 CursorResult 已耗尽并且其基础光标已关闭, Connection 在此创建的数据库也将关闭,这将允许其关联的DBAPI连接资源返回到连接池。

method sqlalchemy.engine.Engine.execution_options(**opt)

返回一个新的 Engine 这将提供 Connection 具有给定执行选项的对象。

归还的人 Engine 与原件有关 Engine 因为它共享相同的连接池和其他状态:

  • 这个 Pool 新使用 Engine 是同一个实例。这个 Engine.dispose() 方法将替换父引擎以及此引擎的连接池实例。

  • 事件侦听器是“级联”的,也就是说,新的 Engine 继承父级的事件,新事件可以与新事件关联 Engine 个别地。

  • 日志配置和日志记录名称从父级复制 Engine .

的意图 Engine.execution_options() 方法是在多个 Engine 对象引用相同的连接池,但由自定义事件将使用的选项区分:

primary_engine = create_engine("mysql://")
shard1 = primary_engine.execution_options(shard_id="shard1")
shard2 = primary_engine.execution_options(shard_id="shard2")

上面, shard1 发动机作为工厂 Connection 将包含执行选项的对象 shard_id=shard1shard2 将生产 Connection 包含执行选项的对象 shard_id=shard2 .

事件处理程序可以使用上述执行选项在给定连接的情况下执行模式切换或其他操作。下面我们发出一个mysql use 语句切换数据库,同时跟踪使用 Connection.info 字典,它为我们提供了遵循DBAPI连接的持久存储空间:

from sqlalchemy import event
from sqlalchemy.engine import Engine

shards = {"default": "base", shard_1: "db1", "shard_2": "db2"}

@event.listens_for(Engine, "before_cursor_execute")
def _switch_shard(conn, cursor, stmt,
        params, context, executemany):
    shard_id = conn._execution_options.get('shard_id', "default")
    current_shard = conn.info.get("current_shard", None)

    if current_shard != shard_id:
        cursor.execute("use %s" % shards[shard_id])
        conn.info["current_shard"] = shard_id

参见

Connection.execution_options() -更新上的执行选项 Connection 对象。

Engine.update_execution_options() -更新给定的执行选项 Engine 就位。

Engine.get_execution_options()

method sqlalchemy.engine.Engine.get_execution_options()

获取将在执行期间生效的非SQL选项。

method sqlalchemy.engine.Engine.has_table(table_name, schema=None)

如果给定后端具有给定名称的表,则返回true。

1.4 版后已移除: 这个 Engine.has_table() 方法已弃用,将在将来的版本中删除。请参考 Inspector.has_table() .

参见

带检查员的细颗粒反射 -使用 Inspector 接口。

quoted_name -用于传递引用信息和模式标识符。

attribute sqlalchemy.engine.Engine.name

字符串名称 Dialect 在使用中 Engine .

method sqlalchemy.engine.Engine.raw_connection(_connection=None)

从连接池返回“原始”DBAPI连接。

返回的对象是正在使用的底层驱动程序所使用的DBAPI连接对象的代理版本。对象将具有与实际DBAPI连接相同的行为,除了 close() 方法将导致连接返回池,而不是实际关闭。

当API由提供时,此方法为特殊情况提供直接DBAPI连接访问 Connection 不需要。当A Connection 对象已存在,DBAPI连接可使用 Connection.connection 访问器。

method sqlalchemy.engine.Engine.run_callable(callable_, *args, **kwargs)

给定一个可调用的对象或函数,执行它,传递 Connection 作为第一个论点。

1.4 版后已移除: 这个 Engine.run_callable() 方法已弃用,并将在将来的版本中删除。使用 Engine.begin() 取而代之的是上下文管理器。

给定的 * ARGS和 * *Kwargs在 Connection 争论。

这个函数,以及 Connection.run_callable() ,允许使用 ConnectionEngine 对象,不需要知道正在处理哪个对象。

method sqlalchemy.engine.Engine.scalar(statement, *multiparams, **params)

执行并返回第一行的第一列。

1.4 版后已移除: 这个 Engine.scalar() 方法在SQLAlchemy的1.x系列中被认为是遗留的,并将在2.0中删除。SQLAlchemy 2.0中的所有语句执行都由 Connection.execute() 方法 Connection ,或在ORM中 Session.execute() 方法 SessionResult.scalar() 方法可用于返回标量结果。(SQLAlchemy 2.0的背景: 迁移到Alchemy

基础结果/光标在执行后关闭。

method sqlalchemy.engine.Engine.table_names(schema=None, connection=None)

返回数据库中所有可用表名的列表。

1.4 版后已移除: 这个 Engine.table_names() 方法已弃用,将在将来的版本中删除。请参考 Inspector.get_table_names() .

参数
  • schema -- 可选,从非默认架构中检索名称。

  • connection -- 可选,使用指定的连接。

method sqlalchemy.engine.Engine.transaction(callable_, *args, **kwargs)

在事务边界内执行给定的函数。

1.4 版后已移除: 这个 Engine.transaction() 方法已弃用,将在将来的版本中删除。使用 Engine.begin() 而不是上下文管理器。

函数通过 Connection 新购自 Engine.connect() 作为第一个参数,后跟给定的 * ARGS和 * *克沃斯。

例如。::

def do_something(conn, x, y):
    conn.execute(text("some statement"), {'x':x, 'y':y})

engine.transaction(do_something, 5, 10)

函数内部的操作都是在单个 Transaction . 一旦成功,事务就被提交。如果引发异常,则在传播异常之前回滚事务。

注解

这个 transaction() 方法被python的用法取代 with: 语句,可用于 Engine.begin() ::

with engine.begin() as conn:
    conn.execute(text("some statement"), {'x':5, 'y':10})

参见

Engine.begin() -引擎级事务上下文

Connection.transaction() - connection-level version of Engine.transaction()

method sqlalchemy.engine.Engine.update_execution_options(**opt)

更新此的默认执行选项字典 Engine .

中给定的键/值 * *opt被添加到将用于所有连接的默认执行选项中。本词典的初始内容可通过 execution_options 参数到 create_engine() .

class sqlalchemy.engine.ExceptionContext

封装有关正在进行的错误条件的信息。

此对象只存在于传递给 ConnectionEvents.handle_error() 事件,支持一个接口,该接口可以在不向后不兼容的情况下进行扩展。

0.9.7 新版功能.

attribute sqlalchemy.engine.ExceptionContext.chained_exception = None

异常链中的前一个处理程序返回的异常(如果有)。

如果存在,则此异常将是最终由SQLAlchemy引发的异常,除非后续处理程序替换它。

可能没有。

attribute sqlalchemy.engine.ExceptionContext.connection = None

这个 Connection 在异常期间使用。

此成员存在,除非第一次连接时出现故障。

attribute sqlalchemy.engine.ExceptionContext.cursor = None

DBAPI光标对象。

可能没有。

attribute sqlalchemy.engine.ExceptionContext.engine = None

这个 Engine 在异常期间使用。

即使在第一次连接失败的情况下,此成员也应始终存在。

1.0.0 新版功能.

attribute sqlalchemy.engine.ExceptionContext.execution_context = None

这个 ExecutionContext 与正在执行的操作相对应。

这适用于语句执行操作,但不适用于事务开始/结束等操作。当异常在 ExecutionContext 可以构造。

请注意 ExceptionContext.statementExceptionContext.parameters 成员可以表示不同于 ExecutionContext ,可能在以下情况下 ConnectionEvents.before_cursor_execute() 事件或类似事件修改了要发送的语句/参数。

可能没有。

attribute sqlalchemy.engine.ExceptionContext.invalidate_pool_on_disconnect = True

表示当“断开连接”条件生效时,池中的所有连接是否应失效。

ConnectionEvents.handle_error() 事件的作用是,在断开连接期间,池中的全部连接集合不会失效;只有作为错误主题的当前连接才会真正失效。

此标志用于自定义断开连接处理方案,其中池中的其他连接的失效将基于其他条件执行,甚至基于每个连接执行。

1.0.3 新版功能.

attribute sqlalchemy.engine.ExceptionContext.is_disconnect = None

表示发生的异常是否表示“断开”状态。

此标志在 ConnectionEvents.handle_error() 处理程序。

SQLAlchemy将遵从此标志,以确定连接是否应在随后失效。也就是说,通过分配给该标志,可以通过更改该标志来调用或阻止“断开”事件,从而导致连接和池无效。

注解

使用 create_engine.pool_pre_ping 参数可以 not 在决定“ping”是否返回false(而不是接收未处理的错误)之前,请咨询此事件。对于这个用例 legacy recipe based on engine_connect() may be used . 未来的API允许对所有函数的“断开连接”检测机制进行更全面的定制。

attribute sqlalchemy.engine.ExceptionContext.original_exception = None

捕获的异常对象。

此成员始终存在。

attribute sqlalchemy.engine.ExceptionContext.parameters = None

直接发送到DBAPI的参数集合。

可能没有。

attribute sqlalchemy.engine.ExceptionContext.sqlalchemy_exception = None

这个 sqlalchemy.exc.StatementError 它包装了原始数据,如果事件没有规避异常处理,则将引发异常处理。

可能是none,因为并非所有异常类型都由sqlAlchemy包装。对于DBAPI级别的异常(它是DBAPI错误类的子类),此字段将始终存在。

attribute sqlalchemy.engine.ExceptionContext.statement = None

直接发送到DBAPI的字符串SQL语句。

可能没有。

class sqlalchemy.engine.NestedTransaction(connection)

表示“嵌套”或保存点事务。

这个 NestedTransaction 对象是通过调用 Connection.begin_nested() 一种方法 Connection

在使用时 NestedTransaction ,BEGIN/COMMIT/ROLLBACK的语义如下:

根据保存点模拟外部事务语义的基本原理,以便代码可以以不可知的方式处理“保存点”事务和“外部”事务。

参见

使用保存点 -保存点API的ORM版本。

method sqlalchemy.engine.NestedTransaction.close()

inherited from the Transaction.close() method of Transaction

关闭此 Transaction .

如果此事务是begin/commit嵌套中的基本事务,则该事务将回滚()。否则,方法返回。

这用于取消事务,而不影响封闭事务的范围。

method sqlalchemy.engine.NestedTransaction.commit()

inherited from the Transaction.commit() method of Transaction

提交此 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

method sqlalchemy.engine.NestedTransaction.rollback()

inherited from the Transaction.rollback() method of Transaction

回滚这个 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

class sqlalchemy.engine.RootTransaction(connection)

上的“根”事务。 Connection

这对应于当前发生的“BEGIN/COMMIT/ROLLBACK”(开始/提交/回滚 Connection 。这个 RootTransaction 通过调用 Connection.begin() 方法,并保持与 Connection 在其整个活跃的跨度内。当前 RootTransaction 正在使用中,可通过 Connection.get_transaction 一种方法 Connection

在……里面 2.0 style 使用、 Connection 还使用“自动开始”行为,该行为将创建新的 RootTransaction 每当使用处于非事务状态的连接在DBAPI连接上发出命令时。的范围 RootTransaction 在2.0样式中,可以使用 Connection.commit()Connection.rollback() 方法。

method sqlalchemy.engine.RootTransaction.close()

inherited from the Transaction.close() method of Transaction

关闭此 Transaction .

如果此事务是begin/commit嵌套中的基本事务,则该事务将回滚()。否则,方法返回。

这用于取消事务,而不影响封闭事务的范围。

method sqlalchemy.engine.RootTransaction.commit()

inherited from the Transaction.commit() method of Transaction

提交此 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

method sqlalchemy.engine.RootTransaction.rollback()

inherited from the Transaction.rollback() method of Transaction

回滚这个 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

class sqlalchemy.engine.Transaction(connection)

表示正在进行的数据库事务。

这个 Transaction 对象是通过调用 Connection.begin() 方法 Connection ::

from sqlalchemy import create_engine
engine = create_engine("postgresql://scott:tiger@localhost/test")
connection = engine.connect()
trans = connection.begin()
connection.execute(text("insert into x (a, b) values (1, 2)"))
trans.commit()

对象提供 rollback()commit() 方法以控制事务边界。它还实现了一个上下文管理器接口,以便 with 语句可与 Connection.begin() 方法:

with connection.begin():
    connection.execute(text("insert into x (a, b) values (1, 2)"))

事务对象是 not 线程安全。

类签名

class sqlalchemy.engine.Transaction (sqlalchemy.engine.util.TransactionalContext)

method sqlalchemy.engine.Transaction.close()

关闭此 Transaction .

如果此事务是begin/commit嵌套中的基本事务,则该事务将回滚()。否则,方法返回。

这用于取消事务,而不影响封闭事务的范围。

method sqlalchemy.engine.Transaction.commit()

提交此 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

method sqlalchemy.engine.Transaction.rollback()

回滚这个 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

class sqlalchemy.engine.TwoPhaseTransaction(connection, xid)

表示两阶段事务。

一个新的 TwoPhaseTransaction 可使用 Connection.begin_twophase() 方法。

接口与 Transaction 加上 prepare() 方法。

method sqlalchemy.engine.TwoPhaseTransaction.close()

inherited from the Transaction.close() method of Transaction

关闭此 Transaction .

如果此事务是begin/commit嵌套中的基本事务,则该事务将回滚()。否则,方法返回。

这用于取消事务,而不影响封闭事务的范围。

method sqlalchemy.engine.TwoPhaseTransaction.commit()

inherited from the Transaction.commit() method of Transaction

提交此 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

method sqlalchemy.engine.TwoPhaseTransaction.prepare()

准备好这个 TwoPhaseTransaction .

准备之后,可以提交事务。

method sqlalchemy.engine.TwoPhaseTransaction.rollback()

inherited from the Transaction.rollback() method of Transaction

回滚这个 Transaction .

此功能的实施可能会根据使用的交易类型而有所不同:

结果集API

Object Name Description

BaseCursorResult

数据库结果对象的基类。

ChunkedIteratorResult

IteratorResult 从迭代器产生可调用的。

CursorResult

表示DBAPI游标状态的结果。

FrozenResult

表示 Result 对象处于适合缓存的“冻结”状态。

IteratorResult

A Result 它从的Python迭代器获取数据 Row 物体。

LegacyCursorResult

的旧版本 CursorResult .

LegacyRow

一个子类 Row 它为核心提供了1.x SQLAlchemy行为。

MappingResult

包装纸 Result 返回字典值而不是 Row 价值观。

MergedResult

A Result 从任何数量的 Result 物体。

Result

表示一组数据库结果。

Row

表示单个结果行。

RowMapping

A Mapping 将列名和对象映射到 Row 价值观。

ScalarResult

包装纸 Result 返回标量值而不是 Row 价值观。

class sqlalchemy.engine.BaseCursorResult(context, cursor_strategy, cursor_description)

数据库结果对象的基类。

attribute sqlalchemy.engine.BaseCursorResult.inserted_primary_key

返回刚刚插入的行的主键。

返回值为 Row 对象,该对象按照主键列在源中的配置顺序表示主键值的命名元组 Table

在 1.4.8 版更改: -The CursorResult.inserted_primary_key 值现在是一个命名元组,通过 Row 类,而不是纯元组。

此访问器仅适用于单行 insert() 未显式指定的构造 Insert.returning() 。虽然对多行插入的支持对大多数后端都不可用,但可以使用 CursorResult.inserted_primary_key_rows 访问者。

请注意,指定server_default子句的主键列或其他列不符合“autoincrement”列的条件(请参阅中的注释 Column ,并且是使用数据库端默认值生成的,将在此列表中显示为 None 除非后端支持“返回”,并且在启用“隐式返回”的情况下执行insert语句。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造或不是insert()构造。

attribute sqlalchemy.engine.BaseCursorResult.inserted_primary_key_rows

返回的值 CursorResult.inserted_primary_key 作为列表中包含的一行;某些方言也可能支持多行形式。

注解

如下所示,在当前的SQLAlChemy版本中,此访问器仅在已提供的功能之外才有用 CursorResult.inserted_primary_key 在使用 PycPcG2 方言。未来的版本希望将此功能推广到更多的方言。

添加此访问器是为了支持提供当前由 Psycopg2快速执行助手 功能,当前 只有mental copg2方言 ,它允许一次插入许多行,同时仍然保留能够返回服务器生成的主键值的行为。

  • 在即将发布的版本中使用mental copg2方言或其他可能支持“Fast Executemany”样式插入的方言时 : When invoking an INSERT statement while passing a list of rows as the second argument to Connection.execute() ,则此访问器将提供行列表,其中每行都包含插入的每行的主键值。

  • When using all other dialects / backends that don't yet support this feature :此访问器仅适用于 单行INSERT语句 ,并返回与 CursorResult.inserted_primary_key 在单个元素列表中。当INSERT语句与要插入的行列表一起执行时,该列表将包含语句中插入的每行一行,但是它将包含 None 用于任何服务器生成的值。

SQLAlChemy的未来版本将进一步概括mental copg2的“快速执行帮助器”特性,以适应其他方言,从而允许该访问器具有更广泛的用途。

1.4 新版功能.

attribute sqlalchemy.engine.BaseCursorResult.is_insert

如果这是真的 CursorResult 是执行已编译的表达式语言的结果 insert() 构造。

如果是真的,这意味着 inserted_primary_key 属性是可访问的,假定语句不包含用户定义的“返回”构造。

method sqlalchemy.engine.BaseCursorResult.last_inserted_params()

返回此执行中插入参数的集合。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造或不是insert()构造。

method sqlalchemy.engine.BaseCursorResult.last_updated_params()

返回此执行中更新参数的集合。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造或不是update()构造。

method sqlalchemy.engine.BaseCursorResult.lastrow_has_defaults()

返回 lastrow_has_defaults() 从底层 ExecutionContext .

ExecutionContext 有关详细信息。

attribute sqlalchemy.engine.BaseCursorResult.lastrowid

返回DBAPI游标上的“lastrowid”访问器。

这是一种特定于DBAPI的方法,仅对支持它的后端和适当的语句有效。它的行为在后端不一致。

在使用insert()表达式构造时,通常不需要使用此方法;在 CursorResult.inserted_primary_key 属性为新插入的行提供主键值的元组,而不考虑数据库后端。

method sqlalchemy.engine.BaseCursorResult.postfetch_cols()

返回 postfetch_cols() 从底层 ExecutionContext .

ExecutionContext 有关详细信息。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造,或者不是insert()或update()构造。

method sqlalchemy.engine.BaseCursorResult.prefetch_cols()

返回 prefetch_cols() 从底层 ExecutionContext .

ExecutionContext 有关详细信息。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造,或者不是insert()或update()构造。

attribute sqlalchemy.engine.BaseCursorResult.returned_defaults

返回使用 ValuesBase.return_defaults() 特征。

该值是的实例 RowNone 如果 ValuesBase.return_defaults() 未使用或后端不支持返回。

0.9.0 新版功能.

attribute sqlalchemy.engine.BaseCursorResult.returned_defaults_rows

返回一个行列表,每个行包含使用 ValuesBase.return_defaults() 特征。

返回值是 Row 物体。

1.4 新版功能.

attribute sqlalchemy.engine.BaseCursorResult.returns_rows

如果这是真的 CursorResult 返回零行或更多行。

也就是说,如果调用这些方法是合法的 CursorResult.fetchone()CursorResult.fetchmany() CursorResult.fetchall() .

总的来说 CursorResult.returns_rows 应始终与DBAPI游标是否具有 .description 属性,指示结果列的存在,注意返回零行的游标仍然具有 .description 如果发出行返回语句。

对于所有针对SELECT语句的结果以及使用RETURNING的DML语句INSERT/UPDATE/DELETE,此属性都应该为True。对于未使用RETURNING的INSERT/UPDATE/DELETE语句,该值通常为False,但是也存在一些特定于方言的异常,例如,当使用MSSQL/pyodbc方言时,为了检索插入的主键值,将内联发出SELECT。

attribute sqlalchemy.engine.BaseCursorResult.rowcount

返回此结果的“行数”。

“rowcount”报告行数 匹配的 按UPDATE或DELETE语句的WHERE条件。

注解

注意事项 CursorResult.rowcount

  • 此属性返回行数 匹配的 ,这不一定与实际的行数相同 被改进的 -例如,如果给定的设置值与行中已有的设置值相同,则UPDATE语句可能不会对给定行进行净更改。这样的行将被匹配,但不会被修改。在具有这两种样式(如mysql)的后端,默认情况下会将rowcount配置为在所有情况下返回匹配计数。

  • CursorResult.rowcountonly 与更新或删除语句一起使用。与python dbapi所说的相反,它确实做到了 not 返回select语句结果中可用的行数,因为dbapis在未缓冲行时不支持此功能。

  • CursorResult.rowcount 可能不是所有方言都能完全实现。尤其是,大多数DBAPI不支持来自ExecuteMany调用的聚合行计数结果。这个 CursorResult.supports_sane_rowcount()CursorResult.supports_sane_multi_rowcount() 如果已知支持每种用法,则方法将从方言报告。

  • 使用RETURN的语句可能不会返回正确的行数。

method sqlalchemy.engine.BaseCursorResult.supports_sane_multi_rowcount()

返回 supports_sane_multi_rowcount 来自方言。

CursorResult.rowcount 背景。

method sqlalchemy.engine.BaseCursorResult.supports_sane_rowcount()

返回 supports_sane_rowcount 来自方言。

CursorResult.rowcount 背景。

class sqlalchemy.engine.ChunkedIteratorResult(cursor_metadata, chunks, source_supports_scalars=False, raw=None, dynamic_yield_per=False)

IteratorResult 从迭代器产生可调用的。

给定的 chunks 参数是一个函数,该函数在每个块中指定要返回的行数,或者 None 对于所有行。然后函数应该返回一个未使用的列表迭代器,每个列表的大小都是请求的。

函数可以在任何时候再次调用,在这种情况下,它应该从同一个结果集继续,但是根据给定的结果调整块大小。

1.4 新版功能.

method sqlalchemy.engine.ChunkedIteratorResult.yield_per(num)

配置行获取策略以一次获取num行。

当迭代result对象时,或者使用诸如 Result.fetchone() 一次返回一行。来自底层游标或其他数据源的数据将被缓冲到内存中的这么多行,然后缓冲的集合将一次产生一行或请求多少行。每次清除缓冲区时,它都将被刷新到这么多行,或者如果剩余的行数较少,则会保留相同数量的行。

这个 Result.yield_per() 方法通常与 Connection.execution_options.stream_results execution选项,如果DBAPI支持,它将允许正在使用的数据库方言使用服务器端游标。

默认情况下,大多数dbapi不使用服务器端游标,这意味着所有行都将从数据库中提前获取,而不管 Result.yield_per() 设置。然而, Result.yield_per() 它可能仍然有用,因为它对来自数据库的原始数据进行SQLAlchemy端处理,另外,当用于ORM场景时,它还可以批量将数据库行转换为ORM实体行。

1.4 新版功能.

参数

num -- 每次重新填充缓冲区时要获取的行数。如果设置为小于1的值,则获取下一个缓冲区的所有行。

class sqlalchemy.engine.FrozenResult(result)

表示 Result 对象处于适合缓存的“冻结”状态。

这个 FrozenResult 对象从 Result.freeze() 任意方法 Result 对象。

一个新的迭代器 Result 对象是从一组固定的数据中生成的,每次 FrozenResult 作为可调用的::

result = connection.execute(query)

frozen = result.freeze()

unfrozen_result_one = frozen()

for row in unfrozen_result_one:
    print(row)

unfrozen_result_two = frozen()
rows = unfrozen_result_two.all()

# ... etc

1.4 新版功能.

参见

重新执行语句 -ORM中实现结果集缓存的示例用法。

merge_frozen_result() -ORM函数将冻结的结果合并回 Session .

class sqlalchemy.engine.IteratorResult(cursor_metadata, iterator, raw=None, _source_supports_scalars=False)

A Result 它从的Python迭代器获取数据 Row 物体。

1.4 新版功能.

class sqlalchemy.engine.LegacyRow(parent, processors, keymap, key_style, data)

一个子类 Row 它为核心提供了1.x SQLAlchemy行为。

这个 LegacyRow 类是为row对象实现大多数Python映射(即类似字典)行为的地方。的映射行为 Row 可通过 _mapping 属性。

1.4 新版功能: -增加的 LegacyRow 它封装了 Row .

method sqlalchemy.engine.LegacyRow.has_key(key)

如果这个返回真 LegacyRow 包含给定的密钥。

1.4 版后已移除: 这个 LegacyRow.has_key() 方法已弃用,将在将来的版本中删除。要测试密钥成员身份,请使用 Row._mapping 属性,即'key in row.u mapping`。

通过SQLAlchemy 1.x系列 __contains__() 方法 Row (或) LegacyRow 对于SQLAlchemy 1.4),还链接到 Row.has_key() ,其中一个表达式是::

"some_col" in row

如果行包含名为的列,则将返回True "some_col" ,以Python映射的工作方式。

然而,根据计划,SQLAlchemy的2.0系列将扭转这种行为,以便 __contains__() 将以Python元组的工作方式引用行中存在的值。

method sqlalchemy.engine.LegacyRow.items()

返回元组列表,每个元组包含一个键/值对。

1.4 版后已移除: 这个 LegacyRow.items() 方法已弃用,将在将来的版本中删除。使用 Row._mapping 属性,即'row_映射.items()'.

这个方法类似于Python字典 .items() 方法,但它返回一个列表,而不是迭代器。

method sqlalchemy.engine.LegacyRow.iterkeys()

返回一个针对 Row.keys() 方法。

1.4 版后已移除: 这个 LegacyRow.iterkeys() 方法已弃用,将在将来的版本中删除。使用 Row._mapping 属性,即'row_映射.keys()'.

此方法类似于Python-2-only字典 .iterkeys() 方法。

method sqlalchemy.engine.LegacyRow.itervalues()

返回一个针对 Row.values() 方法。

1.4 版后已移除: 这个 LegacyRow.itervalues() 方法已弃用,将在将来的版本中删除。使用 Row._mapping 属性,即'row_映射值()'.

此方法类似于Python-2-only字典 .itervalues() 方法。

method sqlalchemy.engine.LegacyRow.values()

返回 Row 作为一个列表。

1.4 版后已移除: 这个 LegacyRow.values() 方法已弃用,将在将来的版本中删除。使用 Row._mapping 属性,即'row_映射值()'.

这个方法类似于Python字典 .values() 方法,但它返回一个列表,而不是迭代器。

class sqlalchemy.engine.MergedResult(cursor_metadata, results)

A Result 从任何数量的 Result 物体。

Result.merge() 方法。

1.4 新版功能.

class sqlalchemy.engine.Result(cursor_metadata)

表示一组数据库结果。

1.4 新版功能: 这个 Result 对象为SQLAlchemy Core和SQLAlchemy ORM提供了一个完全更新的使用模型和调用facade。在核心,它构成了 CursorResult 对象替换上一个 ResultProxy 接口。当使用ORM时,一个更高级别的对象调用 ChunkedIteratorResult 通常使用。

注解

在SQLAlChemy 1.4及更高版本中,此对象用于由返回的ORM结果 Session.execute() ,它可以单独生成ORM映射对象的实例,也可以在类似元组的行内生成ORM映射对象的实例。请注意, Result 对象不会自动对实例或行执行重复数据消除,这与旧的 Query 对象。对于实例或行的Python内重复数据消除,请使用 Result.unique() 修饰符方法。

类签名

class sqlalchemy.engine.Result (sqlalchemy.engine._WithKeys, sqlalchemy.engine.ResultInternal)

method sqlalchemy.engine.Result.all()

返回列表中的所有行。

调用后关闭结果集。随后的调用将返回一个空列表。

1.4 新版功能.

返回

一览表 Row 物体。

method sqlalchemy.engine.Result.columns(*col_expressions)

建立每行中应返回的列。

此方法可用于限制返回的列以及对它们重新排序。给定的表达式列表通常是一系列整数或字符串键名。它们也可能是适当的 ColumnElement 与给定语句构造相对应的对象。

例如。::

statement = select(table.c.x, table.c.y, table.c.z)
result = connection.execute(statement)

for z, y in result.columns('z', 'y'):
    # ...

从语句本身使用列对象的示例:

for z, y in result.columns(
        statement.selected_columns.c.z,
        statement.selected_columns.c.y
):
    # ...

1.4 新版功能.

参数

*col_expressions -- 指示要返回的列。元素可以是整数行索引、字符串列名或适当的 ColumnElement 与select构造相对应的对象。

返回

Result 对象进行了修改。

method sqlalchemy.engine.Result.fetchall()

的同义词 Result.all() 方法。

method sqlalchemy.engine.Result.fetchmany(size=None)

取许多行。

当所有行都用完时,返回一个空列表。

与AlchemY.1.1兼容。

要获取组中的行,请使用 Result.partitions() 方法。

返回

一览表 Row 物体。

method sqlalchemy.engine.Result.fetchone()

取一行。

当所有行都用完时,返回None。

与AlchemY.1.1兼容。

要只获取结果的第一行,请使用 Result.first() 方法。要遍历所有行,请迭代 Result 直接对象。

返回

Row 对象(如果未应用筛选器),或者如果没有保留行,则为无。

method sqlalchemy.engine.Result.first()

获取第一行,如果没有行,则不获取。

关闭结果集并丢弃其余行。

注解

此方法返回一个 row ,例如,默认情况下是元组。要只返回一个标量值,即第一行的第一列,请使用 Result.scalar() 方法或组合 Result.scalars()Result.first() .

此外,与遗留ORM的行为形成对比的是 Query.first() 方法, 不应用任何限制 添加到调用的SQL查询,以生成此 Result ;对于在生成行之前在内存中缓冲结果的DBAPI驱动程序,所有行都将被发送到Python进程,除第一行之外的所有行都将被丢弃。

返回

Row 对象,如果没有行保留,则无。

method sqlalchemy.engine.Result.freeze()

返回一个可调用的对象,该对象将生成此 Result 当被调用时。

返回的可调用对象是 FrozenResult .

这用于结果集缓存。当结果尚未使用时,必须对其调用该方法,而调用该方法将完全消耗结果。当 FrozenResult 从缓存中检索时,可以多次调用它,其中它将生成一个新的 Result 对象每次针对其存储的行集。

参见

重新执行语句 -ORM中实现结果集缓存的示例用法。

method sqlalchemy.engine.Result.keys()

inherited from the sqlalchemy.engine._WithKeys.keys method of sqlalchemy.engine._WithKeys

返回一个iterable视图,该视图生成由每个键表示的字符串键 Row .

键可以表示核心语句返回的列的标签或orm执行返回的orm类的名称。

还可以使用Python测试视图的密钥包含 in 运算符,它将测试视图中表示的字符串键以及可选键(如列对象)。

在 1.4 版更改: 返回键视图对象而不是纯列表。

method sqlalchemy.engine.Result.mappings()

对返回的行应用映射筛选器,返回 MappingResult .

应用此筛选器时,获取行将返回 RowMapping 对象而不是 Row 物体。

1.4 新版功能.

返回

一个新的 MappingResult 引用此的筛选对象 Result 对象。

method sqlalchemy.engine.Result.merge(*others)

合并此 Result 与其他兼容的结果对象。

返回的对象是的实例 MergedResult 给定的迭代器将由以下对象组成。

新结果将使用此结果对象中的元数据。后续的结果对象必须针对相同的结果/游标元数据集,否则行为未定义。

method sqlalchemy.engine.Result.one()

只返回一行或引发异常。

加薪 NoResultFound 如果结果没有返回行,或者 MultipleResultsFound 如果返回多行。

注解

此方法返回一个 row ,例如,默认情况下是元组。要只返回一个标量值,即第一行的第一列,请使用 Result.scalar_one() 方法或组合 Result.scalars()Result.one() .

1.4 新版功能.

返回

第一 Row .

加薪

MultipleResultsFound, NoResultFound

method sqlalchemy.engine.Result.one_or_none()

最多返回一个结果或引发异常。

返回 None 如果结果没有行。加薪 MultipleResultsFound 如果返回多行。

1.4 新版功能.

返回

第一 Row 如果没有行可用,则无。

加薪

MultipleResultsFound

method sqlalchemy.engine.Result.partitions(size=None)

迭代给定大小的行的子列表。

每个列表的大小都是给定的,不包括要生成的最后一个列表,该列表可能只有少量的行。不会产生空列表。

当迭代器被完全使用时,result对象将自动关闭。

注意,后端驱动程序通常会提前缓冲整个结果,除非 Connection.execution_options.stream_results 如果可能,使用execution选项指示驱动程序不应预缓冲结果。并非所有驱动程序都支持此选项,对于不支持此选项的驱动程序,该选项将被忽略。

1.4 新版功能.

参数

size -- 指示生成的每个列表中要显示的最大行数。如果没有,则使用由设置的值 Result.yield_per() ,否则使用 Result.fetchmany() 可能是后端特定的默认值。

返回

列表迭代器

method sqlalchemy.engine.Result.scalar()

获取第一行的第一列,并关闭结果集。

如果没有要获取的行,则返回None。

不执行验证来测试是否还有其他行。

调用此方法后,对象将完全关闭,例如 CursorResult.close() 将调用方法。

返回

Python标量值,如果没有行保留,则为无。

method sqlalchemy.engine.Result.scalar_one()

只返回一个标量结果或引发异常。

这相当于调用 Result.scalars() 然后 Result.one()

method sqlalchemy.engine.Result.scalar_one_or_none()

只返回一个或不返回标量结果。

这相当于调用 Result.scalars() 然后 Result.one_or_none()

method sqlalchemy.engine.Result.scalars(index=0)

返回A ScalarResult 将返回单个元素而不是 Row 物体。

例如。::

>>> result = conn.execute(text("select int_id from table"))
>>> result.scalars().all()
[1, 2, 3]

当从 ScalarResult 筛选对象,将由 Result 而是作为列的值返回。

1.4 新版功能.

参数

index -- 整数或行键,指示要从每行提取的列,默认为 0 表示第一列。

返回

一个新的 ScalarResult 引用此的筛选对象 Result 对象。

method sqlalchemy.engine.Result.unique(strategy=None)

对此返回的对象应用唯一筛选 Result .

当不带参数应用此筛选器时,将对返回的行或对象进行筛选,以使每一行都返回唯一。默认情况下,用于确定这种唯一性的算法是整个元组的Python散列标识。在某些情况下,可以使用专门的每个实体散列方案,例如在使用ORM时,会应用一个方案,该方案针对返回对象的主键标识。

将应用唯一筛选器 在所有其他过滤器之后 ,这意味着如果已使用诸如 Result.columns()Result.scalars() 方法,将uniquing应用于 只返回一个或多个列 . 无论调用这些方法的顺序如何,都会发生这种情况 Result 对象。

独特的过滤器还改变了用于以下方法的微积分 Result.fetchmany()Result.partitions() . 使用时 Result.unique() ,在应用uniquing之后,这些方法将继续生成请求的行数或对象数。但是,这必然会影响底层游标或数据源的缓冲行为,这样多个底层调用 cursor.fetchmany() 可能需要积累足够的对象,以便提供所需大小的唯一集合。

参数

strategy -- 将应用于正在迭代的行或对象的可调用的,它应返回表示行的唯一值的对象。 Python set() 用于存储这些标识。如果未通过,则使用默认的唯一性策略,该策略可能已由此源组装 Result 对象。

method sqlalchemy.engine.Result.yield_per(num)

配置行获取策略以一次获取num行。

当迭代result对象时,或者使用诸如 Result.fetchone() 一次返回一行。来自底层游标或其他数据源的数据将被缓冲到内存中的这么多行,然后缓冲的集合将一次产生一行或请求多少行。每次清除缓冲区时,它都将被刷新到这么多行,或者如果剩余的行数较少,则会保留相同数量的行。

这个 Result.yield_per() 方法通常与 Connection.execution_options.stream_results execution选项,如果DBAPI支持,它将允许正在使用的数据库方言使用服务器端游标。

默认情况下,大多数dbapi不使用服务器端游标,这意味着所有行都将从数据库中提前获取,而不管 Result.yield_per() 设置。然而, Result.yield_per() 它可能仍然有用,因为它对来自数据库的原始数据进行SQLAlchemy端处理,另外,当用于ORM场景时,它还可以批量将数据库行转换为ORM实体行。

1.4 新版功能.

参数

num -- 每次重新填充缓冲区时要获取的行数。如果设置为小于1的值,则获取下一个缓冲区的所有行。

class sqlalchemy.engine.ScalarResult(real_result, index)

包装纸 Result 返回标量值而不是 Row 价值观。

这个 ScalarResult 对象是通过调用 Result.scalars() 方法。

对…的特殊限制 ScalarResult 它没有 fetchone() 方法;因为 fetchone() 是那个吗 None 值表示没有其他结果,这与不兼容 ScalarResult 因为没有办法区分 None 作为行值与 None 作为一个指标。使用 next(result) 单独接收值。

类签名

class sqlalchemy.engine.ScalarResult (sqlalchemy.engine.FilterResult)

method sqlalchemy.engine.ScalarResult.all()

返回列表中的所有标量值。

相当于 Result.all() 除了标量值,而不是 Row 对象,则返回。

method sqlalchemy.engine.ScalarResult.fetchall()

的同义词 ScalarResult.all() 方法。

method sqlalchemy.engine.ScalarResult.fetchmany(size=None)

获取许多对象。

相当于 Result.fetchmany() 除了标量值,而不是 Row 对象,则返回。

method sqlalchemy.engine.ScalarResult.first()

获取第一个对象,如果没有对象,则不获取。

相当于 Result.first() 除了标量值,而不是 Row 对象,则返回。

method sqlalchemy.engine.ScalarResult.one()

只返回一个对象或引发异常。

相当于 Result.one() 除了标量值,而不是 Row 对象,则返回。

method sqlalchemy.engine.ScalarResult.one_or_none()

最多返回一个对象或引发异常。

相当于 Result.one_or_none() 除了标量值,而不是 Row 对象,则返回。

method sqlalchemy.engine.ScalarResult.partitions(size=None)

迭代给定大小的元素的子列表。

相当于 Result.partitions() 除了标量值,而不是 Row 对象,则返回。

method sqlalchemy.engine.ScalarResult.unique(strategy=None)

对此返回的对象应用唯一筛选 ScalarResult .

Result.unique() 有关用法的详细信息。

class sqlalchemy.engine.MappingResult(result)

包装纸 Result 返回字典值而不是 Row 价值观。

这个 MappingResult 对象是通过调用 Result.mappings() 方法。

类签名

class sqlalchemy.engine.MappingResult (sqlalchemy.engine._WithKeys, sqlalchemy.engine.FilterResult)

method sqlalchemy.engine.MappingResult.all()

返回列表中的所有标量值。

相当于 Result.all() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.columns(*col_expressions)

建立每行中应返回的列。

method sqlalchemy.engine.MappingResult.fetchall()

的同义词 MappingResult.all() 方法。

method sqlalchemy.engine.MappingResult.fetchmany(size=None)

获取许多对象。

相当于 Result.fetchmany() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.fetchone()

取一个对象。

相当于 Result.fetchone() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.first()

获取第一个对象,如果没有对象,则不获取。

相当于 Result.first() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.keys()

inherited from the sqlalchemy.engine._WithKeys.keys method of sqlalchemy.engine._WithKeys

返回一个iterable视图,该视图生成由每个键表示的字符串键 Row .

键可以表示核心语句返回的列的标签或orm执行返回的orm类的名称。

还可以使用Python测试视图的密钥包含 in 运算符,它将测试视图中表示的字符串键以及可选键(如列对象)。

在 1.4 版更改: 返回键视图对象而不是纯列表。

method sqlalchemy.engine.MappingResult.one()

只返回一个对象或引发异常。

相当于 Result.one() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.one_or_none()

最多返回一个对象或引发异常。

相当于 Result.one_or_none() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.partitions(size=None)

迭代给定大小的元素的子列表。

相当于 Result.partitions() 除了映射值,而不是 Row 对象,则返回。

method sqlalchemy.engine.MappingResult.unique(strategy=None)

对此返回的对象应用唯一筛选 MappingResult .

Result.unique() 有关用法的详细信息。

class sqlalchemy.engine.CursorResult(context, cursor_strategy, cursor_description)

表示DBAPI游标状态的结果。

在 1.4 版更改: 这个 CursorResultLegacyCursorResult 类替换以前的 ResultProxy 接口。这些类基于 Result 调用提供更新的使用模型的API,并调用SQLAlchemy Core和SQLAlchemy ORM的facade。

通过返回数据库行 Row 类,它在DBAPI返回的原始数据的基础上提供附加的API特性和行为。通过使用诸如 Result.scalars() 方法,也可以返回其他类型的对象。

在SQLAlchemy 1.x系列的范围内,1.4版的核心SQL结果返回 LegacyCursorResult 它代替了 CursorResult 类用于1.3系列及以前版本。此对象将行返回为 LegacyRow 对象,它在对象本身上维护类似Python映射(即字典)的行为。向前看 Row._mapping 属性应用于字典行为。

参见

选择 -使用入门材料 CursorResultRow 物体。

method sqlalchemy.engine.CursorResult.all()

inherited from the Result.all() method of Result

返回列表中的所有行。

调用后关闭结果集。随后的调用将返回一个空列表。

1.4 新版功能.

返回

一览表 Row 物体。

method sqlalchemy.engine.CursorResult.close()

关闭此 CursorResult .

这将关闭与语句执行相对应的基础DBAPI光标(如果仍存在)。注意,当 CursorResult 排出所有可用的行。 CursorResult.close() 通常是可选方法,除非在丢弃 CursorResult 还有其他行等待提取。

调用此方法后,调用将引发 ResourceClosedError 以后使用时。

method sqlalchemy.engine.CursorResult.columns(*col_expressions)

inherited from the Result.columns() method of Result

建立每行中应返回的列。

此方法可用于限制返回的列以及对它们重新排序。给定的表达式列表通常是一系列整数或字符串键名。它们也可能是适当的 ColumnElement 与给定语句构造相对应的对象。

例如。::

statement = select(table.c.x, table.c.y, table.c.z)
result = connection.execute(statement)

for z, y in result.columns('z', 'y'):
    # ...

从语句本身使用列对象的示例:

for z, y in result.columns(
        statement.selected_columns.c.z,
        statement.selected_columns.c.y
):
    # ...

1.4 新版功能.

参数

*col_expressions -- 指示要返回的列。元素可以是整数行索引、字符串列名或适当的 ColumnElement 与select构造相对应的对象。

返回

Result 对象进行了修改。

method sqlalchemy.engine.CursorResult.fetchall()

inherited from the Result.fetchall() method of Result

的同义词 Result.all() 方法。

method sqlalchemy.engine.CursorResult.fetchmany(size=None)

inherited from the Result.fetchmany() method of Result

取许多行。

当所有行都用完时,返回一个空列表。

与AlchemY.1.1兼容。

要获取组中的行,请使用 Result.partitions() 方法。

返回

一览表 Row 物体。

method sqlalchemy.engine.CursorResult.fetchone()

inherited from the Result.fetchone() method of Result

取一行。

当所有行都用完时,返回None。

与AlchemY.1.1兼容。

要只获取结果的第一行,请使用 Result.first() 方法。要遍历所有行,请迭代 Result 直接对象。

返回

Row 对象(如果未应用筛选器),或者如果没有保留行,则为无。

method sqlalchemy.engine.CursorResult.first()

inherited from the Result.first() method of Result

获取第一行,如果没有行,则不获取。

关闭结果集并丢弃其余行。

注解

此方法返回一个 row ,例如,默认情况下是元组。要只返回一个标量值,即第一行的第一列,请使用 Result.scalar() 方法或组合 Result.scalars()Result.first() .

此外,与遗留ORM的行为形成对比的是 Query.first() 方法, 不应用任何限制 添加到调用的SQL查询,以生成此 Result ;对于在生成行之前在内存中缓冲结果的DBAPI驱动程序,所有行都将被发送到Python进程,除第一行之外的所有行都将被丢弃。

返回

Row 对象,如果没有行保留,则无。

method sqlalchemy.engine.CursorResult.freeze()

inherited from the Result.freeze() method of Result

返回一个可调用的对象,该对象将生成此 Result 当被调用时。

返回的可调用对象是 FrozenResult .

这用于结果集缓存。当结果尚未使用时,必须对其调用该方法,而调用该方法将完全消耗结果。当 FrozenResult 从缓存中检索时,可以多次调用它,其中它将生成一个新的 Result 对象每次针对其存储的行集。

参见

重新执行语句 -ORM中实现结果集缓存的示例用法。

attribute sqlalchemy.engine.CursorResult.inserted_primary_key

返回刚刚插入的行的主键。

返回值为 Row 对象,该对象按照主键列在源中的配置顺序表示主键值的命名元组 Table

在 1.4.8 版更改: -The CursorResult.inserted_primary_key 值现在是一个命名元组,通过 Row 类,而不是纯元组。

此访问器仅适用于单行 insert() 未显式指定的构造 Insert.returning() 。虽然对多行插入的支持对大多数后端都不可用,但可以使用 CursorResult.inserted_primary_key_rows 访问者。

请注意,指定server_default子句的主键列或其他列不符合“autoincrement”列的条件(请参阅中的注释 Column ,并且是使用数据库端默认值生成的,将在此列表中显示为 None 除非后端支持“返回”,并且在启用“隐式返回”的情况下执行insert语句。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造或不是insert()构造。

attribute sqlalchemy.engine.CursorResult.inserted_primary_key_rows

返回的值 CursorResult.inserted_primary_key 作为列表中包含的一行;某些方言也可能支持多行形式。

注解

如下所示,在当前的SQLAlChemy版本中,此访问器仅在已提供的功能之外才有用 CursorResult.inserted_primary_key 在使用 PycPcG2 方言。未来的版本希望将此功能推广到更多的方言。

添加此访问器是为了支持提供当前由 Psycopg2快速执行助手 功能,当前 只有mental copg2方言 ,它允许一次插入许多行,同时仍然保留能够返回服务器生成的主键值的行为。

  • 在即将发布的版本中使用mental copg2方言或其他可能支持“Fast Executemany”样式插入的方言时 : When invoking an INSERT statement while passing a list of rows as the second argument to Connection.execute() ,则此访问器将提供行列表,其中每行都包含插入的每行的主键值。

  • When using all other dialects / backends that don't yet support this feature :此访问器仅适用于 单行INSERT语句 ,并返回与 CursorResult.inserted_primary_key 在单个元素列表中。当INSERT语句与要插入的行列表一起执行时,该列表将包含语句中插入的每行一行,但是它将包含 None 用于任何服务器生成的值。

SQLAlChemy的未来版本将进一步概括mental copg2的“快速执行帮助器”特性,以适应其他方言,从而允许该访问器具有更广泛的用途。

1.4 新版功能.

attribute sqlalchemy.engine.CursorResult.is_insert

inherited from the BaseCursorResult.is_insert attribute of BaseCursorResult

如果这是真的 CursorResult 是执行已编译的表达式语言的结果 insert() 构造。

如果是真的,这意味着 inserted_primary_key 属性是可访问的,假定语句不包含用户定义的“返回”构造。

method sqlalchemy.engine.CursorResult.keys()

inherited from the sqlalchemy.engine._WithKeys.keys method of sqlalchemy.engine._WithKeys

返回一个iterable视图,该视图生成由每个键表示的字符串键 Row .

键可以表示核心语句返回的列的标签或orm执行返回的orm类的名称。

还可以使用Python测试视图的密钥包含 in 运算符,它将测试视图中表示的字符串键以及可选键(如列对象)。

在 1.4 版更改: 返回键视图对象而不是纯列表。

method sqlalchemy.engine.CursorResult.last_inserted_params()

返回此执行中插入参数的集合。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造或不是insert()构造。

method sqlalchemy.engine.CursorResult.last_updated_params()

返回此执行中更新参数的集合。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造或不是update()构造。

method sqlalchemy.engine.CursorResult.lastrow_has_defaults()

返回 lastrow_has_defaults() 从底层 ExecutionContext .

ExecutionContext 有关详细信息。

attribute sqlalchemy.engine.CursorResult.lastrowid

inherited from the BaseCursorResult.lastrowid attribute of BaseCursorResult

返回DBAPI游标上的“lastrowid”访问器。

这是一种特定于DBAPI的方法,仅对支持它的后端和适当的语句有效。它的行为在后端不一致。

在使用insert()表达式构造时,通常不需要使用此方法;在 CursorResult.inserted_primary_key 属性为新插入的行提供主键值的元组,而不考虑数据库后端。

method sqlalchemy.engine.CursorResult.mappings()

inherited from the Result.mappings() method of Result

对返回的行应用映射筛选器,返回 MappingResult .

应用此筛选器时,获取行将返回 RowMapping 对象而不是 Row 物体。

1.4 新版功能.

返回

一个新的 MappingResult 引用此的筛选对象 Result 对象。

method sqlalchemy.engine.CursorResult.merge(*others)

合并此 Result 与其他兼容的结果对象。

返回的对象是的实例 MergedResult 给定的迭代器将由以下对象组成。

新结果将使用此结果对象中的元数据。后续的结果对象必须针对相同的结果/游标元数据集,否则行为未定义。

method sqlalchemy.engine.CursorResult.one()

inherited from the Result.one() method of Result

只返回一行或引发异常。

加薪 NoResultFound 如果结果没有返回行,或者 MultipleResultsFound 如果返回多行。

注解

此方法返回一个 row ,例如,默认情况下是元组。要只返回一个标量值,即第一行的第一列,请使用 Result.scalar_one() 方法或组合 Result.scalars()Result.one() .

1.4 新版功能.

返回

第一 Row .

加薪

MultipleResultsFound, NoResultFound

method sqlalchemy.engine.CursorResult.one_or_none()

inherited from the Result.one_or_none() method of Result

最多返回一个结果或引发异常。

返回 None 如果结果没有行。加薪 MultipleResultsFound 如果返回多行。

1.4 新版功能.

返回

第一 Row 如果没有行可用,则无。

加薪

MultipleResultsFound

method sqlalchemy.engine.CursorResult.partitions(size=None)

inherited from the Result.partitions() method of Result

迭代给定大小的行的子列表。

每个列表的大小都是给定的,不包括要生成的最后一个列表,该列表可能只有少量的行。不会产生空列表。

当迭代器被完全使用时,result对象将自动关闭。

注意,后端驱动程序通常会提前缓冲整个结果,除非 Connection.execution_options.stream_results 如果可能,使用execution选项指示驱动程序不应预缓冲结果。并非所有驱动程序都支持此选项,对于不支持此选项的驱动程序,该选项将被忽略。

1.4 新版功能.

参数

size -- 指示生成的每个列表中要显示的最大行数。如果没有,则使用由设置的值 Result.yield_per() ,否则使用 Result.fetchmany() 可能是后端特定的默认值。

返回

列表迭代器

method sqlalchemy.engine.CursorResult.postfetch_cols()

返回 postfetch_cols() 从底层 ExecutionContext .

ExecutionContext 有关详细信息。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造,或者不是insert()或update()构造。

method sqlalchemy.engine.CursorResult.prefetch_cols()

inherited from the BaseCursorResult.prefetch_cols() method of BaseCursorResult

返回 prefetch_cols() 从底层 ExecutionContext .

ExecutionContext 有关详细信息。

加薪 InvalidRequestError 如果执行的语句不是已编译的表达式构造,或者不是insert()或update()构造。

attribute sqlalchemy.engine.CursorResult.returned_defaults

inherited from the BaseCursorResult.returned_defaults attribute of BaseCursorResult

返回使用 ValuesBase.return_defaults() 特征。

该值是的实例 RowNone 如果 ValuesBase.return_defaults() 未使用或后端不支持返回。

0.9.0 新版功能.

attribute sqlalchemy.engine.CursorResult.returned_defaults_rows

返回一个行列表,每个行包含使用 ValuesBase.return_defaults() 特征。

返回值是 Row 物体。

1.4 新版功能.

attribute sqlalchemy.engine.CursorResult.returns_rows

inherited from the BaseCursorResult.returns_rows attribute of BaseCursorResult

如果这是真的 CursorResult 返回零行或更多行。

也就是说,如果调用这些方法是合法的 CursorResult.fetchone()CursorResult.fetchmany() CursorResult.fetchall() .

总的来说 CursorResult.returns_rows 应始终与DBAPI游标是否具有 .description 属性,指示结果列的存在,注意返回零行的游标仍然具有 .description 如果发出行返回语句。

对于所有针对SELECT语句的结果以及使用RETURNING的DML语句INSERT/UPDATE/DELETE,此属性都应该为True。对于未使用RETURNING的INSERT/UPDATE/DELETE语句,该值通常为False,但是也存在一些特定于方言的异常,例如,当使用MSSQL/pyodbc方言时,为了检索插入的主键值,将内联发出SELECT。

attribute sqlalchemy.engine.CursorResult.rowcount

inherited from the BaseCursorResult.rowcount attribute of BaseCursorResult

返回此结果的“行数”。

“rowcount”报告行数 匹配的 按UPDATE或DELETE语句的WHERE条件。

注解

注意事项 CursorResult.rowcount

  • 此属性返回行数 匹配的 ,这不一定与实际的行数相同 被改进的 -例如,如果给定的设置值与行中已有的设置值相同,则UPDATE语句可能不会对给定行进行净更改。这样的行将被匹配,但不会被修改。在具有这两种样式(如mysql)的后端,默认情况下会将rowcount配置为在所有情况下返回匹配计数。

  • CursorResult.rowcountonly 与更新或删除语句一起使用。与python dbapi所说的相反,它确实做到了 not 返回select语句结果中可用的行数,因为dbapis在未缓冲行时不支持此功能。

  • CursorResult.rowcount 可能不是所有方言都能完全实现。尤其是,大多数DBAPI不支持来自ExecuteMany调用的聚合行计数结果。这个 CursorResult.supports_sane_rowcount()CursorResult.supports_sane_multi_rowcount() 如果已知支持每种用法,则方法将从方言报告。

  • 使用RETURN的语句可能不会返回正确的行数。

method sqlalchemy.engine.CursorResult.scalar()

inherited from the Result.scalar() method of Result

获取第一行的第一列,并关闭结果集。

如果没有要获取的行,则返回None。

不执行验证来测试是否还有其他行。

调用此方法后,对象将完全关闭,例如 CursorResult.close() 将调用方法。

返回

Python标量值,如果没有行保留,则为无。

method sqlalchemy.engine.CursorResult.scalar_one()

inherited from the Result.scalar_one() method of Result

只返回一个标量结果或引发异常。

这相当于调用 Result.scalars() 然后 Result.one()

method sqlalchemy.engine.CursorResult.scalar_one_or_none()

inherited from the Result.scalar_one_or_none() method of Result

只返回一个或不返回标量结果。

这相当于调用 Result.scalars() 然后 Result.one_or_none()

method sqlalchemy.engine.CursorResult.scalars(index=0)

inherited from the Result.scalars() method of Result

返回A ScalarResult 将返回单个元素而不是 Row 物体。

例如。::

>>> result = conn.execute(text("select int_id from table"))
>>> result.scalars().all()
[1, 2, 3]

当从 ScalarResult 筛选对象,将由 Result 而是作为列的值返回。

1.4 新版功能.

参数

index -- 整数或行键,指示要从每行提取的列,默认为 0 表示第一列。

返回

一个新的 ScalarResult 引用此的筛选对象 Result 对象。

method sqlalchemy.engine.CursorResult.supports_sane_multi_rowcount()

返回 supports_sane_multi_rowcount 来自方言。

CursorResult.rowcount 背景。

method sqlalchemy.engine.CursorResult.supports_sane_rowcount()

返回 supports_sane_rowcount 来自方言。

CursorResult.rowcount 背景。

method sqlalchemy.engine.CursorResult.unique(strategy=None)

inherited from the Result.unique() method of Result

对此返回的对象应用唯一筛选 Result .

当不带参数应用此筛选器时,将对返回的行或对象进行筛选,以使每一行都返回唯一。默认情况下,用于确定这种唯一性的算法是整个元组的Python散列标识。在某些情况下,可以使用专门的每个实体散列方案,例如在使用ORM时,会应用一个方案,该方案针对返回对象的主键标识。

将应用唯一筛选器 在所有其他过滤器之后 ,这意味着如果已使用诸如 Result.columns()Result.scalars() 方法,将uniquing应用于 只返回一个或多个列 . 无论调用这些方法的顺序如何,都会发生这种情况 Result 对象。

独特的过滤器还改变了用于以下方法的微积分 Result.fetchmany()Result.partitions() . 使用时 Result.unique() ,在应用uniquing之后,这些方法将继续生成请求的行数或对象数。但是,这必然会影响底层游标或数据源的缓冲行为,这样多个底层调用 cursor.fetchmany() 可能需要积累足够的对象,以便提供所需大小的唯一集合。

参数

strategy -- 将应用于正在迭代的行或对象的可调用的,它应返回表示行的唯一值的对象。 Python set() 用于存储这些标识。如果未通过,则使用默认的唯一性策略,该策略可能已由此源组装 Result 对象。

method sqlalchemy.engine.CursorResult.yield_per(num)

配置行获取策略以一次获取num行。

当迭代result对象时,或者使用诸如 Result.fetchone() 一次返回一行。来自底层游标或其他数据源的数据将被缓冲到内存中的这么多行,然后缓冲的集合将一次产生一行或请求多少行。每次清除缓冲区时,它都将被刷新到这么多行,或者如果剩余的行数较少,则会保留相同数量的行。

这个 Result.yield_per() 方法通常与 Connection.execution_options.stream_results execution选项,如果DBAPI支持,它将允许正在使用的数据库方言使用服务器端游标。

默认情况下,大多数dbapi不使用服务器端游标,这意味着所有行都将从数据库中提前获取,而不管 Result.yield_per() 设置。然而, Result.yield_per() 它可能仍然有用,因为它对来自数据库的原始数据进行SQLAlchemy端处理,另外,当用于ORM场景时,它还可以批量将数据库行转换为ORM实体行。

1.4 新版功能.

参数

num -- 每次重新填充缓冲区时要获取的行数。如果设置为小于1的值,则获取下一个缓冲区的所有行。

class sqlalchemy.engine.LegacyCursorResult(context, cursor_strategy, cursor_description)

的旧版本 CursorResult .

此类包括用于“无连接”执行的连接“连接自动关闭”行为,以及使用 LegacyRow 行实现。

1.4 新版功能.

method sqlalchemy.engine.LegacyCursorResult.close()

关闭此 LegacyCursorResult .

此方法的行为与的相同 sqlalchemy.engine.CursorResult() 但它也可能关闭潜在的 Connection 对于“无连接”执行的情况。

2.0 版后已移除: “无连接”执行已弃用,将在版本2.0中删除。版本2.0将具有 Result 对象,该对象在任何情况下都不会再影响原始连接的状态。

调用此方法后,调用将引发 ResourceClosedError 以后使用时。

class sqlalchemy.engine.Row(parent, processors, keymap, key_style, data)

表示单个结果行。

这个 Row 对象表示数据库结果的一行。它通常在SQLAlchemy的1.x系列中与 CursorResult 对象,但是,从SQLAlchemy 1.4开始,ORM也将其用于类似元组的结果。

这个 Row 对象的作用尽可能类似于名为tuple的Python。对于映射(即字典)行上的行为,例如测试键的包含,请参阅 Row._mapping 属性。

参见

选择 -包括从SELECT语句中选择行的示例。

LegacyRow -SQLAlchemy 1.4中引入的兼容性接口。

在 1.4 版更改: 更名 RowProxyRow . Row 不再是一个“代理”对象,因为它包含最终形式的数据,现在的行为基本上类似于命名元组。类似映射的功能被移动到 Row._mapping 属性,但将通过 LegacyRow 由使用的类 LegacyCursorResult . 见 RowProxy不再是“代理”;现在称为Row,其行为类似于增强的命名元组 关于这个变化的背景。

类签名

class sqlalchemy.engine.Row (sqlalchemy.engine.BaseRow, collections.abc.Sequence)

method sqlalchemy.engine.Row._asdict()

返回将字段名映射到其相应值的新字典。

此方法类似于名为tuple的Python ._asdict() 方法,并通过应用 dict() 构造函数添加到 Row._mapping 属性。

1.4 新版功能.

参见

Row._mapping

attribute sqlalchemy.engine.Row._fields

返回字符串键的元组,如 Row .

键可以表示核心语句返回的列的标签或orm执行返回的orm类的名称。

这个属性类似于名为tuple的Python ._fields 属性。

1.4 新版功能.

参见

Row._mapping

attribute sqlalchemy.engine.Row._mapping

返回A RowMapping 为此 Row .

此对象为行中包含的数据提供一致的Python映射(即dictionary)接口。这个 Row 它本身的行为类似于命名元组,但是在SQLAlchemy的1.4系列中 LegacyRow 类仍然由Core使用,它继续对row对象本身有类似映射的行为。

参见

Row._fields

1.4 新版功能.

attribute sqlalchemy.engine.Row.count
attribute sqlalchemy.engine.Row.index
method sqlalchemy.engine.Row.keys()

以字符串形式返回键列表 Row .

1.4 版后已移除: 这个 Row.keys() 方法在SQLAlchemy的1.x系列中被认为是遗留的,并将在2.0中删除。使用namedtuple标准访问器 Row._fields ,或对于完全映射行为,请使用row_映射.keys()(SQLAlchemy 2.0的背景: 迁移到Alchemy

键可以表示核心语句返回的列的标签或orm执行返回的orm类的名称。

这个方法类似于Python字典 .keys() 方法,但它返回一个列表,而不是迭代器。

class sqlalchemy.engine.RowMapping(parent, processors, keymap, key_style, data)

A Mapping 将列名和对象映射到 Row 价值观。

这个 RowMapping 可从 Row 通过 Row._mapping 属性提供的iterable接口 MappingResult 返回的对象 Result.mappings() 方法。

RowMapping 提供对行内容的Python映射(即字典)访问。这包括支持测试特定键(字符串列名或对象)的包含,以及键、值和项的迭代:

for row in result:
    if 'a' in row._mapping:
        print("Column 'a': %s" % row._mapping['a'])

    print("Column b: %s" % row._mapping[table.c.b])

1.4 新版功能: 这个 RowMapping 对象替换以前由数据库结果行提供的类似于映射的访问,现在该行的行为主要类似于命名元组。

类签名

class sqlalchemy.engine.RowMapping (sqlalchemy.engine.BaseRow, collections.abc.Mapping)

method sqlalchemy.engine.RowMapping.items()

返回底层元素的键/值元组的视图 Row .

method sqlalchemy.engine.RowMapping.keys()

返回由底层表示的字符串列名的“keys”视图 Row .

method sqlalchemy.engine.RowMapping.values()

返回底层中表示的值的值的视图 Row .

Previous: 引擎配置 Next: 连接池