Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

甲骨文公司

Support for the Oracle database.

The following table summarizes current support levels for database release versions.

支持的Oracle版本

Support type

Versions

Fully tested in CI

11.2, 18c

Normal support

11+

Best effort

8+

DBAPI Support

The following dialect/DBAPI options are available. Please refer to individual DBAPI sections for connect information.

自动增量行为

通常假定包含整数主键的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.alwaysNone 要使用默认的生成模式,在DDL中呈现为IDENTITY。它还支持设置 Identity.on_nullTrue 将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 COMMITTEDSERIALIZABLE ,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=Truecreate_engine() .

在 1.4 版更改: Oracle方言使用“后编译”方案呈现限制/偏移整数值,该方案在将语句传递给游标执行之前直接呈现整数。这个 use_binds_for_limits 旗帜不再有效。

支持更改行号策略,其中包括一个使用 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=Falsecreate_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上似乎不能正常工作,即使它们是可用的。这个 NVARCHARNCLOB 类型将始终生成nvarchar2和nclob。

  • 当使用cx_oracle时,“本机Unicode”模式被禁用,即sqlAlchemy在作为绑定参数传入之前将所有python unicode对象编码为“string”。

约束反射

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 而是用 Indexunique=True 标志集。

  • Oracle为表的主键创建隐式索引;此索引是 排除 从所有索引结果。

  • 为索引反映的列列表将不包括以sys_nc开头的列名称。

带有系统/系统辅助表空间的表名

这个 Inspector.get_table_names()Inspector.get_temp_table_names() 方法分别返回当前引擎的表名列表。这些方法也是操作中发生的反射的一部分,例如 MetaData.reflect() . 默认情况下,这些操作不包括 SYSTEMSYSAUX 操作中的表空间。为了更改此设置,可以在引擎级别使用 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

BFILE

DATE

提供Oracle日期类型。

DOUBLE_PRECISION

INTERVAL

LONG

NCLOB

NUMBER

RAW

class sqlalchemy.dialects.oracle.BFILE(length=None)
method sqlalchemy.dialects.oracle.BFILE.__init__(length=None)

inherited from the sqlalchemy.types.LargeBinary.__init__ method of LargeBinary

构造一个大二进制类型。

参数

length -- 可选,用于ddl语句中的列的长度,用于接受长度的二进制类型,例如mysql blob类型。

class sqlalchemy.dialects.oracle.DATE(timezone=False)

提供Oracle日期类型。

此类型没有特殊的python行为,只是它的子类 DateTime 这是为了适应甲骨文 DATE 类型支持时间值。

0.9.4 新版功能.

method sqlalchemy.dialects.oracle.DATE.__init__(timezone=False)

inherited from the sqlalchemy.types.DateTime.__init__ method of DateTime

构建新的 DateTime .

参数

