SqlAlchemy 2.0 中文文档(五十一)(5)

简介: SqlAlchemy 2.0 中文文档(五十一)

SqlAlchemy 2.0 中文文档(五十一)(4)https://developer.aliyun.com/article/1563199


Unicode

对于 Python 3 下的所有 DBAPI,所有字符串都是本质上的 Unicode 字符串。然而,在所有情况下,驱动程序都需要明确的编码配置。

确保正确的客户端编码

几乎所有与 Oracle 相关的软件建立客户端编码的长期接受标准是通过NLS_LANG环境变量。cx_Oracle 像大多数其他 Oracle 驱动程序一样将使用此环境变量作为其编码配置的来源。此变量的格式是特殊的;典型值可能是AMERICAN_AMERICA.AL32UTF8

cx_Oracle 驱动程序还支持一种编程替代方案,即直接将encodingnencoding参数传递给其.connect()函数。这些可以在 URL 中如下所示:

engine = create_engine("oracle+cx_oracle://scott:tiger@orclpdb/?encoding=UTF-8&nencoding=UTF-8")

有关encodingnencoding参数的含义,请参阅字符集和国家语言支持(NLS)

另请参阅

在 cx_Oracle 文档中 字符集和国家语言支持 (NLS)

Unicode 特定的列数据类型

核心表达语言通过使用 UnicodeUnicodeText 数据类型处理 Unicode 数据。这些类型默认对应于 VARCHAR2 和 CLOB Oracle 数据类型。当使用这些数据类型处理 Unicode 数据时,期望 Oracle 数据库配置有 Unicode-aware 字符集,并且 NLS_LANG 环境变量已适当设置,以便 VARCHAR2 和 CLOB 数据类型能够容纳数据。

如果 Oracle 数据库未配置 Unicode 字符集,则有两种选择:显式使用 NCHARNCLOB 数据类型,或者在调用 create_engine() 时传递标志 use_nchar_for_unicode=True,这将导致 SQLAlchemy 方言使用 NCHAR/NCLOB 替代 VARCHAR/CLOB 用于 Unicode / UnicodeText 数据类型。

1.3 版本更改:UnicodeUnicodeText 数据类型现在默认对应于 VARCHAR2CLOB Oracle 数据类型,除非在调用 create_engine() 时传递了 use_nchar_for_unicode=True

编码错误

对于 Oracle 数据库中存在损坏编码的情况,方言接受一个参数 encoding_errors,该参数将传递给 Unicode 解码函数,以影响如何处理解码错误。该值最终由 Python decode 函数消耗,并且通过 cx_Oracle 的 encodingErrors 参数和 SQLAlchemy 自己的解码函数传递,因为在不同情况下 cx_Oracle 方言都会使用它们。

新版本 1.3.11 的新增功能:### 通过 setinputsizes 实现对 cx_Oracle 数据绑定性能的精细控制

cx_Oracle DBAPI 对 DBAPI setinputsizes() 调用具有深刻且基本的依赖关系。此调用的目的是为了为作为参数传递的 Python 值绑定到 SQL 语句的数据类型。虽然几乎没有其他 DBAPI 对setinputsizes()调用分配任何用途,但 cx_Oracle DBAPI 在与 Oracle 客户端接口的交互中严重依赖它,在某些情况下,SQLAlchemy 不可能知道数据应该如何绑定,因为某些设置可能导致完全不同的性能特征,同时还改变了类型强制转换行为。

使用 cx_Oracle 方言的用户强烈建议阅读 cx_Oracle 内置数据类型符号列表,网址为cx-oracle.readthedocs.io/en/latest/api_manual/module.html#database-types。请注意,在某些情况下,使用这些类型可能会导致显著的性能下降,尤其是在指定cx_Oracle.CLOB时。

在 SQLAlchemy 方面,可以使用DialectEvents.do_setinputsizes()事件来实现运行时可见性(例如日志记录)和完全控制每个语句上如何使用setinputsizes()

版本 1.2.9 中新增:添加了DialectEvents.setinputsizes()

示例 1 - 记录所有 setinputsizes 调用

下面的示例说明了如何在将其转换为原始setinputsizes()参数字典之前,从 SQLAlchemy 视角记录中间值。字典的键是具有.key.type属性的BindParameter对象:

from sqlalchemy import create_engine, event
engine = create_engine("oracle+cx_oracle://scott:tiger@host/xe")
@event.listens_for(engine, "do_setinputsizes")
def _log_setinputsizes(inputsizes, cursor, statement, parameters, context):
    for bindparam, dbapitype in inputsizes.items():
            log.info(
                "Bound parameter name: %s SQLAlchemy type: %r "
                "DBAPI object: %s",
                bindparam.key, bindparam.type, dbapitype)
