甲骨文公司
Support for the Oracle database.
The following table summarizes current support levels for database release versions.
自动增量行为
通常假定包含整数主键的SQLAlchemy表对象具有“自动递增”行为,这意味着它们可以在插入时生成自己的主键值。对于在Oracle中使用,有两个选项可用,即使用标识列(仅限Oracle 12及更高版本)或序列与列的关联。
指定生成为标识(Oracle 12及更高版本)
从版本12开始,Oracle可以使用 Identity
要指定自动递增行为:
t = Table('mytable', metadata, Column('id', Integer, Identity(start=3), primary_key=True), Column(...), ... )
上面的创建表 Table
对象为:
CREATE TABLE mytable ( id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 3), ..., PRIMARY KEY (id) )
这个 Identity
对象支持许多选项来控制列的“自动递增”行为,如起始值、递增值等。除了标准选项外,Oracle还支持设置 Identity.always
到 None
要使用默认的生成模式,在DDL中呈现为IDENTITY。它还支持设置 Identity.on_null
到 True
将ON NULL与“默认”标识列一起指定。
使用序列(所有Oracle版本)
旧版本的Oracle没有“autoincrement”特性,SQLAlchemy依赖序列来生成这些值。对于较旧的Oracle版本, 必须始终显式指定序列才能启用自动增量 . 这与大多数文档示例不同,这些文档示例假定使用具有自动增量功能的数据库。要指定序列,请使用传递给列构造的sqlachemy.schema.sequence对象::
t = Table('mytable', metadata, Column('id', Integer, Sequence('id_seq'), primary_key=True), Column(...), ... )
使用表反射时也需要此步骤,即AUTLOAD_WITH=ENGINE::
t = Table('mytable', metadata, Column('id', Integer, Sequence('id_seq'), primary_key=True), autoload_with=engine )
在 1.4 版更改: 补充 Identity
在a中构造 Column
指定自动递增列的选项。
事务隔离级别/自动提交
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
注解
的实现 Connection.get_isolation_level()
由Oracle方言实现的方法必须使用Oracle LOCAL_TRANSACTION_ID函数强制启动事务;否则没有任何级别通常是可读的。
此外, Connection.get_isolation_level()
方法将引发异常,如果 v$transaction
由于权限或其他原因,视图不可用,这在Oracle安装中很常见。
CX_ORACLE方言尝试调用 Connection.get_isolation_level()
当方言首次连接到数据库以获取“默认”隔离级别时,调用。此缺省级别是必需的,以便在使用临时修改连接后可以在连接上重置该级别 Connection.execution_options()
方法。在常见情况下, Connection.get_isolation_level()
方法引发异常,原因是 v$transaction
由于不可读以及任何其他与数据库相关的故障,该级别被假定为“已提交读取”。对于此初始首次连接条件不会发出警告,因为预计这将是Oracle数据库的常见限制。
1.3.16 新版功能: 向cx_oracle方言添加了对AUTOCOMMIT的支持以及默认隔离级别的概念
1.3.21 新版功能: 添加了对SERIALIZABLE以及隔离级别实时读取的支持。
在 1.3.22 版更改: 在Oracle安装中常见的由于v$TRANSACTION视图上的权限而导致默认隔离级别无法读取的情况下,默认隔离级别被硬编码为“READ COMMITTED”,这是1.3.21之前的行为。
参见
标识符大小写
在Oracle中,数据字典使用大写文本表示所有不区分大小写的标识符名称。另一方面,SQLAlchemy认为所有小写标识符名称都不区分大小写。在模式级通信期间,Oracle方言将所有不区分大小写的标识符转换为这两种格式,例如表和索引的反射。在sqlAlchemy端使用大写名称表示区分大小写的标识符,sqlAlchemy将引用该名称-这将导致与从Oracle接收的数据字典数据不匹配,因此,除非标识符名称真正创建为区分大小写(即使用带引号的名称),否则所有小写名称都应在sqlAlchemy上使用。一边。
最大标识符长度
自Oracle Server 12.2版起,Oracle已更改默认的最大标识符长度。在这个版本之前,长度是30,对于12.2及更高版本,现在是128。此更改会影响生成的SQL标签名称区域中的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)
在SELECT语句中生成匿名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 server 12.2版或更高版本上运行SQLAlchemy 1.4之前版本的应用程序将面临数据库迁移的情况,即希望对以前生成的较短长度的名称“删除约束”。当标识符长度更改而不首先调整索引或约束的名称时,此迁移将失败。强烈建议此类应用程序利用 create_engine.max_identifier_length
为了保持对截断名称生成的控制,并在更改此值时全面检查和测试登台环境中的所有数据库迁移,以确保已减轻此更改的影响。
在 1.4 版更改: Oracle的默认最大标识符长度为128个字符,如果检测到旧版本的Oracle server(兼容版本<12.2),则在第一次连接时将其调整为30个字符。
极限/偏移支撑
直到12c版,Oracle才对LIMIT和OFFSET提供直接支持。为了在从8系列开始的所有广泛使用的Oracle版本中实现这种行为,SQLAlchemy当前使用ROWNUM来实现LIMIT/OFFSET;准确的方法来自https://blogs.oracle.com/oraclemagazine/on-rownum-and-limiting-results.
当前只有一个选项可以影响其行为:
默认情况下不使用“FIRST_ROWS()”优化关键字。要启用此优化指令的使用,请指定
optimize_limits=True
到create_engine()
.
在 1.4 版更改: Oracle方言使用“后编译”方案呈现限制/偏移整数值,该方案在将语句传递给游标执行之前直接呈现整数。这个 use_binds_for_limits
旗帜不再有效。
参见
新的“后编译”绑定参数用于Oracle、SQL Server中的限制/偏移 .
支持更改行号策略,其中包括一个使用 row_number()
窗口函数以及使用oracle12c“FETCH FIRST N ROW/OFFSET N ROWS”关键字的函数可能会在将来的版本中添加。
返回支持
Oracle数据库支持有限的返回形式,以便从insert、update和delete语句中检索匹配行的结果集。Oracle的返回..in to语法只支持返回一行,因为它依赖out参数才能运行。此外,受支持的DBAPI还有进一步的限制(请参见 返回支持 )
SQLAlchemy的“隐式返回”功能通常在Oracle后端启用,它使用在insert中返回,有时还使用update语句来获取新生成的主键值和其他SQL默认值和表达式。默认情况下,“隐式返回”通常只获取单个 nextval(some_seq)
嵌入到insert中的表达式,以便在insert语句中增加序列并同时返回值。要全面禁用此功能,请指定 implicit_returning=False
到 create_engine()
::
engine = create_engine("oracle://scott:tiger@dsn", implicit_returning=False)
隐式返回也可以作为表选项逐个表禁用:
# Core Table my_table = Table("my_table", metadata, ..., implicit_returning=False) # declarative class MyClass(Base): __tablename__ = 'my_table' __table_args__ = {"implicit_returning": False}
参见
返回支持 -对隐式返回的其他cx_Oracle特定限制。
更新层叠时
Oracle没有原生更新时级联功能。https://asktom.oracle.com/tkyte/update_cascade/index.html上提供了基于触发器的解决方案。
使用SQLAlchemy ORM时,ORM手动发出级联更新的能力有限-使用“deferrable=true,initially='deferred'”关键字参数指定foreignkey对象,并在每个关系()上指定“passive_updates=false”。
Oracle 8兼容性
当检测到Oracle 8时,方言在内部将自身配置为以下行为:
“使用”ansi标志设置为false。这样做的效果是将所有连接短语转换为WHERE子句,如果是左外部连接,则使用Oracle的(+)运算符。
当
Unicode
使用-varchar2和clob。这是因为这些类型在Oracle8上似乎不能正常工作,即使它们是可用的。这个NVARCHAR
和NCLOB
类型将始终生成nvarchar2和nclob。当使用cx_oracle时,“本机Unicode”模式被禁用,即sqlAlchemy在作为绑定参数传入之前将所有python unicode对象编码为“string”。
同义词/dblink反射
当对表对象使用反射时,方言可以通过传递标志来选择性地搜索由同义词表示的表,无论是在本地模式还是远程模式中,还是通过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方言可以返回有关外键、唯一和检查约束以及表上索引的信息。
有关这些约束的原始信息可以使用 Inspector.get_foreign_keys()
, Inspector.get_unique_constraints()
, Inspector.get_check_constraints()
和 Inspector.get_indexes()
.
在 1.2 版更改: Oracle方言现在可以反映唯一和检查约束。
使用反射时 Table
水平 Table
还将包括这些约束。
注意以下注意事项:
当使用
Inspector.get_check_constraints()
方法,Oracle为指定“not null”的列生成一个特殊的“is not null”约束。这个约束是 not 默认情况下返回;要包含“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
,唯一约束将 not 可作为UniqueConstraint
对象,因为在大多数情况下,Oracle使用唯一索引来镜像唯一约束(当两个或多个唯一约束表示同一列时似乎是例外);Table
而是用Index
与unique=True
标志集。Oracle为表的主键创建隐式索引;此索引是 排除 从所有索引结果。
为索引反映的列列表将不包括以sys_nc开头的列名称。
带有系统/系统辅助表空间的表名
这个 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://scott:tiger@xe", exclude_tablespaces=["SYSAUX", "SOME_TABLESPACE"])
1.1 新版功能.
日期时间兼容性
Oracle没有已知的数据类型 DATETIME
相反,它只有 DATE
,它实际上可以存储日期和时间值。因此,Oracle方言提供了 DATE
它是 DateTime
. 此类型没有特殊行为,并且仅作为此类型的“标记”存在;此外,当数据库列被反映并且该类型被报告为 DATE
,时间支持 DATE
使用类型。
在 0.9.4 版更改: 补充 DATE
子类 DateTime
. 这是一个更改,因为以前的版本将反映 DATE
列为 DATE
,哪个子类 Date
. 这里唯一的意义是,对于正在检查列类型的方案,这些列用于特殊的Python翻译或用于将模式迁移到其他数据库后端。
Oracle表选项
create table短语与Oracle一起支持以下选项 Table
构建:
ON COMMIT
::Table( "some_table", metadata, ..., prefixes=['GLOBAL TEMPORARY'], oracle_on_commit='PRESERVE ROWS')
1.0.0 新版功能.
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.
1.0.0 新版功能.
Oracle特定索引选项
位图索引
您可以指定 oracle_bitmap
创建位图索引而不是B树索引的参数:
Index('my_index', my_table.c.data, oracle_bitmap=True)
位图索引不能是唯一的,也不能压缩。SQLAlchemy不会检查这样的限制,只有数据库会检查。
1.0.0 新版功能.
索引压缩
对于包含大量重复值的索引,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
使用默认值(非唯一索引的所有列,唯一索引的最后一列除外)。
1.0.0 新版功能.
Oracle数据类型
与所有的sqlAlchemy方言一样,已知对Oracle有效的所有大写类型都可以从顶级方言导入,无论它们是否源自 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特定构造参数的类型如下:
Object Name | Description |
---|---|
提供Oracle日期类型。 | |
- class sqlalchemy.dialects.oracle.BFILE(length=None)
Support for the Oracle database via the cx-Oracle driver.
DBAPI
Documentation and download information (if applicable) for cx-Oracle is available at: https://oracle.github.io/python-cx_Oracle/
Connecting
Connect String:
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 syntax ,然后在SQLAlChemy中使用
service_name
查询字符串参数::engine = create_engine("oracle+cx_oracle://scott:tiger@hostname:port/?service_name=myservice&encoding=UTF-8&nencoding=UTF-8")
这个 full Easy Connect syntax 不受支持。相反,请使用
tnsnames.ora
文件并使用DSN连接。与tnsnames.ora或Oracle云的连接
或者,如果没有端口、数据库名称或
service_name
则方言将使用Oracle DSN“连接字符串”。这将URL的“hostname”部分作为数据源名称。例如,如果tnsnames.ora
文件包含一个 Net Service Name 的myalias
详情如下:myalias = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.example.com)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orclpdb1) ) )
CX_ORACLE方言在以下情况下连接到此数据库服务
myalias
是URL的主机名部分,不指定端口、数据库名称或service_name
::engine = create_engine("oracle+cx_oracle://scott:tiger@myalias/?encoding=UTF-8&nencoding=UTF-8")
Oracle Cloud的用户应使用此语法,并按照CX_ORACLE文档中所示配置云Wallet Connecting to Autononmous Databases 。
SID连接
要使用Oracle过时的SID连接语法,可以在URL的“数据库名”部分传递SID,如下所示:
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)))'
传递cxu Oracle connect参数
附加的连接参数通常可以通过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参数。将参数直接传递给
.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 } )
请注意,的默认值为
encoding
和nencoding
在CX_ORACLE 8.0中更改为“UTF-8”,因此在使用该版本或更高版本时可以省略这些参数。SQLAlchemy cx_Oracle方言在驱动程序之外使用的选项
还有一些选项被sqlacalchemy cx_Oracle方言本身所使用。这些选项总是直接传递给
create_engine()
,例如:e = create_engine( "oracle+cx_oracle://user:pass@dsn", coerce_to_unicode=False)
cx_Oracle方言接受的参数如下:
arraysize
-在光标上设置cx_oracle.arraysize值,默认值为50。对于cx_oracle,此设置非常重要,因为lob对象的内容只能在“活动”行中读取(例如,在一批50行中)。auto_convert_lobs
-默认为true;请参见 目标对象 .coerce_to_unicode
-见 统一码 细节。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://", creator=pool.acquire, poolclass=NullPool)
然后,在CX_ORACLE的池处理连接池的情况下,可以正常使用上述引擎::
with engine.connect() as conn: print(conn.scalar("select 1 FROM dual"))
除了为多用户应用程序提供可扩展的解决方案外,CX_ORACLE会话池还支持一些Oracle功能,如DRCP和 Application Continuity 。
使用Oracle数据库驻留连接池(DRCP)
在使用Oracle的 DRCP 最佳实践是在从SessionPool获取连接时传递连接类和“纯度”。请参阅 cx_Oracle DRCP documentation 。
这可以通过包装来实现
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://", creator=creator, poolclass=NullPool)
然后,在CX_ORACLE处理会话池并且Oracle数据库另外使用DRCP::的情况下,可以正常使用上述引擎
with engine.connect() as conn: print(conn.scalar("select 1 FROM dual"))
统一码
与python3下的所有dbapi一样,所有字符串本质上都是Unicode字符串。在python2下,cx峈Oracle还直接支持Python Unicode对象。但是,在所有情况下,驱动程序都需要显式的编码配置。
确保正确的客户端编码
为几乎所有与Oracle相关的软件建立客户端编码的长期接受的标准是通过 NLS_LANG 环境变量。与大多数其他Oracle驱动程序一样,cxU Oracle将使用此环境变量作为其编码配置的源。此变量的格式是特殊的;典型的值是
AMERICAN_AMERICA.AL32UTF8
.除了支持Oracle U pass的编程驱动程序之外,还有一种可选的方法
encoding
和nencoding
直接将参数.connect()
功能。这些可以在URL中显示,如下所示:engine = create_engine("oracle+cx_oracle://scott:tiger@orclpdb/?encoding=UTF-8&nencoding=UTF-8")
关于
encoding
和nencoding
参数,请参考 Characters Sets and National Language Support (NLS) .参见
Characters Sets and National Language Support (NLS) -在cx_Oracle文档中。
Unicode特定的列数据类型
核心表达式语言通过使用
Unicode
和UnicodeText
数据类型。默认情况下,这些类型对应于VARCHAR2和CLOB Oracle数据类型。当将这些数据类型与Unicode数据一起使用时,Oracle数据库应该配置有一个支持Unicode的字符集,并且NLS_LANG
环境变量被适当地设置,以便varchar2和clob数据类型能够容纳数据。如果Oracle数据库未配置Unicode字符集,则两个选项将使用
NCHAR
和NCLOB
显式的数据类型,或传递标志use_nchar_for_unicode=True
到create_engine()
,这将导致sqlAlchemy方言将nchar/nclob用于Unicode
/UnicodeText
数据类型,而不是varchar/clob。在 1.3 版更改: 这个
Unicode
和UnicodeText
数据类型现在对应于VARCHAR2
和CLOB
Oracle数据类型,除非use_nchar_for_unicode=True
当create_engine()
被称为。python2下结果行的Unicode强制
当获取包含字符串的结果集时,在python 3下,cx_Oracle DBAPI将所有字符串作为python unicode对象返回,因为python 3只有unicode字符串类型。对于从varchar2、char、clob、nchar、nclob等数据类型中提取的数据,会发生这种情况。为了在python 2下提供交叉兼容性,sqlachemy cx_oracle方言也会将unicode转换添加到python 2下的字符串数据中。历史上,这使用了由cx_oracle提供但被发现没有性能的转换器;sqlAlchemy自己的转换器用于python 2下的字符串到unicode转换。要禁用varchar2、char和clob的python 2 unicode转换,标志
coerce_to_unicode=False
可以传递给create_engine()
.在 1.3 版更改: 在python 2下,默认情况下,Unicode转换应用于所有字符串值。这个
coerce_to_unicode
现在默认为true,可以设置为false以禁用以varchar2/char/clob数据形式传递的字符串的Unicode强制。编码错误
对于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方言的用户为 强烈鼓励 在https://cx-oracle.readthedocs.io/en/latest/api_manual/module.html#database-types.上阅读CX_ORACLE的内置数据类型符号列表请注意,在某些情况下,使用这些类型与不使用这些类型相比,性能可能会显著降低,特别是在指定
cx_Oracle.CLOB
。在炼金术方面,
DialectEvents.do_setinputsizes()
事件既可用于setinputsizes步骤的运行时可见性(例如日志记录),也可用于完全控制setinputsizes()
按语句使用。1.2.9 新版功能: 补充
DialectEvents.setinputsizes()
示例1-记录所有setinputsizes调用
下面的示例说明如何在将中间值转换为原始值之前,从SQLAlchemy的角度记录它们。
setinputsizes()
参数字典。字典的关键是BindParameter
具有.key
和A.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的所有绑定
这个
CLOB
cx_oracle中的数据类型会产生很大的性能开销,但是默认情况下会为Text
在sqlacalchemy 1.2系列中键入。此设置可以修改如下: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]
返回支持
cx_Oracle方言实现使用out参数返回。方言支持完全返回,但建议使用cx_oracle 6以获得完全支持。
目标对象
cx_oracle使用cx_oracle.lob对象返回Oracle LOB。sqlAlchemy将这些转换为字符串,以便二进制类型的接口与其他后端的接口一致,后者发生在cx_Oracle OutputTypeHandler中。
cx_Oracle在版本6之前将要求在读取新批行之前读取lob对象,这由
cursor.arraysize
. 从6系列开始,此限制已解除。不过,由于sqlacalchemy预先读取这些LOB,所以无论如何都可以避免这个问题。要禁用方言的自动“read()”功能,标志
auto_convert_lobs=False
可传递给create_engine()
. 在cx-oracle 5系列中,关闭此标志意味着如果在提取过时的lob对象时不读取它,则有可能读取该对象。使用cx_Oracle 6,可以解决此问题。在 1.2 版更改: LOB处理系统在内部被大大简化以使用outputtypehanders,不再使用备用的“缓冲”结果集对象。
不支持两阶段事务
两阶段交易是 不支持 在cx_Oracle下,由于驱动程序支持不佳。从cx_oracle 6.0b1开始,两阶段事务的接口已更改为更直接地传递到底层OCI层,自动化程度更低。支持此系统的附加逻辑未在SQLAlchemy中实现。
精确数字
sqlAlchemy的numeric类型可以像python那样处理接收和返回值
Decimal
对象或浮动对象。当ANumeric
对象或子类,如Float
,DOUBLE_PRECISION
等正在使用中,Numeric.asdecimal
标志确定是否应将值强制为Decimal
返回时,或作为浮动对象返回。为了使甲骨文下的事情更加复杂,甲骨文的NUMBER
如果“scale”为零,类型还可以表示整数值,因此Oracle特定NUMBER
类型也考虑到这一点。cx-oracle方言广泛使用连接级和光标级的“outputtypehander”可调用文件,以便按要求强制使用数值。这些可调用物是特定于
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
标志仅影响纯字符串SQL语句的结果,否则这些语句与Numeric
SQLAlChemy类型(或此类类型的子类)。在 1.2 版更改: cx_-oracle的数字处理系统已经重新设计,以利用新的cx_-oracle功能以及更好地集成输出类型处理程序。