SqlAlchemy 2.0 中文文档(五十一)(1)https://developer.aliyun.com/article/1563194
成员
init()
类签名
类 sqlalchemy.dialects.oracle.BINARY_FLOAT
(sqlalchemy.types.Float
)
method __init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)
继承自 Float
的 sqlalchemy.types.Float.__init__
方法
构造一个 Float。
参数:
precision
–
用于在 DDLCREATE TABLE
中使用的数字精度。后端应该尽量确保此精度表示通用Float
数据类型的数字位数。
注意
对于 Oracle 后端,在渲染 DDL 时,不接受Float.precision
参数,因为 Oracle 不支持将浮点精度指定为小数位数。相反,使用特定于 Oracle 的FLOAT
数据类型,并指定FLOAT.binary_precision
参数。这是 SQLAlchemy 版本 2.0 中的新功能。
要创建一个与数据库无关的Float
,分别为 Oracle 指定二进制精度,可以使用TypeEngine.with_variant()
,如下所示:
from sqlalchemy import Column from sqlalchemy import Float from sqlalchemy.dialects import oracle Column( "float_data", Float(5).with_variant(oracle.FLOAT(binary_precision=16), "oracle") )
asdecimal
– 与Numeric
相同的标志,但默认值为False
。请注意,将此标志设置为True
会导致浮点转换。decimal_return_scale
– 在将浮点数转换为 Python 十进制数时使用的默认精度。由于十进制的不准确性,浮点值通常会更长,并且大多数浮点数据库类型都没有“精度”的概念,因此,默认情况下,浮点类型在转换时会寻找前十位小数点。指定此值将覆盖该长度。请注意,如果未另行指定,包括“精度”的 MySQL 浮点类型将使用“精度”作为 decimal_return_scale 的默认值。
class sqlalchemy.dialects.oracle.DATE
提供 Oracle DATE 类型。
此类型没有特殊的 Python 行为,除了它是DateTime
的子类;这是为了适应 Oracle DATE
类型支持时间值的事实。
成员
init()
类签名
类sqlalchemy.dialects.oracle.DATE
(sqlalchemy.dialects.oracle.types._OracleDateLiteralRender
,sqlalchemy.types.DateTime
)
method __init__(timezone: bool = False)
继承自 DateTime
的 sqlalchemy.types.DateTime.__init__
方法
构造一个新的DateTime
。
参数:
时区 – 布尔值。表示日期时间类型是否应在仅基本日期/时间保存类型上启用时区支持(如果可用)。建议在使用此标志时直接使用TIMESTAMP
数据类型,因为一些数据库包括与时区可用的 TIMESTAMP 数据类型不同的独立通用日期/时间保存类型,例如 Oracle。
class sqlalchemy.dialects.oracle.FLOAT
Oracle FLOAT。
这与FLOAT
相同,不同之处在于接受特定于 Oracle 的FLOAT.binary_precision
参数,并且不接受Float.precision
参数。
Oracle FLOAT 类型以“二进制精度”表示精度,默认为 126。对于 REAL 类型,该值为 63。此参数不清晰地映射到特定数量的小数位数,但大致相当于所需小数位数除以 0.3103。
2.0 版中的新功能。
成员
init()
类签名
class sqlalchemy.dialects.oracle.FLOAT
(sqlalchemy.types.FLOAT
)
method __init__(binary_precision=None, asdecimal=False, decimal_return_scale=None)
构造一个 FLOAT
参数:
binary_precision
– 要在 DDL 中呈现的 Oracle 二进制精度值。这可以使用公式“十进制精度= 0.30103 * 二进制精度”来近似到十进制字符的数量。Oracle 用于 FLOAT / DOUBLE PRECISION 的默认值为 126。asdecimal
– 参见Float.asdecimal
decimal_return_scale
– 参见Float.decimal_return_scale
class sqlalchemy.dialects.oracle.INTERVAL
成员
init()
类签名
class sqlalchemy.dialects.oracle.INTERVAL
(sqlalchemy.types.NativeForEmulated
, sqlalchemy.types._AbstractInterval
)
method __init__(day_precision=None, second_precision=None)
构造一个 INTERVAL。
请注意,当前仅支持 DAY TO SECOND 间隔。这是由于可用 DBAPI 中缺少对 YEAR TO MONTH 间隔的支持。
参数:
day_precision
– 日期精度值。这是要存储的日字段的位数。默认为“2”。second_precision
– 秒精度值。这是要存储的分数秒字段的位数。默认为“6”。
class sqlalchemy.dialects.oracle.NCLOB
成员
init()
类签名
sqlalchemy.dialects.oracle.NCLOB
类(sqlalchemy.types.Text
)
method __init__(length: int | None = None, collation: str | None = None)
继承自 String
的 sqlalchemy.types.String.__init__
方法
创建一个持有字符串的类型。
参数:
length
– 可选的,在 DDL 和 CAST 表达式中使用的列的长度。如果不会发出CREATE TABLE
,可以安全地省略。某些数据库可能需要在 DDL 中使用长度,并且如果包含了没有长度的VARCHAR
,则在发出CREATE TABLE
DDL 时将引发异常。该值被解释为字节还是字符取决于数据库。collation
–
可选的,在 DDL 和 CAST 表达式中使用的列级排序。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字呈现。例如:
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8')))) SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1
- 注意
在大多数情况下,应使用Unicode
或UnicodeText
数据类型来存储非 ASCII 数据的Column
。这些数据类型将确保在数据库上使用正确的类型。
attribute sqlalchemy.dialects.oracle.NVARCHAR2
NVARCHAR
的别名
class sqlalchemy.dialects.oracle.NUMBER
类签名
sqlalchemy.dialects.oracle.NUMBER
类(sqlalchemy.types.Numeric
,sqlalchemy.types.Integer
)
class sqlalchemy.dialects.oracle.LONG
成员
init()
类签名
sqlalchemy.dialects.oracle.LONG
类(sqlalchemy.types.Text
)
method __init__(length: int | None = None, collation: str | None = None)
继承自 String
的 sqlalchemy.types.String.__init__
方法
创建一个持有字符串的类型。
参数:
length
– 可选的,在 DDL 和 CAST 表达式中使用的列的长度。如果不会发出CREATE TABLE
,可以安全地省略。某些数据库可能需要在 DDL 中使用长度,并且如果包含了没有长度的VARCHAR
,则在发出CREATE TABLE
DDL 时将引发异常。该值被解释为字节还是字符取决于数据库。collation
–
可选的,在 DDL 和 CAST 表达式中使用的列级排序。使用 SQLite、MySQL 和 PostgreSQL 支持的 COLLATE 关键字呈现。例如:
>>> from sqlalchemy import cast, select, String >>> print(select(cast('some string', String(collation='utf8')))) SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1
- 注意
在大多数情况下,应该使用Unicode
或UnicodeText
数据类型来表示预期存储非 ASCII 数据的Column
。这些数据类型将确保在数据库上使用正确的类型。
class sqlalchemy.dialects.oracle.RAW
类签名
类sqlalchemy.dialects.oracle.RAW
(sqlalchemy.types._Binary
)
class sqlalchemy.dialects.oracle.ROWID
Oracle ROWID 类型。
在 cast() 或类似情况下使用时,生成 ROWID。
类签名
类sqlalchemy.dialects.oracle.ROWID
(sqlalchemy.types.TypeEngine
)
class sqlalchemy.dialects.oracle.TIMESTAMP
Oracle 实现的 TIMESTAMP
,支持额外的 Oracle 特定模式
2.0 版本中的新功能。
成员
init()
类签名
类sqlalchemy.dialects.oracle.TIMESTAMP
(sqlalchemy.types.TIMESTAMP
)
method __init__(timezone: bool = False, local_timezone: bool = False)
构造一个新的TIMESTAMP
。
参数:
timezone
– 布尔值。表示 TIMESTAMP 类型应该使用 Oracle 的TIMESTAMP WITH TIME ZONE
数据类型。local_timezone
– 布尔值。表示 TIMESTAMP 类型应该使用 Oracle 的TIMESTAMP WITH LOCAL TIME ZONE
数据类型。
cx_Oracle
通过 cx-Oracle 驱动程序支持 Oracle 数据库。
DBAPI
cx-Oracle 的文档和下载信息(如果适用)可在此处获得:oracle.github.io/python-cx_Oracle/
连接
连接字符串:
oracle+cx_oracle://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]
DSN vs. 主机名连接
cx_Oracle 提供了几种指示目标数据库的方法。方言从一系列不同的 URL 形式转换而来。
使用 Easy Connect 语法的主机名连接
给定目标 Oracle 数据库的主机名、端口和服务名称,例如来自 Oracle 的 Easy Connect 语法,然后在 SQLAlchemy 中使用 service_name
查询字符串参数进行连接:
engine = create_engine("oracle+cx_oracle://scott:tiger@hostname:port/?service_name=myservice&encoding=UTF-8&nencoding=UTF-8")
不支持完整的 Easy Connect 语法。而是使用 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 的主机名部分,而没有指定端口、数据库名称或 service_name
时,cx_Oracle 方言将连接到此数据库服务:
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)))'
传递 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 中,encoding
和 nencoding
的默认值已更改为 “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 会话池
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 数据库 Resident 连接池(DRCP)
在使用 Oracle 的DRCP时,最佳实践是在从 SessionPool 获取连接时传递连接类和“purity”。请参阅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环境变量。cx_Oracle 像大多数其他 Oracle 驱动程序一样将使用此环境变量作为其编码配置的来源。此变量的格式是特殊的;典型的值可能是AMERICAN_AMERICA.AL32UTF8
。
cx_Oracle 驱动程序还支持一种编程方式,即直接将encoding
和nencoding
参数传递给其.connect()
函数。这些可以在 URL 中如下所示:
engine = create_engine("oracle+cx_oracle://scott:tiger@orclpdb/?encoding=UTF-8&nencoding=UTF-8")
关于encoding
和nencoding
参数的含义,请参考字符集和国家语言支持(NLS)。
另见
字符集和国家语言支持(NLS) - 在 cx_Oracle 文档中。
Unicode 特定的列数据类型
核心表达式语言通过使用Unicode
和 UnicodeText
数据类型处理 Unicode 数据。这些类型默认对应于 VARCHAR2 和 CLOB Oracle 数据类型。在使用这些数据类型处理 Unicode 数据时,预期 Oracle 数据库配置为具有 Unicode 意识的字符集,并且NLS_LANG
环境变量设置正确,以便 VARCHAR2 和 CLOB 数据类型可以容纳数据。
如果 Oracle 数据库未配置为 Unicode 字符集,则有两种选择:显式使用NCHAR
和NCLOB
数据类型,或者在调用create_engine()
时传递标志use_nchar_for_unicode=True
,这将导致 SQLAlchemy 方言使用 NCHAR/NCLOB 代替 VARCHAR/CLOB 用于Unicode
/ UnicodeText
数据类型。
从版本 1.3 开始更改:Unicode
和 UnicodeText
数据类型现在对应于 VARCHAR2
和 CLOB
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] ```### RETURNING 支持 cx_Oracle 方言使用 OUT 参数实现 RETURNING。该方言完全支持 RETURNING。 ### LOB 数据类型 LOB 数据类型是指诸如 CLOB、NCLOB 和 BLOB 之类的“大对象”数据类型。cx_Oracle 和 oracledb 的现代版本经过优化,可以将这些数据类型作为单个缓冲区传递。因此,SQLAlchemy 默认使用这些新型处理程序。 要禁用新型类型处理程序的使用,并将 LOB 对象作为具有 `read()` 方法的经典缓冲对象传递,可以向 `create_engine()` 传递参数 `auto_convert_lobs=False`,这仅在引擎范围内生效。 ### 不支持两阶段事务 由于驱动程序支持不佳,cx_Oracle 不支持两阶段事务。从 cx_Oracle 6.0b1 开始,两阶段事务的接口已更改为更直接地通过到底层 OCI 层的传递,自动化程度较低。支持此系统的附加逻辑未在 SQLAlchemy 中实现。 ### 精确数字 SQLAlchemy 的数字类型可以处理接收和返回 Python `Decimal` 对象或浮点对象的值。当使用 `Numeric` 对象或其子类如 `Float`,`DOUBLE_PRECISION` 等时,`Numeric.asdecimal` 标志确定返回时值是否应强制转换为 `Decimal`,或返回为浮点对象。在 Oracle 下更加复杂,Oracle 的 `NUMBER` 类型如果“scale”为零,也可以表示整数值,因此 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 功能以及更好地集成 outputtypehandlers。 ## python-oracledb
通过 python-oracledb 驱动程序支持 Oracle 数据库。
SqlAlchemy 2.0 中文文档(五十一)(3)https://developer.aliyun.com/article/1563197