示例 2 - 删除所有与 CLOB 的绑定

在 cx_Oracle 中,CLOB 数据类型会导致显著的性能开销,但在 SQLAlchemy 1.2 系列中默认为Text类型。可以按以下方式修改此设置:

from sqlalchemy import create_engine, event
from cx_Oracle import CLOB
engine = create_engine("oracle+cx_oracle://scott:tiger@host/xe")
@event.listens_for(engine, "do_setinputsizes")
def _remove_clob(inputsizes, cursor, statement, parameters, context):
    for bindparam, dbapitype in list(inputsizes.items()):
        if dbapitype is CLOB:
            del inputsizes[bindparam]
```### RETURNING 支持
cx_Oracle 方言使用 OUT 参数实现 RETURNING。该方言完全支持 RETURNING。### LOB 数据类型
LOB 数据类型指的是诸如 CLOB、NCLOB 和 BLOB 等“大对象”数据类型。cx_Oracle 和 oracledb 的现代版本经过优化,使得这些数据类型能够作为单个缓冲区传递。因此,默认情况下,SQLAlchemy 使用这些较新的类型处理程序。
要禁用较新的类型处理程序,并将 LOB 对象作为具有`read()`方法的经典缓冲对象传递,请将参数`auto_convert_lobs=False`传递给`create_engine()`,该参数仅对整个引擎生效。
### 不支持两阶段事务
由于驱动程序支持不佳,cx_Oracle 不支持两阶段事务。 从 cx_Oracle 6.0b1 开始,两阶段事务的接口已更改为更直接地通过底层 OCI 层进行传递,并减少了自动化。 支持此系统的附加逻辑未在 SQLAlchemy 中实现。
### 精确数字
SQLAlchemy 的数字类型可以将值作为 Python `Decimal` 对象或 float 对象接收和返回。 当使用 `Numeric` 对象或其子类(如 `Float`,`DOUBLE_PRECISION` 等)时, `Numeric.asdecimal` 标志决定是否应在返回时将值强制转换为 `Decimal`,或以 float 对象返回。 在 Oracle 下情况更加复杂,如果“scale”为零,Oracle 的 `NUMBER` 类型还可以表示整数值,因此 Oracle 特定的 `NUMBER` 类型也考虑了这一点。
cx_Oracle 方言广泛使用连接和游标级别的“outputtypehandler”可调用来根据需要强制转换数值。 这些可调用是针对正在使用的具体 `Numeric` 的特定风味的,以及如果不存在 SQLAlchemy 类型化对象。 已观察到的情况包括 Oracle 可能发送有关返回的数字类型的不完整或模糊信息的情况,例如查询,其中数字类型被嵌套在多个子查询的多个级别下。 类型处理程序在所有情况下都尽力做出正确的决定,在所有情况下都将决策委托给底层的 cx_Oracle DBAPI,以便在驱动程序可以做出最佳决策的所有情况下进行。
当不存在类型化对象时,例如在执行纯 SQL 字符串时,存在默认的“outputtypehandler”,该处理程序通常将指定精度和比例的数字值作为 Python `Decimal` 对象返回。 为了性能原因禁用此转换为十进制数的操作,请将标志 `coerce_to_decimal=False` 传递给 `create_engine()`:
```py
engine = create_engine("oracle+cx_oracle://dsn", coerce_to_decimal=False)

coerce_to_decimal 标志仅影响与 Numeric SQLAlchemy 类型(或其子类)无关联的纯字符串 SQL 语句的结果。

自 1.2 版本起进行了更改:cx_Oracle 的数字处理系统已经重写,以利用较新的 cx_Oracle 特性以及更好地集成输出类型处理程序。

DBAPI

cx-Oracle 的文档和下载信息(如适用)可在此处获取。

连接

连接字符串:

oracle+cx_oracle://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]

DSN vs. 主机名连接

cx_Oracle 提供了几种指示目标数据库的方法。方言将一系列不同的 URL 形式进行转换。

使用简易连接语法连接主机名

给定目标 Oracle 数据库的主机名、端口和服务名,例如来自 Oracle 的简易连接语法,然后在 SQLAlchemy 中使用service_name查询字符串参数进行连接:

engine = create_engine("oracle+cx_oracle://scott:tiger@hostname:port/?service_name=myservice&encoding=UTF-8&nencoding=UTF-8")

不支持完整的简易连接语法。而是使用tnsnames.ora文件,并使用 DSN 进行连接。

使用 tnsnames.ora 或 Oracle Cloud 进行连接

