The dialect supports several create_engine()
arguments which affect the behavior of the dialect regardless of driver in use.
use_ansi
- 使用ANSI JOIN结构(请参阅Oracle 8一节)。默认为True
。如果False
,则Oracle-8兼容构造用于连接。optimize_limits
- 默认为False
。参见LIMIT / OFFSET部分。use_binds_for_limits
- 默认为True
。参见LIMIT / OFFSET部分。包含整数主键的SQLAlchemy表对象通常被认为具有“自动增量”行为,这意味着它们可以在INSERT时生成它们自己的主键值。由于Oracle没有“自动增量”功能,SQLAlchemy依赖序列来生成这些值。With the Oracle dialect, a sequence must always be explicitly specified to enable autoincrement. 这与假定使用具有自动增量功能的数据库的大多数文档示例不同。要指定序列,请使用传递给Column构造的sqlalchemy.schema.Sequence对象:
t = Table('mytable', metadata,
Column('id', Integer, Sequence('id_seq'), primary_key=True),
Column(...), ...
)
当使用表反射时,这一步也是必需的,即autoload = True:
t = Table('mytable', metadata,
Column('id', Integer, Sequence('id_seq'), primary_key=True),
autoload=True
)
在Oracle中,数据字典使用大写文本表示所有不区分大小写的标识符名称。另一方面,SQLAlchemy认为全小写标识符名称不区分大小写。在模式级通信期间,Oracle方言将所有不区分大小写的标识符转换为和来自这两种格式,例如表和索引的反映。在SQLAlchemy侧使用大写名称表示区分大小写的标识符,并且SQLAlchemy将引用名称 - 这将导致与从Oracle接收的数据字典数据不匹配,因此除非标识名称已真正创建为区分大小写(即使用带引号的名称) ,所有小写字母名称都应该用在SQLAlchemy方面。
Oracle不支持LIMIT或OFFSET关键字。SQLAlchemy与ROWNUM一起使用了一个包装子查询方法。The exact methodology is taken from http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html .
有两个选项会影响其行为:
optimize_limits=True
指定为create_engine()
。use_binds_for_limits=False
指定为create_engine()
。当使用完全不同的窗口查询方法(即ROW_NUMBER()OVER(ORDER BY))来提供LIMIT / OFFSET(注意大多数用户不会观察到此情况)时,某些用户报告了更好的性能。为了适应这种情况,用于LIMIT / OFFSET的方法可以完全替换。请参阅http://www.sqlalchemy.org/trac/wiki/UsageRecipes/WindowFunctionsByDefault中的配方,该配置安装了一个选择编译器,该选择编译器使用窗口函数替代极限/偏移量的生成。
Oracle数据库支持有限的RETURNING形式,以便从INSERT,UPDATE和DELETE语句中检索匹配行的结果集。Oracle的RETURNING..INTO语法只支持返回一行,因为它依赖OUT参数才能正常工作。另外,受支持的DBAPI还有其他限制(请参阅RETURNING Support)。
SQLAlchemy的“隐式返回”功能通常在Oracle后端启用,它在INSERT中使用RETURNING,有时使用UPDATE语句来获取新生成的主键值和其他SQL默认值和表达式。默认情况下,“隐式返回”通常只会获取嵌入到INSERT中的单个nextval(some_seq)
表达式的值,以便在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}
也可以看看
RETURNING Support - 对隐式返回的额外cx_oracle特定限制。
Oracle没有本地ON UPDATE CASCADE功能。基于触发器的解决方案可在http://asktom.oracle.com/tkyte/update_cascade/index.html中找到。
使用SQLAlchemy ORM时,ORM手动发布级联更新的能力有限 - 使用“deferrable = True”,initial ='deferred'“关键字参数指定ForeignKey对象,并在每个关系()上指定”passive_updates = False“。
当检测到Oracle 8时,方言内部将其自身配置为以下行为:
Unicode
时,NVARCHAR2和NCLOB数据类型不再生成为DDL - 而是发出VARCHAR2和CLOB。这是因为这些类型在Oracle 8上似乎不能正常工作,即使它们可用。NVARCHAR
和NCLOB
类型将始终生成NVARCHAR2和NCLOB。When using reflection with Table objects, the dialect can optionally search for tables indicated by synonyms, either in local or remote schemas or accessed over DBLINK, by passing the flag oracle_resolve_synonyms=True
as a keyword argument to the Table
construct:
some_table = Table('some_table', autoload=True,
autoload_with=some_engine,
oracle_resolve_synonyms=True)
设置此标志时,不仅在ALL_TABLES
视图中搜索给定的名称(如some_table
),还会在ALL_SYNONYMS
如果同义词位于并指向DBLINK,则oracle方言知道如何使用DBLINK语法(例如@dblink
)查找表的信息。
oracle_resolve_synonyms
is accepted wherever reflection arguments are accepted, including methods such as MetaData.reflect()
and Inspector.get_columns()
.
如果同义词没有被使用,这个标志应该被禁用。
Oracle没有称为DATETIME
的数据类型,它只有DATE
,它实际上可以存储日期和时间值。出于这个原因,Oracle方言提供了一个类型oracle.DATE
,它是DateTime
的子类。这种类型没有特殊的行为,仅作为这种类型的“标记”出现;此外,当数据库列被反映并且类型被报告为DATE
时,将使用支持时间的oracle.DATE
类型。
版本0.9.4中已更改:将oracle.DATE
添加到DateTime
子类中。这是一个变化,因为以前的版本会将DATE
列反映为types.DATE
,它是Date
的子类。这里唯一的意义是检查在特殊Python翻译中使用的列类型或将模式迁移到其他数据库后端的方案。
CREATE TABLE短语通过与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_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中的新功能
与所有SQLAlchemy方言一样,所有已知可用于Oracle的UPPERCASE类型都可以从顶级方言导入,无论它们源自sqlalchemy.types
还是来自当地方言:
from sqlalchemy.dialects.oracle import \
BFILE, BLOB, CHAR, CLOB, DATE, \
DOUBLE_PRECISION, FLOAT, INTERVAL, LONG, NCLOB, \
NUMBER, NVARCHAR, NVARCHAR2, RAW, TIMESTAMP, VARCHAR, \
VARCHAR2
特定于Oracle的类型或具有特定于Oracle的构造参数如下所示:
sqlalchemy.dialects.oracle.
BFILE
(length=None)¶基础:sqlalchemy.types.LargeBinary
__初始化__ T0> ( T1> 长度=无 T2> ) T3> ¶ T4>
__init__()
method of LargeBinary
构建一个LargeBinary类型。
参数: | length¶ – optional, a length for the column for use in DDL statements, for those binary types that accept a length, such as the MySQL BLOB type. |
---|
sqlalchemy.dialects.oracle。
DATE
( timezone = False ) T5> ¶ T6>Bases: sqlalchemy.types.DateTime
提供oracle DATE类型。
这种类型没有特殊的Python行为,除了它的子类types.DateTime
;这是为了适应Oracle DATE
类型支持时间值的事实。
版本0.9.4中的新功能
__初始化__ T0> ( T1> 时区=假 T2> ) T3> ¶ T4>
DateTime
的 __init__()
构建一个新的DateTime
。
参数: | 时区 ¶ - 布尔值。如果为True,并由后端支持,则会产生'TIMESTAMP WITH TIMEZONE'。对于不支持时区感知时间戳的后端,不起作用。 |
---|
sqlalchemy.dialects.oracle。
DOUBLE_PRECISION
( precision = None, scale = None,asdecimal = None ) ¶sqlalchemy.dialects.oracle。
INTERVAL
( day_precision =无, second_precision =无 T5> ) T6> ¶ T7>sqlalchemy.dialects.oracle.
NCLOB
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__()
method of String
创建一个字符串保存类型。
参数: |
|
---|
sqlalchemy.dialects.oracle。
NUMBER
( precision = None, scale = None,asdecimal = None ) ¶sqlalchemy.dialects.oracle.
LONG
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__
(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False)¶__init__()
method of String
创建一个字符串保存类型。
参数: |
|
---|
sqlalchemy.dialects.oracle。
RAW 长度=无 ) T5> ¶ T6>
基础:sqlalchemy.types._Binary
通过cx-Oracle驱动程序支持Oracle数据库。
有关cx-Oracle的文档和下载信息(如果适用),请访问:http://cx-oracle.sourceforge.net/
与dbname
连接时,使用cx_oracle makedsn()
函数将主机,端口和dbname标记转换为TNS名称。否则,主机令牌将直接作为TNS名称。
其他参数可以指定为URL上的查询字符串参数,也可以指定为create_engine()
的关键字参数:
allow_twophase
- 启用两阶段交易。默认为True
。
arraysize
- 在游标上设置cx_oracle.arraysize值,默认值为50。这个设置对于cx_Oracle很重要,因为LOB对象的内容只能在“实时”行中读取(例如在一批50行内)。
auto_convert_lobs
- 默认为True;请参阅LOB Objects。
auto_setinputsizes
- 为所有绑定参数发出cx_oracle.setinputsizes()调用。这是LOB数据类型所必需的,但可以禁用以减少开销。默认为True
。可以使用exclude_setinputsizes
参数从此过程中排除特定类型。
coerce_to_unicode
- 详细信息请参阅Unicode。
coerce_to_decimal
- 详细请参阅Precision Numerics。
exclude_setinputsizes
- 要从“auto setinputsizes”功能中排除的字符串DBAPI类型名称的元组或列表。此处的类型名称必须与“cx_Oracle”模块名称空间中找到的DBAPI类型匹配,例如cx_Oracle.UNICODE,cx_Oracle.NCLOB等。默认为(STRING, UNICODE)
。
版本0.8中的新功能可以通过exclude_setinputsizes属性从auto_setinputsizes功能中排除特定的DBAPI类型。
mode
- 给出SYSDBA或SYSOPER的字符串值,或者一个整数值。该值仅作为URL查询字符串参数使用。
threaded
- 启用对cx_oracle连接的多线程访问。默认为True
。请注意,这是cx_Oracle DBAPI本身的相反默认值。
service_name
- 使用连接字符串(DSN)与SERVICE_NAME
而不是SID
的选项。当给出database
部分时,不能传递它。例如。 oracle+cx_oracle://scott:tiger@host:1521/?service_name=hr
是一个有效的url。该值仅作为URL查询字符串参数使用。
版本1.0.0中的新功能
从版本5开始,cx_Oracle DBAPI完全支持unicode,并且能够以本地方式将字符串结果作为Python unicode对象返回。
在Python 3中使用时,cx_Oracle将所有字符串作为Python unicode对象(即Python 3中的plain str
)返回。在Python 2中,它将以Python unicode的形式返回那些类型为NVARCHAR
或NCLOB
的列值。对于类型为VARCHAR
或其他非Unicode字符串类型的列值,它将以Python字符串(例如,字节串)的形式返回值。
cx_Oracle SQLAlchemy方言提供了两种不同的选项,用于在Python 2下将VARCHAR
列值作为Python unicode对象返回:
Unicode
type or String
type with convert_unicode=True
is explicitly associated with the result column. 对于任何ORM或核心查询或SQL表达式以及指定输出列类型的text()
结构,情况都是如此,因此绝大多数情况下这不是问题。然而,当发送一个完整的原始字符串给Connection.execute()
时,该输入信息不存在,除非字符串在text()
结构中处理,输入信息。从SQLAlchemy 0.9.2版开始,默认方法是使用SQLAlchemy的输入系统。除非用户明确需要,否则这会使cx_Oracle的昂贵的Python 2方法停用。在Python 3下,SQLAlchemy检测到cx_Oracle本地返回unicode对象,并使用cx_Oracle的系统。
要在Python 2下重新启用cx_Oracle的输出类型处理程序,可以将coerce_to_unicode=True
标志(0.9.4中的新值)传递给create_engine()
:
engine = create_engine("oracle+cx_oracle://dsn", coerce_to_unicode=True)
或者,如果不使用cx_Oracle的本地处理程序,则可以使用text()
功能来运行纯字符串SQL语句并以Python 2 unicode的形式获取VARCHAR
from sqlalchemy import text, Unicode
result = conn.execute(
text("select username from user").columns(username=Unicode))
版本0.9.2更改: cx_Oracle的outputtypehandlers不再用于Python 2中非Unicode数据类型的unicode结果,因为它们被确定为主要的性能瓶颈。而是使用SQLAlchemy自己的unicode工具。
版本0.9.4新增:添加了coerce_to_unicode
标志,以重新启用cx_Oracle的outputtypehandler并恢复到0.9.2之前的行为。
cx_oracle DBAPI支持Oracle已经有限的RETURNING支持的有限子集。通常情况下,结果只能保证最多返回一列;这是SQLAlchemy使用RETURNING获取主键关联序列值的典型情况。由于cx_oracle缺少对更复杂的RETURNING场景所需的OCI_DATA_AT_EXEC API的支持,因此其他列表达式将以非确定的方式导致问题。
因此,通过完全禁用RETURNING支持可以提高稳定性;否则SQLAlchemy将使用RETURNING来获取新序列生成的主键。如RETURNING Support所示:
engine = create_engine("oracle://scott:tiger@dsn",
implicit_returning=False)
cx_oracle使用cx_oracle.LOB对象返回Oracle LOB。SQLAlchemy将它们转换为字符串,以便Binary类型的接口与其他后端的接口一致,并且在result.fetchmany()和result.fetchall()等场景中不需要与活动游标的链接。这意味着默认情况下,LOB对象无条件地被SQLAlchemy完全取出,并且与活动光标的链接被中断。
要禁用此处理,请将auto_convert_lobs=False
传递给create_engine()
。
两阶段事务是使用XA事务实现的,并且从SQLAlchemy 0.8.0b2,0.7.10开始,已知以最新版本的cx_Oracle的基本工作方式工作。但是,该机制尚未被认为是有力的,应该仍然被视为实验性的。
特别是最近5.1.2的cx_Oracle DBAPI有一个关于两个阶段的错误,这个阶段阻止了一个特定的DBAPI连接在准备好的事务中以及传统的DBAPI使用模式中始终可用;因此,一旦通过Connection.begin_prepared()
使用了特定的连接,底层DBAPI连接的所有后续用法都必须位于准备事务的上下文内。
Engine
的默认行为是维护一个DBAPI连接池。因此,由于上述故障,已在两阶段操作中使用并返回到池的DBAPI连接在非两阶段上下文中将不可用。为了避免这种情况,应用程序可以做出以下几种选择之一:
NullPool
禁用连接池Engine
仅用于两阶段操作。绑定到包含twophase=True
的ORM Session
的Engine
将一致使用两阶段事务样式。Connection.detach()
方法从连接池中清除正在使用的DBAPI连接。在0.8.0b2,0.7.10版本中更改:已执行并测试了对cx_oracle准备事务的支持。
SQLAlchemy方言经历了很多步骤以确保十进制数字的发送和接收完全准确。可调用的“outputtypehandler”与每个检测数字类型并将其作为字符串值接收的cx_oracle连接对象相关联,而不是直接接收Python float
,然后将其传递给Python Decimal
在cx_oracle方言下的Numeric
和Float
类型意识到这种行为,并且强制Decimal
到float
如果asdecimal
标志为False
(默认在Float
,Numeric
上可选)。
由于处理程序首先在所有情况下都强制Decimal
,该功能会显着影响性能。如果不需要精度数字,则可以通过将标志coerce_to_decimal=False
传递给create_engine()
来禁用十进制处理:
engine = create_engine("oracle+cx_oracle://dsn", coerce_to_decimal=False)
New in version 0.7.6: Add the coerce_to_decimal
flag.
性能的另一种替代方法是使用cdecimal库;有关其他注意事项,请参阅Numeric
。
该处理程序试图使用结果集列的“精度”和“比例”属性来最好地确定后续输入值是否应该被接收为Decimal
而不是int(在这种情况下,不会添加处理)。There are several scenarios where OCI does not provide unambiguous data as to the numeric type, including some situations where individual rows may return a combination of floating point and integer values. 已经观察到“精确度”和“比例”的某些值来确定这种情况。当它发生时,outputtypehandler接收到一个字符串,然后传递给一个处理函数,该函数检测每个返回值是否存在小数点,如果是,则转换为Decimal
,否则转换为int。The intention is that simple int-based statements like “SELECT my_seq.nextval() FROM DUAL” continue to return ints and not Decimal
objects, and that any kind of floating point value is received as a string so that there is no floating point loss of precision.
“存在小数点”逻辑本身对区域设置也很敏感。在OCI下,这由NLS_LANG环境变量控制。首次连接时,方言进行测试以确定当前的“十进制”字符,对于欧洲语言环境,该字符可以是逗号“,”。从这一点开始,outputtypehandler使用该字符来表示小数点。请注意,在处理带有不使用句点“。”作为十进制字符的区域设置的数字时,需要cx_oracle 5.0.3或更高版本。
在版本0.6.6中更改: outputtypehandler支持locale使用逗号“,”字符表示小数点的情况。
通过zxJDBC为Jython驱动程序支持Oracle数据库。
注意
当前版本的SQLAlchemy不支持Jython。zxjdbc方言应该被认为是实验性的。
此数据库的驱动程序可在以下网址找到:http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html