SQLAlchemy 2.0 文档
方言
- PostgreSQL
- MySQL 和 MariaDB
- SQLite
- Oracle¶
- 对 Oracle 数据库的支持。
- 自动递增行为
- 事务隔离级别/自动提交
- 标识符大小写
- 最大标识符长度
- LIMIT/OFFSET/FETCH 支持
- RETURNING 支持
- ON UPDATE CASCADE
- Oracle 8 兼容性
- 同义词/DBLINK 反射
- 约束反射
- 表名包含 SYSTEM/SYSAUX 表空间
- 日期时间兼容性
- Oracle 表选项
- Oracle 特定索引选项
- Oracle 数据类型
- cx_Oracle
- python-oracledb
- Microsoft SQL Server
项目版本
- 上一章: SQLite
- 下一章: Microsoft SQL Server
- 上一级: 主页
- 本页内容
- Oracle
- 对 Oracle 数据库的支持。
- 自动递增行为
- 事务隔离级别/自动提交
- 标识符大小写
- 最大标识符长度
- LIMIT/OFFSET/FETCH 支持
- RETURNING 支持
- ON UPDATE CASCADE
- Oracle 8 兼容性
- 同义词/DBLINK 反射
- 约束反射
- 表名包含 SYSTEM/SYSAUX 表空间
- 日期时间兼容性
- Oracle 表选项
- Oracle 特定索引选项
- Oracle 数据类型
- cx_Oracle
- python-oracledb
Oracle¶
对 Oracle 数据库的支持。
下表总结了当前对数据库版本的支持级别。
支持类型 |
版本 |
---|---|
11+ |
|
9+ |
DBAPI 支持¶
以下方言/DBAPI 选项可用。有关连接信息,请参阅各个 DBAPI 部分。
自动递增行为¶
包含整数主键的 SQLAlchemy 表对象通常被认为具有“自动递增”行为,这意味着它们可以在 INSERT 时生成自己的主键值。在 Oracle 中使用时,有两种选择可用,即使用 IDENTITY 列(仅限 Oracle 12 及更高版本)或将 SEQUENCE 与列关联。
指定 GENERATED AS IDENTITY(Oracle 12 及更高版本)¶
从版本 12 开始,Oracle 可以使用 IDENTITY 列,使用 Identity
指定自动递增行为
t = Table('mytable', metadata,
Column('id', Integer, Identity(start=3), primary_key=True),
Column(...), ...
)
上面 Table
对象的 CREATE TABLE 将是
CREATE TABLE mytable (
id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 3),
...,
PRIMARY KEY (id)
)
该 Identity
对象支持许多选项来控制列的“自动递增”行为,例如起始值、递增值等。除了标准选项外,Oracle 还支持将 Identity.always
设置为 None
以使用默认生成的模式,在 DDL 中呈现 GENERATED AS IDENTITY。它还支持将 Identity.on_null
设置为 True
以指定 ON NULL 与 'BY DEFAULT' IDENTITY 列一起使用。
使用 SEQUENCE(所有 Oracle 版本)¶
旧版本的 Oracle 没有“自动递增”功能,SQLAlchemy 依赖于序列来生成这些值。在旧版本的 Oracle 中,必须始终显式指定序列才能启用自动递增。这与大多数假设使用支持自动递增的数据库的文档示例有所不同。要指定序列,请使用 sqlalchemy.schema.Sequence 对象,该对象传递给 Column 构造函数
t = Table('mytable', metadata,
Column('id', Integer, Sequence('id_seq', start=1), primary_key=True),
Column(...), ...
)
使用表反射时,此步骤也是必需的,即 autoload_with=engine
t = Table('mytable', metadata,
Column('id', Integer, Sequence('id_seq', start=1), primary_key=True),
autoload_with=engine
)
事务隔离级别/自动提交¶
Oracle 数据库支持“READ COMMITTED”和“SERIALIZABLE”隔离模式。cx_Oracle 方言还支持 AUTOCOMMIT 隔离级别。
要使用每个连接执行选项设置
connection = engine.connect()
connection = connection.execution_options(
isolation_level="AUTOCOMMIT"
)
对于 READ COMMITTED
和 SERIALIZABLE
,Oracle 方言使用 ALTER SESSION
在会话级别设置级别,该级别在连接返回到连接池时恢复到其默认设置。
有效值 isolation_level
包括
READ COMMITTED
AUTOCOMMIT
SERIALIZABLE
注意
Oracle 方言实现的 Connection.get_isolation_level()
方法必然会强制使用 Oracle LOCAL_TRANSACTION_ID 函数启动事务;否则通常无法读取任何级别。
此外,如果由于权限或其他原因 v$transaction
视图不可用,Connection.get_isolation_level()
方法将引发异常,这在 Oracle 安装中很常见。
cx_Oracle 方言在方言首次连接到数据库时尝试调用 Connection.get_isolation_level()
方法以获取“默认”隔离级别。此默认级别是必需的,以便在使用 Connection.execution_options()
方法临时修改连接后,可以将级别重置回连接。
在 Connection.get_isolation_level()
方法由于 v$transaction
不可读以及任何其他与数据库相关的故障而引发异常的常见情况下,假设级别为“READ COMMITTED”。对于此初始首次连接条件,不会发出任何警告,因为预计这会在 Oracle 数据库中是常见的限制。
版本 1.3.16 中的新增功能: 为 cx_oracle 方言以及默认隔离级别的概念添加了对 AUTOCOMMIT 的支持
版本 1.3.21 中的新增功能: 添加了对 SERIALIZABLE 的支持以及隔离级别的实时读取。
版本 1.3.22 中的更改: 如果由于 Oracle 安装中 v$transaction
的权限问题导致无法读取默认隔离级别,则默认隔离级别将硬编码为“READ COMMITTED”,这是 1.3.21 之前的行为。
设置事务隔离级别,包括 DBAPI 自动提交
标识符大小写¶
在 Oracle 中,数据字典使用大写文本表示所有不区分大小写的标识符名称。另一方面,SQLAlchemy 认为所有小写标识符名称不区分大小写。Oracle 方言在进行模式级别通信(例如表的反射和索引)时,会将所有不区分大小写的标识符转换为这两种格式。在 SQLAlchemy 侧使用大写名称表示区分大小写的标识符,SQLAlchemy 将引用该名称 - 这会导致与从 Oracle 收到的数据字典数据不匹配,因此,除非标识符名称真正创建为区分大小写(即使用引用的名称),否则应该在 SQLAlchemy 侧使用所有小写名称。
最大标识符长度¶
为了帮助进行此更改和其他更改,Oracle 引入了“兼容性”版本的概念,它是一个独立于实际服务器版本的版本号,用于帮助迁移 Oracle 数据库,并且可以在 Oracle 服务器本身内配置。此兼容性版本使用以下查询检索:SELECT value FROM v$parameter WHERE name = 'compatible';
。SQLAlchemy Oracle 方言在确定默认最大标识符长度时,会尝试在首次连接时使用此查询来确定服务器的有效兼容性版本,该版本决定了服务器允许的最大标识符长度。如果该表不可用,则会使用服务器版本信息。
从 SQLAlchemy 1.4 开始,Oracle 方言的默认最大标识符长度为 128 个字符。首次连接时,将检测兼容性版本,如果它小于 Oracle 版本 12.2,则最大标识符长度将更改为 30 个字符。在所有情况下,设置 create_engine.max_identifier_length
参数将绕过此更改,并且将使用给定的值。
engine = create_engine(
"oracle+cx_oracle://scott:tiger@oracle122",
max_identifier_length=30)
最大标识符长度在生成匿名 SQL 标签时发挥作用,但更重要的是在根据命名约定生成约束名称时发挥作用。正是这一方面导致 SQLAlchemy 需要保守地更改此默认值。例如,以下命名约定根据标识符长度产生两个截然不同的约束名称
from sqlalchemy import Column
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import Table
from sqlalchemy.dialects import oracle
from sqlalchemy.schema import CreateIndex
m = MetaData(naming_convention={"ix": "ix_%(column_0N_name)s"})
t = Table(
"t",
m,
Column("some_column_name_1", Integer),
Column("some_column_name_2", Integer),
Column("some_column_name_3", Integer),
)
ix = Index(
None,
t.c.some_column_name_1,
t.c.some_column_name_2,
t.c.some_column_name_3,
)
oracle_dialect = oracle.dialect(max_identifier_length=30)
print(CreateIndex(ix).compile(dialect=oracle_dialect))
标识符长度为 30 时,上面的 CREATE INDEX 如下所示
CREATE INDEX ix_some_column_name_1s_70cd ON t
(some_column_name_1, some_column_name_2, some_column_name_3)
但是,长度为 128 时,它将变为
CREATE INDEX ix_some_column_name_1some_column_name_2some_column_name_3 ON t
(some_column_name_1, some_column_name_2, some_column_name_3)
因此,在 Oracle 服务器版本 12.2 或更高版本上运行过 SQLAlchemy 1.4 之前的版本的应用程序,可能会遇到数据库迁移想要在以前使用较短长度生成的名称上“DROP CONSTRAINT”的情况。当在调整索引或约束名称之前更改标识符长度时,此迁移将失败。强烈建议此类应用程序使用 create_engine.max_identifier_length
来控制截断名称的生成,并在更改此值时,在暂存环境中完全审查和测试所有数据库迁移,以确保已缓解此更改的影响。
1.4 版中的变更: Oracle 的默认 max_identifier_length 为 128 个字符,如果检测到旧版本的 Oracle 服务器(兼容性版本 < 12.2),则在首次连接时将其调整为 30 个字符。
LIMIT/OFFSET/FETCH 支持¶
像 Select.limit()
和 Select.offset()
这样的方法使用 FETCH FIRST N ROW / OFFSET N ROWS
语法,假设 Oracle 12c 或更高版本,并假设 SELECT 语句没有嵌入在 UNION 等复合语句中。此语法也可以通过使用 Select.fetch()
方法直接获得。
2.0 版中的变更: Oracle 方言现在对所有 Select.limit()
和 Select.offset()
使用(包括 ORM 和旧版 Query
)使用 FETCH FIRST N ROW / OFFSET N ROWS
。要强制使用使用窗口函数的旧版行为,请将 enable_offset_fetch=False
方言参数指定给 create_engine()
。
通过将 enable_offset_fetch=False
传递给 create_engine()
,可以在任何 Oracle 版本上禁用 FETCH FIRST / OFFSET
的使用,这将强制使用使用窗口函数的“旧版”模式。在使用 Oracle 12c 之前的版本时,此模式也会自动选择。
在使用旧版模式或在复合语句中嵌入具有 limit/offset 的 Select
语句时,将使用基于窗口函数的 LIMIT / OFFSET 的模拟方法,该方法涉及使用 ROW_NUMBER
创建子查询,这容易出现性能问题以及复杂语句的 SQL 构造问题。但是,此方法受所有 Oracle 版本支持。请参阅下面的说明。
有关 LIMIT / OFFSET 模拟的说明(当无法使用 fetch() 方法时)¶
如果使用 Select.limit()
和 Select.offset()
,或在 ORM 中使用 Oracle 12c 之前的版本的 Query.limit()
和 Query.offset()
方法,则以下说明适用
SQLAlchemy 目前使用 ROWNUM 来实现 LIMIT/OFFSET;确切的方法来自 https://blogs.oracle.com/oraclemagazine/on-rownum-and-limiting-results 。
默认情况下不使用“FIRST_ROWS()”优化关键字。要启用此优化指令的使用,请将
optimize_limits=True
指定给create_engine()
。1.4 版中的变更: Oracle 方言使用“后编译”方案渲染 limit/offset 整数,该方案在将语句传递给游标以执行之前直接渲染整数。
use_binds_for_limits
标志不再起作用。版本 1.3.22 中的更改: 如果由于 Oracle 安装中
v$transaction
的权限问题导致无法读取默认隔离级别,则默认隔离级别将硬编码为“READ COMMITTED”,这是 1.3.21 之前的行为。
RETURNING 支持¶
Oracle 数据库完全支持 RETURNING,用于使用单个绑定参数集合调用的 INSERT、UPDATE 和 DELETE 语句(即 cursor.execute()
风格的语句;SQLAlchemy 通常不支持 executemany 语句中的 RETURNING)。也可以返回多行。
2.0 版中的变更: Oracle 后端完全支持与其他后端相同的 RETURNING。
ON UPDATE CASCADE¶
Oracle 没有原生 ON UPDATE CASCADE 功能。可以从 https://web.archive.org/web/20090317041251/https://asktom.oracle.com/tkyte/update_cascade/index.html 获取基于触发器的解决方案。
在使用 SQLAlchemy ORM 时,ORM 具有有限的能力手动发出级联更新 - 使用“deferrable=True, initially='deferred'”关键字参数指定 ForeignKey 对象,并在每个关系() 上指定“passive_updates=False”。
Oracle 8 兼容性¶
警告
SQLAlchemy 2.0 不确定 Oracle 8 兼容性的状态。
当检测到 Oracle 8 时,方言会在内部将自身配置为以下行为
同义词/DBLINK 反射¶
在使用 Table 对象进行反射时,方言可以选择搜索由同义词指示的表(在本地或远程模式中,或者通过 DBLINK 访问),方法是将标志 oracle_resolve_synonyms=True
作为关键字参数传递给 Table
结构
some_table = Table('some_table', autoload_with=some_engine,
oracle_resolve_synonyms=True)
当设置此标志时,将搜索给定的名称(如上面的 some_table
),不仅在 ALL_TABLES
视图中,而且还在 ALL_SYNONYMS
视图中,以查看此名称是否实际上是另一个名称的同义词。如果找到同义词并且它引用 DBLINK,则 oracle 方言知道如何使用 DBLINK 语法(例如 @dblink
)查找表的信息。
oracle_resolve_synonyms
在需要反射参数的地方都可以被接受,包括 MetaData.reflect()
和 Inspector.get_columns()
等方法。
如果未使用同义词,则应禁用此标志。
约束反射¶
Oracle 方言可以返回有关外键、唯一键和 CHECK 约束以及表索引的信息。
可以使用 Inspector.get_foreign_keys()
、Inspector.get_unique_constraints()
、Inspector.get_check_constraints()
和 Inspector.get_indexes()
获取有关这些约束的原始信息。
在版本 1.2 中更改: Oracle 方言现在可以反射 UNIQUE 和 CHECK 约束。
在 Table
级别使用反射时,Table
将包括这些约束。
请注意以下注意事项
当使用
Inspector.get_check_constraints()
方法时,Oracle 会为指定“NOT NULL”的列构建一个特殊的“IS NOT NULL”约束。默认情况下,不会返回此约束;要包括“IS NOT NULL”约束,请传递标志include_all=True
from sqlalchemy import create_engine, inspect engine = create_engine("oracle+cx_oracle://s:t@dsn") inspector = inspect(engine) all_check_constraints = inspector.get_check_constraints( "some_table", include_all=True)
在大多数情况下,当反射
Table
时,UNIQUE 约束不会作为UniqueConstraint
对象可用,因为 Oracle 在大多数情况下会将唯一约束与 UNIQUE 索引镜像(例外情况似乎是当两个或多个唯一约束代表相同的列时);Table
将改为使用带有unique=True
标志的Index
表示这些约束。Oracle 为表的主键创建隐式索引;此索引排除在所有索引结果之外。
为索引反映的列列表不包括以 SYS_NC 开头的列名。
具有 SYSTEM/SYSAUX 表空间的表名¶
方法 Inspector.get_table_names()
和 Inspector.get_temp_table_names()
都为当前引擎返回表名列表。这些方法也是 MetaData.reflect()
等操作中发生的反射的一部分。默认情况下,这些操作会将 SYSTEM
和 SYSAUX
表空间排除在操作之外。要更改此设置,可以在引擎级别使用 exclude_tablespaces
参数更改默认的排除表空间列表。
# exclude SYSAUX and SOME_TABLESPACE, but not SYSTEM
e = create_engine(
"oracle+cx_oracle://scott:tiger@xe",
exclude_tablespaces=["SYSAUX", "SOME_TABLESPACE"])
日期时间兼容性¶
Oracle 没有名为 DATETIME
的数据类型,它只有 DATE
,实际上可以存储日期和时间值。因此,Oracle 方言提供了一种类型 DATE
,它是 DateTime
的子类。此类型没有特殊行为,只是作为此类型的“标记”存在;此外,当数据库列被反射并且类型被报告为 DATE
时,将使用支持时间的 DATE
类型。
Oracle 表选项¶
CREATE TABLE 语句在 Oracle 中与 Table
结构一起支持以下选项。
ON COMMIT
:Table( "some_table", metadata, ..., prefixes=['GLOBAL TEMPORARY'], oracle_on_commit='PRESERVE ROWS')
COMPRESS
:Table('mytable', metadata, Column('data', String(32)), oracle_compress=True) Table('mytable', metadata, Column('data', String(32)), oracle_compress=6) The ``oracle_compress`` parameter accepts either an integer compression level, or ``True`` to use the default compression level.
TABLESPACE
:Table('mytable', metadata, ..., oracle_tablespace="EXAMPLE_TABLESPACE") The ``oracle_tablespace`` parameter specifies the tablespace in which the table is to be created. This is useful when you want to create a table in a tablespace other than the default tablespace of the user. .. versionadded:: 2.0.37
Oracle 特定的索引选项¶
位图索引¶
您可以指定 oracle_bitmap
参数来创建位图索引而不是 B 树索引。
Index('my_index', my_table.c.data, oracle_bitmap=True)
位图索引不能是唯一的,也不能被压缩。SQLAlchemy 不会检查此类限制,只有数据库会检查。
索引压缩¶
Oracle 对于包含大量重复值的索引有更有效的存储模式。使用 oracle_compress
参数来开启键压缩。
Index('my_index', my_table.c.data, oracle_compress=True)
Index('my_index', my_table.c.data1, my_table.c.data2, unique=True,
oracle_compress=1)
参数 oracle_compress
接受一个整数,指定要压缩的前缀列数量,或 True
,使用默认值(对于非唯一索引的所有列,对于唯一索引的所有列,除了最后一列)。
Oracle 数据类型¶
与所有 SQLAlchemy 方言一样,所有已知在 Oracle 中有效的 UPPERCASE 类型都可以从顶级方言导入,无论它们来自 sqlalchemy.types
还是本地方言。
from sqlalchemy.dialects.oracle import (
BFILE,
BLOB,
CHAR,
CLOB,
DATE,
DOUBLE_PRECISION,
FLOAT,
INTERVAL,
LONG,
NCLOB,
NCHAR,
NUMBER,
NVARCHAR,
NVARCHAR2,
RAW,
TIMESTAMP,
VARCHAR,
VARCHAR2,
)
在版本 1.2.19 中添加: 将 NCHAR
添加到 Oracle 方言导出的数据类型列表中。
特定于 Oracle 或具有 Oracle 特定构造参数的类型如下所示。
对象名称 | 描述 |
---|---|
提供 Oracle DATE 类型。 |
|
Oracle FLOAT。 |
|
|
|
Oracle ROWID 类型。 |
|
Oracle 的 |
- class sqlalchemy.dialects.oracle.BFILE¶
成员
-
method
sqlalchemy.dialects.oracle.BFILE.
__init__(length: int | None = None)¶ 从
sqlalchemy.types.LargeBinary.__init__
方法继承LargeBinary
构造 LargeBinary 类型。
- 参数:
length¶ – 可选,列的长度,用于 DDL 语句,对于那些接受长度的二进制类型,例如 MySQL BLOB 类型。
-
method
- class sqlalchemy.dialects.oracle.BINARY_DOUBLE¶
成员
-
方法
sqlalchemy.dialects.oracle.BINARY_DOUBLE.
__init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)¶ 继承自
sqlalchemy.types.Float.__init__
方法Float
构造一个 Float。
- 参数:
precision¶ –
用于 DDL
CREATE TABLE
的数值精度。后端**应该**尝试确保此精度表示通用Float
数据类型的数字位数。注意
对于 Oracle 后端,当渲染 DDL 时,
Float.precision
参数不被接受,因为 Oracle 不支持以小数位数指定 float 精度。 相反,使用 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 十进制数时使用的默认比例。由于小数精度问题,浮点数通常会长得多,大多数浮点数据库类型都没有“比例”的概念,因此默认情况下,float 类型在转换时会寻找前十个小数位。指定此值将覆盖该长度。请注意,MySQL 浮点类型(确实包含“比例”)将使用“比例”作为 decimal_return_scale 的默认值,除非另有指定。
-
方法
- 类 sqlalchemy.dialects.oracle.BINARY_FLOAT¶
成员
-
方法
sqlalchemy.dialects.oracle.BINARY_FLOAT.
__init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)¶ 继承自
sqlalchemy.types.Float.__init__
方法Float
构造一个 Float。
- 参数:
precision¶ –
用于 DDL
CREATE TABLE
的数值精度。后端**应该**尝试确保此精度表示通用Float
数据类型的数字位数。注意
对于 Oracle 后端,当渲染 DDL 时,
Float.precision
参数不被接受,因为 Oracle 不支持以小数位数指定 float 精度。 相反,使用 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 十进制数时使用的默认比例。由于小数精度问题,浮点数通常会长得多,大多数浮点数据库类型都没有“比例”的概念,因此默认情况下,float 类型在转换时会寻找前十个小数位。指定此值将覆盖该长度。请注意,MySQL 浮点类型(确实包含“比例”)将使用“比例”作为 decimal_return_scale 的默认值,除非另有指定。
-
方法
- 类 sqlalchemy.dialects.oracle.DATE¶
提供 Oracle DATE 类型。
此类型没有特殊 Python 行为,除了它继承了
DateTime
;这是为了适应 OracleDATE
类型支持时间值的事实。成员
类签名
类
sqlalchemy.dialects.oracle.DATE
(sqlalchemy.dialects.oracle.types._OracleDateLiteralRender
,sqlalchemy.types.DateTime
)
- 类 sqlalchemy.dialects.oracle.FLOAT¶
Oracle FLOAT。
这与
FLOAT
相同,除了接受 Oracle 特定的FLOAT.binary_precision
参数,并且Float.precision
参数不被接受。Oracle FLOAT 类型以“二进制精度”表示精度,默认为 126。对于 REAL 类型,值为 63。此参数不会干净地映射到特定的小数位数,而是大致相当于所需的小数位数除以 0.3103。
版本 2.0 中的新功能。
成员
-
方法
sqlalchemy.dialects.oracle.FLOAT.
__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
-
方法
- 类 sqlalchemy.dialects.oracle.INTERVAL¶
成员
类签名
类
sqlalchemy.dialects.oracle.INTERVAL
(sqlalchemy.types.NativeForEmulated
,sqlalchemy.types._AbstractInterval
)-
方法
sqlalchemy.dialects.oracle.INTERVAL.
__init__(day_precision=None, second_precision=None)¶ 构造一个 INTERVAL。
注意,目前仅支持 DAY TO SECOND 区间。这是因为在可用的 DBAPI 中不支持 YEAR TO MONTH 区间。
-
方法
- 类 sqlalchemy.dialects.oracle.NCLOB¶
成员
-
方法
sqlalchemy.dialects.oracle.NCLOB.
__init__(length: int | None = None, collation: str | None = None)¶ 从
sqlalchemy.types.String.__init__
方法继承String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,在 DDL 和 CAST 表达式中使用的列的长度。如果不会发出任何
CREATE TABLE
,则可以安全地省略。某些数据库可能需要在 DDL 中使用length
,并在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,则会引发异常。值是解释为字节还是字符是特定于数据库的。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
。这些数据类型将确保在数据库上使用正确的类型。
-
方法
-
属性
sqlalchemy.dialects.oracle..
sqlalchemy.dialects.oracle.NVARCHAR2¶ NVARCHAR
的别名。
- 类 sqlalchemy.dialects.oracle.NUMBER¶
- 类 sqlalchemy.dialects.oracle.LONG¶
成员
-
方法
sqlalchemy.dialects.oracle.LONG.
__init__(length: int | None = None, collation: str | None = None)¶ 从
sqlalchemy.types.String.__init__
方法继承String
创建一个保存字符串的类型。
- 参数:
length¶ – 可选,用于 DDL 和 CAST 表达式中的列长度。如果不会发出
CREATE TABLE
,则可以安全地省略。某些数据库可能需要使用 DDL 中的length
,并在发出CREATE TABLE
DDL 时,如果包含没有长度的VARCHAR
,则会引发异常。该值是解释为字节还是字符取决于数据库。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¶
类签名
class
sqlalchemy.dialects.oracle.RAW
(sqlalchemy.types._Binary
)
- class sqlalchemy.dialects.oracle.ROWID¶
Oracle ROWID 类型。
在 cast() 或类似函数中使用时,会生成 ROWID。
- class sqlalchemy.dialects.oracle.TIMESTAMP¶
Oracle 的
TIMESTAMP
实现,支持其他 Oracle 特定模式。版本 2.0 中的新功能。
成员
-
method
sqlalchemy.dialects.oracle.TIMESTAMP.
__init__(timezone: bool = False, local_timezone: bool = False)¶ 构造一个新的
TIMESTAMP
。
-
method
cx_Oracle¶
通过 cx-Oracle 驱动程序支持 Oracle 数据库。
DBAPI¶
cx-Oracle 的文档和下载信息(如果适用)可在以下位置找到:https://oracle.github.io/python-cx_Oracle/
连接¶
连接字符串
oracle+cx_oracle://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]
DSN 与主机名连接¶
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 的主机名部分时,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 中,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 方言接受的参数如下
使用 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 环境变量。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)。
版本 1.3.22 中的更改: 如果由于 Oracle 安装中 v$transaction
的权限问题导致无法读取默认隔离级别,则默认隔离级别将硬编码为“READ COMMITTED”,这是 1.3.21 之前的行为。
字符集和国家语言支持 (NLS) - 在 cx_Oracle 文档中。
特定于 Unicode 的列数据类型¶
核心表达式语言通过使用 Unicode
和 UnicodeText
数据类型来处理 Unicode 数据。这些类型默认对应于 VARCHAR2 和 CLOB Oracle 数据类型。在将这些数据类型与 Unicode 数据一起使用时,预计 Oracle 数据库已配置为使用支持 Unicode 的字符集,并且 NLS_LANG
环境变量已正确设置,以便 VARCHAR2 和 CLOB 数据类型可以容纳数据。
如果 Oracle 数据库未配置为使用 Unicode 字符集,则有两种选择:使用 NCHAR
和 NCLOB
数据类型,或将标志 use_nchar_for_unicode=True
传递给 create_engine()
,这将导致 SQLAlchemy 方言使用 NCHAR/NCLOB 而不是 VARCHAR/CLOB 来表示 Unicode
/ UnicodeText
数据类型。
在版本 1.3 中更改: Unicode
和 UnicodeText
数据类型现在对应于 VARCHAR2
和 CLOB
Oracle 数据类型,除非将 use_nchar_for_unicode=True
传递给方言,当调用 create_engine()
时。
编码错误¶
对于 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 的内置数据类型符号列表,网址为 https://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 的角度记录这些值。字典的键是 BindParameter
对象,它们具有 .key
和 .type
属性
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()
,这只会发生在整个引擎范围内。
不支持两阶段事务(使用 oracledb)¶
由于驱动程序支持不佳,cx_Oracle 下**不支持**两阶段事务。但是,更新的 python-oracledb 方言**确实**支持两阶段事务,应优先使用它。
精确数值¶
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()
engine = create_engine("oracle+cx_oracle://dsn", coerce_to_decimal=False)
coerce_to_decimal
标志仅影响与 Numeric
SQLAlchemy 类型(或此类类型的子类)无关的纯字符串 SQL 语句的结果。
在版本 1.2 中更改: cx_Oracle 的数值处理系统已重新设计,以利用更新的 cx_Oracle 功能以及更好的 outputtypehandler 集成。
python-oracledb¶
通过 python-oracledb 驱动程序支持 Oracle 数据库。
DBAPI¶
python-oracledb 的文档和下载信息(如果适用)可在以下网站获得: https://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。
版本 1.3.22 中的更改: 如果由于 Oracle 安装中 v$transaction
的权限问题导致无法读取默认隔离级别,则默认隔离级别将硬编码为“READ COMMITTED”,这是 1.3.21 之前的行为。
cx_Oracle - cx_Oracle 的所有注释都适用于 oracledb 驱动程序,除了 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")
方言的 asyncio 版本也可以使用 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 的异步版本的支持。
厚模式支持¶
默认情况下,python-oracledb
以瘦模式启动,它不需要在系统中安装 oracle 客户端库。 python-oracledb
驱动程序还支持“厚”模式,其行为类似于 cx_oracle
,并要求安装 Oracle Client Interface (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"
})
版本 1.3.22 中的更改: 如果由于 Oracle 安装中 v$transaction
的权限问题导致无法读取默认隔离级别,则默认隔离级别将硬编码为“READ COMMITTED”,这是 1.3.21 之前的行为。
https://python-oracledb.readthedocs.io/en/latest/api_manual/module.html#oracledb.init_oracle_client
支持两阶段事务¶
oracledb 完全支持两阶段事务。从 oracledb 2.3 开始,瘦模式也支持两阶段事务。两阶段事务的 API 通过 Connection.begin_twophase()
和 Session.twophase
在 Core 级提供,用于透明的 ORM 使用。
在版本 2.0.32 中更改: 添加了对两阶段事务的支持
在版本 2.0.0 中新增: 添加了对 oracledb 驱动程序的支持。
flambé! 龙和炼金术士 图像设计由 Rotem Yaari 创建并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档最后生成时间:2024 年 11 月 8 日星期五上午 8:41:19 EST