或者,如果未提供端口、数据库名称或service_name,则方言将使用 Oracle DSN “连接字符串”。这将 URL 的“主机名”部分作为数据源名称。例如,如果tnsnames.ora文件包含如下的网络服务名称myalias

myalias =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orclpdb1)
    )
  )

myalias是 URL 的主机名部分时,cx_Oracle 方言将连接到此数据库服务,而不指定端口、数据库名称或service_name

engine = create_engine("oracle+cx_oracle://scott:tiger@myalias/?encoding=UTF-8&nencoding=UTF-8")

Oracle Cloud 的用户应使用此语法,并按照 cx_Oracle 文档连接到 Autonomous 数据库中所示配置云钱包。

SID 连接

要使用 Oracle 的过时 SID 连接语法,可以如下传递 SID 在 URL 的“数据库名称”部分:

engine = create_engine("oracle+cx_oracle://scott:tiger@hostname:1521/dbname?encoding=UTF-8&nencoding=UTF-8")

在上述代码中,传递给 cx_Oracle 的 DSN 由cx_Oracle.makedsn()创建,如下所示:

>>> import cx_Oracle
>>> cx_Oracle.makedsn("hostname", 1521, sid="dbname")
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1521))(CONNECT_DATA=(SID=dbname)))'
使用简易连接语法连接主机名

给定目标 Oracle 数据库的主机名、端口和服务名,例如来自 Oracle 的简易连接语法,然后在 SQLAlchemy 中使用service_name查询字符串参数进行连接:

engine = create_engine("oracle+cx_oracle://scott:tiger@hostname:port/?service_name=myservice&encoding=UTF-8&nencoding=UTF-8")

不支持完整的简易连接语法。而是使用tnsnames.ora文件,并使用 DSN 进行连接。

使用 tnsnames.ora 或 Oracle Cloud 进行连接

或者,如果没有提供端口、数据库名称或service_name,则方言将使用 Oracle DSN “连接字符串”。这将 URL 的“主机名”部分作为数据源名称。例如,如果tnsnames.ora文件包含如下的网络服务名myalias

myalias =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.example.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orclpdb1)
    )
  )

myalias是 URL 的主机名部分时,cx_Oracle 方言将连接到此数据库服务,而不指定端口、数据库名称或service_name

engine = create_engine("oracle+cx_oracle://scott:tiger@myalias/?encoding=UTF-8&nencoding=UTF-8")

Oracle Cloud 的用户应使用此语法,并按照 cx_Oracle 文档中显示的方式配置云钱包连接到自主数据库

SID 连接

要使用 Oracle 的过时 SID 连接语法,SID 可以在 URL 的“数据库名称”部分中传递,如下所示:

engine = create_engine("oracle+cx_oracle://scott:tiger@hostname:1521/dbname?encoding=UTF-8&nencoding=UTF-8")

上面,传递给 cx_Oracle 的 DSN 是通过cx_Oracle.makedsn()创建的,如下所示:

>>> import cx_Oracle
>>> cx_Oracle.makedsn("hostname", 1521, sid="dbname")
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1521))(CONNECT_DATA=(SID=dbname)))'

传递 cx_Oracle 连接参数

通常可以通过 URL 查询字符串传递其他连接参数;像cx_Oracle.SYSDBA这样的特殊符号将被拦截并转换为正确的符号:

e = create_engine(
    "oracle+cx_oracle://user:pass@dsn?encoding=UTF-8&nencoding=UTF-8&mode=SYSDBA&events=true")

从版本 1.3 开始:cx_oracle 方言现在接受 URL 字符串中的所有参数名称,以传递给 cx_Oracle DBAPI。与早期情况相同但没有正确记录的是,create_engine.connect_args参数也接受所有 cx_Oracle DBAPI 连接参数。

要直接传递参数给.connect()而不使用查询字符串,请使用create_engine.connect_args字典。可以传递任何 cx_Oracle 参数值和/或常量,例如:

import cx_Oracle
e = create_engine(
    "oracle+cx_oracle://user:pass@dsn",
    connect_args={
        "encoding": "UTF-8",
        "nencoding": "UTF-8",
        "mode": cx_Oracle.SYSDBA,
        "events": True
    }
)

请注意,在 cx_Oracle 8.0 中,encodingnencoding的默认值已更改为“UTF-8”,因此在使用该版本或更高版本时可以省略这些参数。

SQLAlchemy cx_Oracle 方言在驱动程序之外消耗的选项

还有一些选项是由 SQLAlchemy cx_oracle 方言本身消耗的。这些选项始终直接传递给create_engine(),例如:

e = create_engine(
    "oracle+cx_oracle://user:pass@dsn", coerce_to_decimal=False)