timezone -- 布尔函数。指示日期时间类型应启用时区支持(如果在 base date/time-holding type only . 建议使用 TIMESTAMP 当使用此标志时直接使用数据类型,因为某些数据库包含独立的通用日期/时间保持类型,这与支持时区的时间戳数据类型不同,例如Oracle。

class sqlalchemy.dialects.oracle.DOUBLE_PRECISION(precision=None, asdecimal=False, decimal_return_scale=None)
method sqlalchemy.dialects.oracle.DOUBLE_PRECISION.__init__(precision=None, asdecimal=False, decimal_return_scale=None)

inherited from the sqlalchemy.types.Float.__init__ method of Float

构造一个浮点。

参数
  • precision -- 用于DDL的数字精度 CREATE TABLE .

  • asdecimal -- 与…相同的标志 Numeric ,但默认为 False . 请注意,将此标志设置为 True 导致浮点转换。

  • decimal_return_scale -- 从浮点转换为python小数时使用的默认小数位数。由于小数点不准确,浮点值通常要长得多,而且大多数浮点数据库类型没有“小数位数”的概念,因此默认情况下,浮点类型在转换时查找前十位小数。指定此值将覆盖该长度。注意,如果没有另外指定,mysql float类型(包括“scale”)将使用“scale”作为decimal_return_scale的默认值。…版本已添加::0.9.0

class sqlalchemy.dialects.oracle.INTERVAL(day_precision=None, second_precision=None)

类签名

class sqlalchemy.dialects.oracle.INTERVAL (sqlalchemy.types.NativeForEmulated, sqlalchemy.types._AbstractInterval)

method sqlalchemy.dialects.oracle.INTERVAL.__init__(day_precision=None, second_precision=None)

构造一个间隔。

请注意,目前只支持日到秒的时间间隔。这是由于在可用的dbapi中缺少对年到月间隔的支持。

参数
  • day_precision -- 日精度值。这是要为“日”字段存储的位数。默认为“2”

  • second_precision -- 第二个精度值。这是为小数秒字段存储的位数。默认为“6”。

class sqlalchemy.dialects.oracle.NCLOB(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False, _expect_unicode=False)
method sqlalchemy.dialects.oracle.NCLOB.__init__(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False, _expect_unicode=False)

inherited from the sqlalchemy.types.String.__init__ method of String

创建字符串保持类型。

参数
  • length -- 可选,用于DDL和CAST表达式的列的长度。如果没有,可以安全地省略 CREATE TABLE 将发布。某些数据库可能需要 length 在DDL中使用,并在 CREATE TABLE 如果 VARCHAR 不包括长度。该值是否解释为字节或字符是特定于数据库的。

  • collation -- 可选,在DDL和CAST表达式中使用的列级排序规则。使用SQLite、MySQL和PostgreSQL支持的COLLATE关键字呈现。E、 g.:>>>从sqlalchemy import cast,select,String>>>打印(select(cast('some String',String(collation='utf8')))select cast(:param_1 AS VARCHAR COLLATE utf8)AS anon_

  • convert_unicode -- 当设置为 True , the String 类型将假定输入将作为python 2下的python unicode对象传递,结果将作为python unicode对象返回。在DBAPI在python 2下不支持pythonUnicode的罕见情况下,sqlachemy将在字符串上使用自己的编码器/解码器功能,参考 create_engine.encoding 参数参数传递给 create_engine() 作为编码。…已弃用::1.3 String.convert_unicode 参数已弃用,将在将来的版本中删除。所有现代DBAPI现在都直接支持PythonUnicode,而这个参数是不必要的。对于极为罕见的情况,python unicode将由sqlachemy在后端进行编码/解码, does 本机支持python unicode,字符串值 "force" 可以在此处传递,这将导致无条件使用SQLAlchemy的编码/解码服务。…注意::sqlacalchemy的unicode转换标志和特性只适用于python 2;在python 3中,所有字符串对象都是unicode对象。出于这个原因,以及事实上,几乎所有现代DBAPI现在都支持Unicode,即使在Python2下, String.convert_unicode 标志本身就是一个遗留功能。…注:在绝大多数情况下, UnicodeUnicodeText 数据类型应用于 Column 它期望存储非ascii数据。这些数据类型将确保在数据库端使用正确的类型,并在Python2下设置正确的Unicode行为。。另请参见: create_engine.convert_unicode - Engine 宽参数

  • unicode_error -- 可选,用于处理Unicode转换错误的方法。表现得像 errors 标准库的关键字参数 string.decode() 函数,要求 String.convert_unicode 设置为 "force" …已弃用::1.3 String.unicode_errors 参数已弃用,将在将来的版本中删除。这个参数对于现代的python dbapis来说是不必要的,并且会显著降低性能。

class sqlalchemy.dialects.oracle.NUMBER(precision=None, scale=None, asdecimal=None)
method sqlalchemy.dialects.oracle.NUMBER.__init__(precision=None, scale=None, asdecimal=None)

构造一个数字。

参数
  • precision -- 用于DDL的数字精度 CREATE TABLE .

  • scale -- DDL中使用的数字刻度 CREATE TABLE .

  • asdecimal -- 默认为真。返回值是否应作为python decimal对象或float发送。不同的dbapis根据数据类型发送一个或另一个-数字类型将确保返回值在dbapis中是一致的。

  • decimal_return_scale -- 从浮点转换为python小数时使用的默认小数位数。由于小数点不准确,浮点值通常要长得多,而且大多数浮点数据库类型都没有“小数位数”的概念,因此默认情况下,浮点类型在转换时查找前十位小数。指定此值将覆盖该长度。包含显式“.scale”值的类型,如基 Numeric 以及mysql float类型,将使用“.scale”值作为decimal_return_scale的默认值,如果没有另外指定。…添加的版本:0.9.0

当使用 Numeric 类型,应注意确保asdecimal设置适用于正在使用的dbapi-当numeric应用decimal->float或float->decimal的转换时,此转换会对收到的所有结果列产生额外的性能开销。

本地返回十进制(例如psycopg2)的dbapis在设置为 True ,因为本机十进制转换减少了浮点问题的数量,并且数字类型本身不需要应用任何进一步的转换。但是,另一个DBAPI以本机方式返回浮动 will 产生额外的转换开销,并且仍然会受到浮点数据丢失的影响-在这种情况下 asdecimal=False 将至少移除额外的转换开销。

class sqlalchemy.dialects.oracle.LONG(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False, _expect_unicode=False)
method sqlalchemy.dialects.oracle.LONG.__init__(length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False, _expect_unicode=False)

inherited from the sqlalchemy.types.String.__init__ method of String

创建字符串保持类型。

参数
  • length -- 可选,用于DDL和CAST表达式的列的长度。如果没有,可以安全地省略 CREATE TABLE 将发布。某些数据库可能需要 length 在DDL中使用,并在 CREATE TABLE 如果 VARCHAR 不包括长度。该值是否解释为字节或字符是特定于数据库的。

  • collation -- 可选,在DDL和CAST表达式中使用的列级排序规则。使用SQLite、MySQL和PostgreSQL支持的COLLATE关键字呈现。E、 g.:>>>从sqlalchemy import cast,select,String>>>打印(select(cast('some String',String(collation='utf8')))select cast(:param_1 AS VARCHAR COLLATE utf8)AS anon_

  • convert_unicode -- 当设置为 True , the String 类型将假定输入将作为python 2下的python unicode对象传递,结果将作为python unicode对象返回。在DBAPI在python 2下不支持pythonUnicode的罕见情况下,sqlachemy将在字符串上使用自己的编码器/解码器功能,参考 create_engine.encoding 参数参数传递给 create_engine() 作为编码。…已弃用::1.3 String.convert_unicode 参数已弃用,将在将来的版本中删除。所有现代DBAPI现在都直接支持PythonUnicode,而这个参数是不必要的。对于极为罕见的情况,python unicode将由sqlachemy在后端进行编码/解码, does 本机支持python unicode,字符串值 "force" 可以在此处传递,这将导致无条件使用SQLAlchemy的编码/解码服务。…注意::sqlacalchemy的unicode转换标志和特性只适用于python 2;在python 3中,所有字符串对象都是unicode对象。出于这个原因,以及事实上,几乎所有现代DBAPI现在都支持Unicode,即使在Python2下, String.convert_unicode 标志本身就是一个遗留功能。…注:在绝大多数情况下, UnicodeUnicodeText 数据类型应用于 Column 它期望存储非ascii数据。这些数据类型将确保在数据库端使用正确的类型,并在Python2下设置正确的Unicode行为。。另请参见: create_engine.convert_unicode - Engine 宽参数

  • unicode_error -- 可选,用于处理Unicode转换错误的方法。表现得像 errors 标准库的关键字参数 string.decode() 函数,要求 String.convert_unicode 设置为 "force" …已弃用::1.3 String.unicode_errors 参数已弃用,将在将来的版本中删除。这个参数对于现代的python dbapis来说是不必要的,并且会显著降低性能。

class sqlalchemy.dialects.oracle.RAW(length=None)

类签名

class sqlalchemy.dialects.oracle.RAW (sqlalchemy.types._Binary)

method sqlalchemy.dialects.oracle.RAW.__init__(length=None)

inherited from the sqlalchemy.types._Binary.__init__ method of sqlalchemy.types._Binary

cx_Oracle

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 Namemyalias 详情如下:

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
    }
)

请注意,的默认值为 encodingnencoding 在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_classNullPool 要禁用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的编程驱动程序之外,还有一种可选的方法 encodingnencoding 直接将参数 .connect() 功能。这些可以在URL中显示,如下所示:

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

关于 encodingnencoding 参数,请参考 Characters Sets and National Language Support (NLS) .

参见

Characters Sets and National Language Support (NLS) -在cx_Oracle文档中。

Unicode特定的列数据类型

核心表达式语言通过使用 UnicodeUnicodeText 数据类型。默认情况下,这些类型对应于VARCHAR2和CLOB Oracle数据类型。当将这些数据类型与Unicode数据一起使用时,Oracle数据库应该配置有一个支持Unicode的字符集,并且 NLS_LANG 环境变量被适当地设置,以便varchar2和clob数据类型能够容纳数据。

如果Oracle数据库未配置Unicode字符集,则两个选项将使用 NCHARNCLOB 显式的数据类型,或传递标志 use_nchar_for_unicode=Truecreate_engine() ,这将导致sqlAlchemy方言将nchar/nclob用于 Unicode / UnicodeText 数据类型,而不是varchar/clob。

在 1.3 版更改: 这个 UnicodeUnicodeText 数据类型现在对应于 VARCHAR2CLOB Oracle数据类型,除非 use_nchar_for_unicode=Truecreate_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 对象或浮动对象。当A Numeric 对象或子类,如 FloatDOUBLE_PRECISION 等正在使用中, Numeric.asdecimal 标志确定是否应将值强制为 Decimal 返回时,或作为浮动对象返回。为了使甲骨文下的事情更加复杂,甲骨文的 NUMBER 如果“scale”为零,类型还可以表示整数值,因此Oracle特定 NUMBER 类型也考虑到这一点。

cx-oracle方言广泛使用连接级和光标级的“outputtypehander”可调用文件,以便按要求强制使用数值。这些可调用物是特定于 Numeric 在使用中,以及如果不存在任何SQLAlchemy类型对象。在观察到的情况下,Oracle可能会发送有关返回的数字类型的不完整或不明确的信息,例如,将数字类型隐藏在多个级别的子查询下的查询。类型处理程序在所有情况下都尽其所能做出正确的决策,对于驱动程序能够做出最佳决策的所有情况,都遵从底层的cx_Oracle DBAPI。

当没有输入对象时,如执行普通的SQL字符串时,会出现一个默认的“outputTypeHandler”,它通常会返回指定精度和比例为python的数值。 Decimal 物体。若要出于性能原因禁用强制小数,请传递标志 coerce_to_decimal=Falsecreate_engine() ::

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

这个 coerce_to_decimal 标志仅影响纯字符串SQL语句的结果,否则这些语句与 Numeric SQLAlChemy类型(或此类类型的子类)。

在 1.2 版更改: cx_-oracle的数字处理系统已经重新设计,以利用新的cx_-oracle功能以及更好地集成输出类型处理程序。

Previous: SQLite Next: Microsoft SQL服务器