cx_oracle 方言接受的参数如下:

  • arraysize - 设置光标上的 cx_oracle.arraysize 值;默认为None,表示应使用驱动程序的默认值(通常值为 100)。此设置控制在提取行时缓冲多少行,并且在修改时可能会对性能产生显着影响。该设置用于cx_Oracle以及oracledb
    改变版本 2.0.26:- 将默认值从 50 更改为 None,以使用驱动程序本身的默认值。
  • auto_convert_lobs - 默认为 True;请参阅 LOB 数据类型。
  • coerce_to_decimal - 详情请参阅精确数字。
  • encoding_errors - 详情请参阅编码错误。

使用 cx_Oracle SessionPool

cx_Oracle 库提供了自己的连接池实现,可以代替 SQLAlchemy 的池功能。这可以通过使用 create_engine.creator 参数提供一个返回新连接的函数,以及将 create_engine.pool_class 设置为 NullPool 来实现禁用 SQLAlchemy 的池:

import cx_Oracle
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool
pool = cx_Oracle.SessionPool(
    user="scott", password="tiger", dsn="orclpdb",
    min=2, max=5, increment=1, threaded=True,
    encoding="UTF-8", nencoding="UTF-8"
)
engine = create_engine("oracle+cx_oracle://", creator=pool.acquire, poolclass=NullPool)

然后可以正常使用上述引擎,其中 cx_Oracle 的池处理连接池:

with engine.connect() as conn:
    print(conn.scalar("select 1 FROM dual"))

除了为多用户应用程序提供可扩展的解决方案外,cx_Oracle 会话池还支持一些 Oracle 功能,例如 DRCP 和应用程序连续性

使用 Oracle 数据库常驻连接池(DRCP)

当使用 Oracle 的DRCP时,最佳实践是在从 SessionPool 获取连接时传递连接类和“纯度”。参考 cx_Oracle DRCP 文档

这可以通过包装 pool.acquire() 来实现:

import cx_Oracle
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool
pool = cx_Oracle.SessionPool(
    user="scott", password="tiger", dsn="orclpdb",
    min=2, max=5, increment=1, threaded=True,
    encoding="UTF-8", nencoding="UTF-8"
)
def creator():
    return pool.acquire(cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF)
engine = create_engine("oracle+cx_oracle://", creator=creator, poolclass=NullPool)

然后可以正常使用上述引擎,其中 cx_Oracle 处理会话池,Oracle 数据库另外使用 DRCP:

with engine.connect() as conn:
    print(conn.scalar("select 1 FROM dual"))

Unicode

对于 Python 3 下的所有 DBAPI,所有字符串本质上都是 Unicode 字符串。然而,在所有情况下,驱动程序都需要明确的编码配置。

确保正确的客户端编码

几乎所有与 Oracle 相关的软件的建立客户端编码的长期接受标准是通过NLS_LANG环境变量。像大多数其他 Oracle 驱动程序一样,cx_Oracle 将使用此环境变量作为其编码配置的源。该变量的格式是特殊的;典型值可能是 AMERICAN_AMERICA.AL32UTF8

cx_Oracle 驱动程序还支持一种编程替代方法,即直接将 encodingnencoding 参数传递给其 .connect() 函数。这些可以在 URL 中存在如下:

engine = create_engine("oracle+cx_oracle://scott:tiger@orclpdb/?encoding=UTF-8&nencoding=UTF-8")

关于 encodingnencoding 参数的含义,请参阅字符集和国家语言支持(NLS)

另请参阅

字符集和国家语言支持 (NLS) - 在 cx_Oracle 文档中。

Unicode 特定的列数据类型

核心表达式语言通过使用 UnicodeUnicodeText 数据类型处理 Unicode 数据。这些类型默认对应于 VARCHAR2 和 CLOB Oracle 数据类型。当使用这些数据类型处理 Unicode 数据时,期望 Oracle 数据库配置了 Unicode-aware 字符集,并且 NLS_LANG 环境变量被适当设置,以便 VARCHAR2 和 CLOB 数据类型可以容纳数据。

如果 Oracle 数据库未配置为 Unicode 字符集,则两个选项是显式使用 NCHARNCLOB 数据类型,或者在调用 create_engine() 时传递 use_nchar_for_unicode=True 标志,这将导致 SQLAlchemy 方言对 Unicode / UnicodeText 数据类型使用 NCHAR/NCLOB 而不是 VARCHAR/CLOB。

版本 1.3 中的变更:UnicodeUnicodeText 数据类型现在对应于 VARCHAR2CLOB Oracle 数据类型,除非在调用 create_engine() 时传递了 use_nchar_for_unicode=True 参数给方言。

编码错误

对于 Oracle 数据库中数据存在破损编码的特殊情况,方言接受一个名为 encoding_errors 的参数,该参数将传递给 Unicode 解码函数,以影响如何处理解码错误。该值最终由 Python 的 decode 函数消耗,并且通过 cx_Oracle 的 encodingErrors 参数(由 Cursor.var() 消耗)以及 SQLAlchemy 自己的解码函数传递,因为在不同情况下 cx_Oracle 方言都会使用它们。

新版本 1.3.11 中新增。

确保正确的客户端编码

几乎所有与 Oracle 相关的软件建立客户端编码的长期接受标准是通过 NLS_LANG 环境变量。cx_Oracle 像大多数其他 Oracle 驱动程序一样将使用此环境变量作为其编码配置的来源。该变量的格式是特殊的;典型值可能是 AMERICAN_AMERICA.AL32UTF8

cx_Oracle 驱动程序还支持一种编程方式,即直接将 encodingnencoding 参数传递给其 .connect() 函数。可以在 URL 中以以下方式存在:

engine = create_engine("oracle+cx_oracle://scott:tiger@orclpdb/?encoding=UTF-8&nencoding=UTF-8")

关于 encodingnencoding 参数的含义,请参阅字符集和国家语言支持(NLS)

参见

字符集和国家语言支持(NLS) - 在 cx_Oracle 文档中。

Unicode 特定列数据类型

核心表达式语言通过使用 UnicodeUnicodeText 数据类型处理 Unicode 数据。这些类型默认对应于 VARCHAR2 和 CLOB Oracle 数据类型。当使用这些数据类型处理 Unicode 数据时,预期 Oracle 数据库已配置为使用 Unicode 意识字符集,并且 NLS_LANG 环境变量已适当设置,以便 VARCHAR2 和 CLOB 数据类型可以容纳数据。

如果 Oracle 数据库未配置为 Unicode 字符集,则两个选项是显式使用 NCHARNCLOB 数据类型,或者在调用 create_engine() 时传递标志 use_nchar_for_unicode=True 给 SQLAlchemy 方言,这将导致 SQLAlchemy 方言在 Unicode / UnicodeText 数据类型上使用 NCHAR/NCLOB 而不是 VARCHAR/CLOB。

从版本 1.3 开始更改:UnicodeUnicodeText 数据类型现在对应于 VARCHAR2CLOB Oracle 数据类型,除非在调用 create_engine() 时传递了 use_nchar_for_unicode=True

编码错误

对于 Oracle 数据库中存在损坏编码的特殊情况,该方言接受一个名为 encoding_errors 的参数,该参数将传递给 Unicode 解码函数,以影响如何处理解码错误。该值最终由 Python 的 decode 函数消耗,并且通过 cx_Oracle 的 encodingErrors 参数传递给 Cursor.var(),以及通过 SQLAlchemy 自己的解码函数传递,因为在不同情况下 cx_Oracle 方言都会使用两者。

自版本 1.3.11 起新增。

使用 setinputsizes 对 cx_Oracle 数据绑定性能进行精细控制

cx_Oracle DBAPI 对 DBAPI setinputsizes() 调用具有深层且根本的依赖性。此调用的目的是为通过参数传递的 Python 值绑定到 SQL 语句的数据类型建立起来。虽然几乎没有其他 DBAPI 将任何用途分配给 setinputsizes() 调用,但是 cx_Oracle DBAPI 在与 Oracle 客户端接口的交互中大量依赖它,并且在某些情况下,SQLAlchemy 无法确切地知道数据应该如何绑定,因为某些设置可能会导致性能特性发生深刻不同,同时改变类型强制转换行为。

强烈建议 cx_Oracle 方言的用户阅读 cx_Oracle 内置数据类型符号的列表,网址为 cx-oracle.readthedocs.io/en/latest/api_manual/module.html#database-types。请注意,在某些情况下,使用这些类型与不使用这些类型相比,性能可能会显著下降,特别是在指定 cx_Oracle.CLOB 时。

在 SQLAlchemy 方面,DialectEvents.do_setinputsizes() 事件可用于在运行时(例如记录)可见 setinputsizes 步骤,以及完全控制每个语句如何使用 setinputsizes()

自版本 1.2.9 起新增:增加了 DialectEvents.setinputsizes()

示例 1 - 记录所有 setinputsizes 调用

以下示例说明了如何在转换为原始 setinputsizes() 参数字典之前从 SQLAlchemy 视角记录中间值。字典的键是具有 .key.type 属性的 BindParameter 对象:

from sqlalchemy import create_engine, event
engine = create_engine("oracle+cx_oracle://scott:tiger@host/xe")
@event.listens_for(engine, "do_setinputsizes")
def _log_setinputsizes(inputsizes, cursor, statement, parameters, context):
    for bindparam, dbapitype in inputsizes.items():
            log.info(
                "Bound parameter name: %s SQLAlchemy type: %r "
                "DBAPI object: %s",
                bindparam.key, bindparam.type, dbapitype)
示例 2 - 移除所有对 CLOB 的绑定

在 cx_Oracle 中,CLOB 数据类型会导致显着的性能开销,但是在 SQLAlchemy 1.2 系列中,默认为 Text 类型设置了该类型。可以按照以下方式修改此设置:

from sqlalchemy import create_engine, event
from cx_Oracle import CLOB
engine = create_engine("oracle+cx_oracle://scott:tiger@host/xe")
@event.listens_for(engine, "do_setinputsizes")
def _remove_clob(inputsizes, cursor, statement, parameters, context):
    for bindparam, dbapitype in list(inputsizes.items()):
        if dbapitype is CLOB:
            del inputsizes[bindparam]
示例 1 - 记录所有 setinputsizes 调用

以下示例说明了如何在 SQLAlchemy 视角下记录中间值,然后再将它们转换为原始setinputsizes()参数字典。字典的键是具有.key.type属性的BindParameter对象:

from sqlalchemy import create_engine, event
engine = create_engine("oracle+cx_oracle://scott:tiger@host/xe")
@event.listens_for(engine, "do_setinputsizes")
def _log_setinputsizes(inputsizes, cursor, statement, parameters, context):
    for bindparam, dbapitype in inputsizes.items():
            log.info(
                "Bound parameter name: %s SQLAlchemy type: %r "
                "DBAPI object: %s",
                bindparam.key, bindparam.type, dbapitype)
示例 2 - 删除所有对 CLOB 的绑定

在 cx_Oracle 中,CLOB 数据类型会产生显着的性能开销,但在 SQLAlchemy 1.2 系列中默认设置为Text类型。可以按以下方式修改此设置:

from sqlalchemy import create_engine, event
from cx_Oracle import CLOB
engine = create_engine("oracle+cx_oracle://scott:tiger@host/xe")
@event.listens_for(engine, "do_setinputsizes")
def _remove_clob(inputsizes, cursor, statement, parameters, context):
    for bindparam, dbapitype in list(inputsizes.items()):
        if dbapitype is CLOB:
            del inputsizes[bindparam]

RETURNING 支持

cx_Oracle 方言使用 OUT 参数实现 RETURNING。该方言完全支持 RETURNING。

LOB 数据类型

LOB 数据类型指的是诸如 CLOB、NCLOB 和 BLOB 等“大对象”数据类型。现代版本的 cx_Oracle 和 oracledb  都经过优化,以便将这些数据类型作为单个缓冲区传递。因此,默认情况下 SQLAlchemy 使用这些较新的类型处理程序。

要禁用较新类型处理程序的使用,并将 LOB 对象作为具有read()方法的经典缓冲对象传递,可以将参数auto_convert_lobs=False传递给create_engine(),这仅在整个引擎范围内生效。

不支持两阶段事务

由于 cx_Oracle 的驱动程序支持不佳,cx_Oracle 不支持两阶段事务。从 cx_Oracle 6.0b1  开始,用于两阶段事务的接口已更改为更直接地通过到底层 OCI 层的传递,自动化程度较低。支持此系统的附加逻辑未在 SQLAlchemy 中实现。

精确数值

SQLAlchemy 的数值类型可以处理接收和返回 Python Decimal 对象或浮点对象的值。当使用 Numeric 对象或其子类如 FloatDOUBLE_PRECISION 等时,Numeric.asdecimal 标志确定返回时值是否应强制转换为 Decimal,或作为浮点对象返回。在 Oracle 下更加复杂的是,如果“scale”为零,Oracle 的 NUMBER 类型也可以表示整数值,因此 Oracle 特定的 NUMBER 类型也考虑到了这一点。

cx_Oracle 方言广泛使用连接和游标级别的“outputtypehandler”可调用对象,以按请求强制转换数值。这些可调用对象特定于正在使用的特定Numeric的类型,以及如果没有  SQLAlchemy 类型化对象存在。已经观察到 Oracle  可能会发送关于返回的数值类型不完整或模糊的信息的情况,例如查询,其中数值类型被埋在多级子查询下。类型处理程序尽最大努力在所有情况下做出正确的决定,在所有情况下都推迟到底层  cx_Oracle DBAPI,以便在驱动程序可以做出最佳决定的所有这些情况下。

当没有类型化对象时,例如执行纯 SQL 字符串时,存在一个默认的“outputtypehandler”,通常返回指定精度和比例的数值,其类型为 Python 的Decimal对象。为了出于性能考虑禁用对十进制数的强制转换,请在create_engine()中传递标志coerce_to_decimal=False

engine = create_engine("oracle+cx_oracle://dsn", coerce_to_decimal=False)

coerce_to_decimal标志仅影响不与Numeric SQLAlchemy 类型(或其子类)相关联的纯字符串 SQL 语句的结果。

从 1.2 版本开始更改:cx_Oracle 的数值处理系统已经重新设计,以利用较新的 cx_Oracle 功能以及更好地集成 outputtypehandlers。

python-oracledb

通过 python-oracledb 驱动程序支持 Oracle 数据库。

DBAPI

有关 python-oracledb 的文档和下载信息(如果适用),请访问:oracle.github.io/python-oracledb/

连接

连接字符串:

oracle+oracledb://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]

python-oracledb 是由 Oracle 发布的,旨在取代 cx_Oracle 驱动程序。它与 cx_Oracle  完全兼容,具有不需要任何依赖项的“轻客户端”模式,以及使用与 cx_Oracle 相同的方式使用 Oracle Client Interface  的“厚客户端”模式。

另请参阅

cx_Oracle - cx_Oracle 的所有注意事项也适用于 oracledb 驱动程序。

SQLAlchemy 的oracledb方言提供了同名的同步和异步实现。根据引擎的创建方式选择合适的版本:

  • 使用oracle+oracledb://...调用create_engine()将自动选择同步版本,例如:
from sqlalchemy import create_engine
sync_engine = create_engine("oracle+oracledb://scott:tiger@localhost/?service_name=XEPDB1")
  • 使用oracle+oracledb://...调用create_async_engine()将自动选择异步版本,例如:
from sqlalchemy.ext.asyncio import create_async_engine
asyncio_engine = create_async_engine("oracle+oracledb://scott:tiger@localhost/?service_name=XEPDB1")

可以明确指定方言的异步版本,例如使用oracledb_async后缀:

from sqlalchemy.ext.asyncio import create_async_engine
asyncio_engine = create_async_engine("oracle+oracledb_async://scott:tiger@localhost/?service_name=XEPDB1")

新版本 2.0.25 中新增对 oracledb 的异步版本的支持。

Thick mode 支持

默认情况下,python-oracledb 以 thin 模式启动,不需要在系统中安装 Oracle 客户端库。python-oracledb 驱动程序还支持一种“thick”模式,其行为类似于cx_oracle,并且要求安装 Oracle 客户端接口(OCI)。

要启用此模式,用户可以手动调用oracledb.init_oracle_client,也可以通过将参数thick_mode=True传递给create_engine()来实现。要将自定义参数传递给init_oracle_client,如lib_dir路径,则可以将字典传递给此参数,如下所示:

engine = sa.create_engine("oracle+oracledb://...", thick_mode={
    "lib_dir": "/path/to/oracle/client/lib", "driver_name": "my-app"
})

另请参见

python-oracledb.readthedocs.io/en/latest/api_manual/module.html#oracledb.init_oracle_client

新版本 2.0.0 中新增对 oracledb 驱动程序的支持。

DBAPI

python-oracledb 的文档和下载信息(如适用)可在此处找到:oracle.github.io/python-oracledb/

连接

连接字符串:

oracle+oracledb://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]

Thick mode 支持

默认情况下,python-oracledb 以 thin 模式启动,不需要在系统中安装 Oracle 客户端库。python-oracledb 驱动程序还支持一种“thick”模式,其行为类似于cx_oracle,并且要求安装 Oracle 客户端接口(OCI)。

要启用此模式,用户可以手动调用oracledb.init_oracle_client,也可以通过将参数thick_mode=True传递给create_engine()来实现。要将自定义参数传递给init_oracle_client,如lib_dir路径,则可以将字典传递给此参数,如下所示:

engine = sa.create_engine("oracle+oracledb://...", thick_mode={
    "lib_dir": "/path/to/oracle/client/lib", "driver_name": "my-app"
})

另请参见

python-oracledb.readthedocs.io/en/latest/api_manual/module.html#oracledb.init_oracle_client

新版本 2.0.0 中新增对 oracledb 驱动程序的支持。

不需要任何依赖项的“轻客户端”模式,以及使用与 cx_Oracle 相同的方式使用 Oracle Client Interface 的“厚客户端”模式。

另请参阅

cx_Oracle - cx_Oracle 的所有注意事项也适用于 oracledb 驱动程序。

SQLAlchemy 的oracledb方言提供了同名的同步和异步实现。根据引擎的创建方式选择合适的版本:

  • 使用oracle+oracledb://...调用create_engine()将自动选择同步版本,例如:
from sqlalchemy import create_engine
sync_engine = create_engine("oracle+oracledb://scott:tiger@localhost/?service_name=XEPDB1")
  • 使用oracle+oracledb://...调用create_async_engine()将自动选择异步版本,例如:
from sqlalchemy.ext.asyncio import create_async_engine
asyncio_engine = create_async_engine("oracle+oracledb://scott:tiger@localhost/?service_name=XEPDB1")

可以明确指定方言的异步版本,例如使用oracledb_async后缀:

from sqlalchemy.ext.asyncio import create_async_engine
asyncio_engine = create_async_engine("oracle+oracledb_async://scott:tiger@localhost/?service_name=XEPDB1")

新版本 2.0.25 中新增对 oracledb 的异步版本的支持。

Thick mode 支持

默认情况下,python-oracledb 以 thin 模式启动,不需要在系统中安装 Oracle 客户端库。python-oracledb 驱动程序还支持一种“thick”模式,其行为类似于cx_oracle,并且要求安装 Oracle 客户端接口(OCI)。

要启用此模式,用户可以手动调用oracledb.init_oracle_client,也可以通过将参数thick_mode=True传递给create_engine()来实现。要将自定义参数传递给init_oracle_client,如lib_dir路径,则可以将字典传递给此参数,如下所示:

engine = sa.create_engine("oracle+oracledb://...", thick_mode={
    "lib_dir": "/path/to/oracle/client/lib", "driver_name": "my-app"
})

另请参见

python-oracledb.readthedocs.io/en/latest/api_manual/module.html#oracledb.init_oracle_client

新版本 2.0.0 中新增对 oracledb 驱动程序的支持。

DBAPI

python-oracledb 的文档和下载信息(如适用)可在此处找到:oracle.github.io/python-oracledb/

连接

连接字符串:

oracle+oracledb://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]

Thick mode 支持

默认情况下,python-oracledb 以 thin 模式启动,不需要在系统中安装 Oracle 客户端库。python-oracledb 驱动程序还支持一种“thick”模式,其行为类似于cx_oracle,并且要求安装 Oracle 客户端接口(OCI)。

要启用此模式,用户可以手动调用oracledb.init_oracle_client,也可以通过将参数thick_mode=True传递给create_engine()来实现。要将自定义参数传递给init_oracle_client,如lib_dir路径,则可以将字典传递给此参数,如下所示:

engine = sa.create_engine("oracle+oracledb://...", thick_mode={
    "lib_dir": "/path/to/oracle/client/lib", "driver_name": "my-app"
})

另请参见

python-oracledb.readthedocs.io/en/latest/api_manual/module.html#oracledb.init_oracle_client

新版本 2.0.0 中新增对 oracledb 驱动程序的支持。

相关文章
|
3月前
|
SQL 缓存 关系型数据库
SqlAlchemy 2.0 中文文档(四十一)(6)
SqlAlchemy 2.0 中文文档(四十一)
49 7
|
3月前
|
SQL 缓存 关系型数据库
SqlAlchemy 2.0 中文文档(四十一)(7)
SqlAlchemy 2.0 中文文档(四十一)(8)
50 5
|
3月前
|
SQL JSON 关系型数据库
SqlAlchemy 2.0 中文文档(四十一)(5)
SqlAlchemy 2.0 中文文档(四十一)
44 6
|
3月前
|
SQL JSON 关系型数据库
SqlAlchemy 2.0 中文文档(四十一)(8)
SqlAlchemy 2.0 中文文档(四十一)
52 6
|
3月前
|
SQL 缓存 关系型数据库
SqlAlchemy 2.0 中文文档(四十一)(4)
SqlAlchemy 2.0 中文文档(四十一)
35 4
|
3月前
|
SQL 缓存 关系型数据库
SqlAlchemy 2.0 中文文档(四十一)(3)
SqlAlchemy 2.0 中文文档(四十一)
43 4
|
3月前
|
SQL Oracle 关系型数据库
SqlAlchemy 2.0 中文文档(五十一)(2)
SqlAlchemy 2.0 中文文档(五十一)
28 1
|
3月前
|
Oracle 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(五十一)(3)
SqlAlchemy 2.0 中文文档(五十一)
32 1
|
3月前
|
SQL Oracle 关系型数据库
SqlAlchemy 2.0 中文文档(五十一)(4)
SqlAlchemy 2.0 中文文档(五十一)
31 1
|
3月前
|
Oracle 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(五十一)(1)
SqlAlchemy 2.0 中文文档(五十一)
34 1