Oracle

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

9+

DBAPI Support

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

Поведение автоинкремента

Объекты таблиц SQLAlchemy, включающие целочисленные первичные ключи, обычно предполагаются с «автоинкрементным» поведением, то есть они могут генерировать собственные значения первичного ключа при INSERT. Для использования в Oracle доступны два варианта: использование столбцов IDENTITY (только для Oracle 12 и выше) или ассоциация SEQUENCE со столбцом.

Указание GENERATED AS IDENTITY (Oracle 12 и выше)

Начиная с версии 12 Oracle может использовать столбцы идентичности, используя Identity для указания автоинкрементного поведения:

t = Table('mytable', metadata,
    Column('id', Integer, Identity(start=3), primary_key=True),
    Column(...), ...
)

CREATE TABLE для вышеуказанного объекта Table будет иметь вид:

CREATE TABLE mytable (
    id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 3),
    ...,
    PRIMARY KEY (id)
)

Объект Identity поддерживает множество опций для управления «автоинкрементным» поведением столбца, например, начальное значение, значение инкремента и т.д. В дополнение к стандартным опциям, Oracle поддерживает установку Identity.always в None для использования режима генерации по умолчанию, отображая GENERATED AS IDENTITY в DDL. Также поддерживается установка Identity.on_null в True для указания ON NULL в сочетании со столбцом идентичности „BY DEFAULT“.

Использование последовательности (все версии 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
)

Изменено в версии 1.4: Добавлена конструкция Identity в Column для указания опции автоинкрементного столбца.

Уровень изоляции транзакций / автокоммит

База данных Oracle поддерживает режимы изоляции «READ COMMITTED» и «SERIALIZABLE». Уровень изоляции AUTOCOMMIT также поддерживается диалектом cx_Oracle.

Чтобы задать параметры выполнения по каждому соединению, выполните следующие действия:

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 не доступен для чтения, а также в случае любого другого сбоя, связанного с базой данных, уровень принимается равным «READ COMMITTED». Никакого предупреждения не выдается для этого начального условия первого подключения, поскольку ожидается, что это обычное ограничение для баз данных Oracle.

Добавлено в версии 1.3.16: добавлена поддержка AUTOCOMMIT в диалект cx_oracle, а также понятие уровня изоляции по умолчанию

Добавлено в версии 1.3.21: Добавлена поддержка SERIALIZABLE, а также живое считывание уровня изоляции.

Изменено в версии 1.3.22: В случае, если уровень изоляции по умолчанию не может быть прочитан из-за разрешений на представление v$transaction, что часто встречается в установках Oracle, уровень изоляции по умолчанию жестко кодируется в «READ COMMITTED», что было поведением до версии 1.3.21.

Идентификатор Корпус

В Oracle словарь данных представляет все нечувствительные к регистру имена идентификаторов с помощью текста UPPERCASE. С другой стороны, SQLAlchemy считает имя идентификатора в нижнем регистре нечувствительным к регистру. Диалект Oracle преобразует все нечувствительные к регистру идентификаторы в эти два формата и обратно во время взаимодействия на уровне схемы, например, при отражении таблиц и индексов. Использование имени UPPERCASE на стороне SQLAlchemy указывает на то, что идентификатор чувствителен к регистру, и SQLAlchemy заключит имя в кавычки - это приведет к несоответствию с данными словаря данных, полученными от Oracle, поэтому, если имена идентификаторов не были действительно созданы как чувствительные к регистру (т.е. с использованием имен в кавычках), на стороне SQLAlchemy следует использовать все имена в нижнем регистре.

Максимальная длина идентификатора

Oracle изменила максимальную длину идентификатора по умолчанию, начиная с версии Oracle Server 12.2. До этой версии длина составляла 30, а в версии 12.2 и выше она теперь равна 128. Это изменение влияет на SQLAlchemy в области генерируемых имен SQL-меток, а также на генерацию имен ограничений, особенно в том случае, когда используется функция соглашения об именовании ограничений, описанная в Настройка соглашений об именовании ограничений.

Чтобы помочь с этим и другими изменениями, 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-меток в операторах SELECT, так и, что более важно, при генерации имен ограничений на основе соглашения об именовании. Именно в этой области в 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)

Однако при length=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)

Таким образом, приложения, использующие версии SQLAlchemy до 1.4 на сервере Oracle версии 12.2 или выше, могут столкнуться со сценарием миграции базы данных, в котором требуется «DROP CONSTRAINT» для имени, которое ранее было сгенерировано с меньшей длиной. Такая миграция будет неудачной, если длина идентификатора будет изменена без предварительной корректировки имени индекса или ограничения. Таким приложениям настоятельно рекомендуется использовать create_engine.max_identifier_length, чтобы сохранить контроль над генерацией усеченных имен, а также полностью проверять и тестировать все миграции баз данных в промежуточной среде при изменении этого значения, чтобы убедиться, что влияние этого изменения было смягчено.

Изменено в версии 1.4: по умолчанию max_identifier_length для Oracle составляет 128 символов, которая уменьшается до 30 при первом подключении, если обнаружена более старая версия сервера Oracle (версия совместимости < 12.2).

Поддержка ОГРАНИЧЕНИЙ/ОТКАЗОВ/ФЕТЧ

Такие методы, как Select.limit() и Select.offset(), используют синтаксис FETCH FIRST N ROW / OFFSET N ROWS, предполагая Oracle 12c или выше, и предполагая, что оператор SELECT не встроен в составной оператор, такой как UNION. Этот синтаксис также доступен непосредственно при использовании метода Select.fetch().

Изменено в версии 2.0: диалект Oracle теперь использует FETCH FIRST N ROW / OFFSET N ROWS для всех Select.limit() и Select.offset(), включая ORM и унаследованные Query. Чтобы заставить унаследованное поведение использовать оконные функции, укажите параметр диалекта enable_offset_fetch=False в create_engine().

Использование FETCH FIRST / OFFSET может быть отключено на любой версии Oracle путем передачи enable_offset_fetch=False в create_engine(), что заставит использовать «унаследованный» режим, использующий оконные функции. Этот режим также выбирается автоматически при использовании версии Oracle до 12c.

При использовании унаследованного режима или когда оператор Select с ограничением/смещением встроен в составной оператор, используется эмулированный подход для LIMIT / OFFSET на основе оконных функций, который включает создание подзапроса с использованием ROW_NUMBER, что чревато проблемами производительности, а также проблемами построения SQL для сложных операторов. Тем не менее, этот подход поддерживается всеми версиями Oracle. См. примечания ниже.

Примечания по эмуляции LIMIT / OFFSET (когда метод fetch() не может быть использован)

При использовании методов Select.limit() и Select.offset(), а также методов Query.limit() и Query.offset() в ORM на версии Oracle до 12c действуют следующие указания:

поддержка возврата

База данных Oracle полностью поддерживает RETURNING для операторов INSERT, UPDATE и DELETE, которые вызываются с одним набором связанных параметров (то есть, оператор в стиле cursor.execute(); SQLAlchemy обычно не поддерживает RETURNING с операторами executemany). Также может быть возвращено несколько строк.

Изменено в версии 2.0: бэкенд Oracle имеет полную поддержку RETURNING наравне с другими бэкендами.

НА КАСКАДЕ ОБНОВЛЕНИЙ

Oracle не имеет встроенной функциональности ON UPDATE CASCADE. Решение на основе триггеров доступно по адресу https://asktom.oracle.com/tkyte/update_cascade/index.html .

При использовании SQLAlchemy ORM имеет ограниченные возможности для ручного выпуска каскадных обновлений - укажите объекты ForeignKey, используя ключевые аргументы «deferrable=True, initially=“deferred“», и укажите «passive_updates=False» для каждого отношения().

Совместимость с Oracle 8

Предупреждение

Статус совместимости с Oracle 8 для SQLAlchemy 2.0 неизвестен.

Когда Oracle 8 обнаружен, диалект внутренне настраивает себя на следующее поведение:

  • флаг use_ansi устанавливается в False. Это имеет эффект преобразования всех фраз JOIN в предложение WHERE, а в случае LEFT OUTER JOIN используется оператор (+) Oracle.

  • типы данных NVARCHAR2 и NCLOB больше не генерируются как DDL, когда используется Unicode - вместо них выдаются VARCHAR2 и CLOB. Это происходит потому, что эти типы, похоже, не работают корректно в Oracle 8, хотя они доступны. Типы NVARCHAR и NCLOB всегда будут генерировать NVARCHAR2 и NCLOB.

Отражение ограничений

Диалект Oracle может возвращать информацию об ограничениях foreign key, unique и 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 создает специальное ограничение «IS NOT NULL» для столбцов, в которых указано «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 будет представлять их с помощью Index с установленным флагом unique=True.

  • 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.

Специфические опции индексов 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, все типы UPPERCASE, которые, как известно, действительны в 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

BINARY_DOUBLE

BINARY_FLOAT

DATE

Укажите тип oracle DATE.

FLOAT

Oracle FLOAT.

INTERVAL

LONG

NCLOB

NUMBER

NVARCHAR2

alias of NVARCHAR

RAW

ROWID

Тип Oracle ROWID.

TIMESTAMP

Oracle реализация TIMESTAMP, которая поддерживает дополнительные режимы, специфичные для Oracle

class sqlalchemy.dialects.oracle.BFILE

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.BFILE (sqlalchemy.types.LargeBinary)

method sqlalchemy.dialects.oracle.BFILE.__init__(length: Optional[int] = None)

наследуется от sqlalchemy.types.LargeBinary.__init__ метода LargeBinary

Создайте тип LargeBinary.

Параметры:

length – опционально, длина столбца для использования в DDL-запросах, для тех бинарных типов, которые принимают длину, например, тип MySQL BLOB.

class sqlalchemy.dialects.oracle.BINARY_DOUBLE

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.BINARY_DOUBLE (sqlalchemy.types.Double)

method sqlalchemy.dialects.oracle.BINARY_DOUBLE.__init__(precision: Optional[int] = None, asdecimal: bool = False, decimal_return_scale: Optional[int] = None)

наследуется от sqlalchemy.types.Float.__init__ метода Float

Постройте поплавок.

Параметры:
  • precision – числовая точность для использования в DDL CREATE TABLE. Бэкенды должны пытаться обеспечить, чтобы эта точность указывала на число цифр для общего типа данных Float. … примечание:: Для бэкенда Oracle параметр Float.precision не принимается при рендеринге DDL, поскольку Oracle не поддерживает точность float, указанную как число десятичных знаков. Вместо этого используйте специфический для Oracle тип данных FLOAT и укажите параметр FLOAT.binary_precision. Это новое в версии 2.0 SQLAlchemy. Чтобы создать независимый от базы данных 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 float, которые включают «масштаб», будут использовать «масштаб» по умолчанию для decimal_return_scale, если не указано иное.

class sqlalchemy.dialects.oracle.BINARY_FLOAT

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.BINARY_FLOAT (sqlalchemy.types.Float)

method sqlalchemy.dialects.oracle.BINARY_FLOAT.__init__(precision: Optional[int] = None, asdecimal: bool = False, decimal_return_scale: Optional[int] = None)

наследуется от sqlalchemy.types.Float.__init__ метода Float

Постройте поплавок.

Параметры:
  • precision – числовая точность для использования в DDL CREATE TABLE. Бэкенды должны пытаться обеспечить, чтобы эта точность указывала на число цифр для общего типа данных Float. … примечание:: Для бэкенда Oracle параметр Float.precision не принимается при рендеринге DDL, поскольку Oracle не поддерживает точность float, указанную как число десятичных знаков. Вместо этого используйте специфический для Oracle тип данных FLOAT и укажите параметр FLOAT.binary_precision. Это новое в версии 2.0 SQLAlchemy. Чтобы создать независимый от базы данных 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 float, которые включают «масштаб», будут использовать «масштаб» по умолчанию для decimal_return_scale, если не указано иное.

class sqlalchemy.dialects.oracle.DATE

Укажите тип oracle DATE.

Этот тип не имеет особого поведения в Python, за исключением того, что он является подклассом DateTime; это сделано для того, чтобы соответствовать тому факту, что тип Oracle DATE поддерживает значение времени.

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.DATE (sqlalchemy.dialects.oracle.types._OracleDateLiteralRender, sqlalchemy.types.DateTime)

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

наследуется от sqlalchemy.types.DateTime.__init__ метода DateTime

Создайте новый DateTime.

Параметры:

timezone – булево. Указывает, что тип 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.

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.FLOAT (sqlalchemy.types.FLOAT)

method sqlalchemy.dialects.oracle.FLOAT.__init__(binary_precision=None, asdecimal=False, decimal_return_scale=None)

Постройте FLOAT

Параметры:
  • binary_precision – Значение двоичной точности Oracle для отображения в DDL. Оно может быть приближено к количеству десятичных знаков по формуле «десятичная точность = 0,30103 * двоичная точность». Значение по умолчанию, используемое Oracle для FLOAT / DOUBLE PRECISION, равно 126.

  • asdecimal – См. Float.asdecimal

  • decimal_return_scale – См. Float.decimal_return_scale

class sqlalchemy.dialects.oracle.INTERVAL

Members

__init__()

Классная подпись

класс 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

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.NCLOB (sqlalchemy.types.Text)

method sqlalchemy.dialects.oracle.NCLOB.__init__(length: Optional[int] = None, collation: Optional[str] = None)

наследуется от sqlalchemy.types.String.__init__ метода String

Создайте тип, удерживающий строку.

Параметры:
  • length – необязательный, длина столбца для использования в выражениях DDL и CAST. Может быть опущена, если не будет выдаваться CREATE TABLE. Некоторые базы данных могут требовать length для использования в DDL, и будут выдавать исключение при выдаче CREATE TABLE DDL, если включена VARCHAR без длины. Интерпретируется ли значение как байты или как символы, зависит от конкретной базы данных.

  • collation – Необязательно, collation на уровне столбцов для использования в выражениях DDL и CAST. Используется ключевое слово COLLATE, поддерживаемое SQLite, MySQL и PostgreSQL. Например: … sourcecode:: pycon+sql >>> from sqlalchemy import cast, select, String >>> print(select(cast(„some string“, String(collation=“utf8“)))) {printsql}SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1 … примечание:: В большинстве случаев для Unicode или UnicodeText следует использовать типы данных Column, которые предполагают хранение неасксичных данных. Эти типы данных гарантируют, что в базе данных используются правильные типы.

attribute sqlalchemy.dialects.oracle..sqlalchemy.dialects.oracle.NVARCHAR2

alias of NVARCHAR

class sqlalchemy.dialects.oracle.NUMBER
class sqlalchemy.dialects.oracle.LONG

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.LONG (sqlalchemy.types.Text)

method sqlalchemy.dialects.oracle.LONG.__init__(length: Optional[int] = None, collation: Optional[str] = None)

наследуется от sqlalchemy.types.String.__init__ метода String

Создайте тип, удерживающий строку.

Параметры:
  • length – необязательный, длина столбца для использования в выражениях DDL и CAST. Может быть опущена, если не будет выдаваться CREATE TABLE. Некоторые базы данных могут требовать length для использования в DDL, и будут выдавать исключение при выдаче CREATE TABLE DDL, если включена VARCHAR без длины. Интерпретируется ли значение как байты или как символы, зависит от конкретной базы данных.

  • collation – Необязательно, collation на уровне столбцов для использования в выражениях DDL и CAST. Используется ключевое слово COLLATE, поддерживаемое SQLite, MySQL и PostgreSQL. Например: … sourcecode:: pycon+sql >>> from sqlalchemy import cast, select, String >>> print(select(cast(„some string“, String(collation=“utf8“)))) {printsql}SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1 … примечание:: В большинстве случаев для Unicode или UnicodeText следует использовать типы данных 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.

Members

__init__()

Классная подпись

класс sqlalchemy.dialects.oracle.TIMESTAMP (sqlalchemy.types.TIMESTAMP)

method sqlalchemy.dialects.oracle.TIMESTAMP.__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

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 Database, например, с сайта 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 Cloud

В качестве альтернативы, если не указан порт, имя базы данных или service_name, диалект будет использовать «строку подключения» Oracle DSN. При этом в качестве имени источника данных берется часть URL «имя хоста». Например, если файл 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 Connecting to Autononmous Databases.

Соединения SID

Чтобы использовать устаревший синтаксис подключения Oracle SID, SID можно передать в части URL «имя базы данных», как показано ниже:

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

Выше, DSN, переданный в cx_Oracle, создается командой 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
    }
)

Обратите внимание, что значение по умолчанию для encoding и nencoding было изменено на «UTF-8» в cx_Oracle 8.0, поэтому эти параметры могут быть опущены при использовании этой версии или более поздних.

Параметры, потребляемые диалектом 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 для курсоров, по умолчанию 50. Эта настройка важна для cx_Oracle, поскольку содержимое объектов LOB можно читать только в пределах «живого» ряда (например, в пределах пакета из 50 рядов).

  • auto_convert_lobs - по умолчанию имеет значение True; См. Типы данных LOB.

  • 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+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 и Application Continuity.

Использование Oracle Database Resident Connection Pooling (DRCP)

При использовании DRCP от Oracle лучшей практикой является передача класса соединения и «чистоты» при получении соединения из 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+cx_oracle://", creator=creator, poolclass=NullPool)

Приведенный выше движок можно использовать в нормальном режиме, когда cx_Oracle обрабатывает пул сессий, а Oracle Database дополнительно использует DRCP:

with engine.connect() as conn:
    print(conn.scalar("select 1 FROM dual"))

Юникод

Как и для всех DBAPI под Python 3, все строки по своей сути являются строками 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 смотрите в Characters Sets and National Language Support (NLS).

См.также

Characters Sets and National Language Support (NLS) - в документации по cx_Oracle.

Специфические для Unicode типы данных столбцов

Язык выражений Core работает с данными в формате 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().

Ошибки кодирования

Для необычного случая, когда данные в базе данных Oracle присутствуют с нарушенной кодировкой, диалект принимает параметр encoding_errors, который будет передан функциям декодирования Unicode, чтобы повлиять на то, как обрабатываются ошибки декодирования. Значение в конечном итоге потребляется функцией Python decode, и передается как через параметр cx_Oracle encodingErrors, потребляемый Cursor.var(), так и через собственную функцию декодирования SQLAlchemy, поскольку диалект cx_Oracle использует оба параметра в разных обстоятельствах.

Добавлено в версии 1.3.11.

Тонкий контроль над производительностью привязки данных cx_Oracle с помощью setinputsizes

В cx_Oracle DBAPI заложена глубокая и фундаментальная зависимость от использования вызова DBAPI setinputsizes(). Цель этого вызова - установить типы данных, которые связаны с SQL-оператором для значений Python, передаваемых в качестве параметров. Хотя практически ни один другой 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

Следующий пример иллюстрирует, как регистрировать промежуточные значения с точки зрения SQLAlchemy, прежде чем они будут преобразованы в необработанный словарь параметров setinputsizes(). Ключами словаря являются 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

Тип данных CLOB в cx_Oracle приводит к значительным перегрузкам производительности, однако в 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]

поддержка возврата

Диалект cx_Oracle реализует RETURNING с использованием параметров OUT. Диалект полностью поддерживает RETURNING.

Типы данных LOB

Под типами данных LOB подразумеваются типы данных «больших объектов», такие как CLOB, NCLOB и BLOB. Современные версии cx_Oracle и oracledb оптимизированы для передачи этих типов данных в виде одного буфера. Поэтому SQLAlchemy по умолчанию использует эти новые обработчики типов.

Чтобы отключить использование новых обработчиков типов и передавать объекты LOB как классические буферизованные объекты с методом read(), параметр auto_convert_lobs=False может быть передан в create_engine(), что происходит только в масштабах всего движка.

Двухфазные транзакции не поддерживаются

Двухфазные транзакции не поддерживаются в cx_Oracle из-за слабой поддержки драйверов. Начиная с версии cx_Oracle 6.0b1, интерфейс для двухфазных транзакций был изменен и стал более прямым проходом к базовому уровню OCI с меньшей степенью автоматизации. Дополнительная логика для поддержки этой системы не реализована в SQLAlchemy.

Точные числа

Числовые типы SQLAlchemy могут принимать и возвращать значения как объекты Python Decimal или объекты float. Когда используется объект Numeric или подкласс, такой как Float, DOUBLE_PRECISION и т.д., флаг Numeric.asdecimal определяет, должны ли значения при возврате принудительно приводиться к Decimal или возвращаться как объекты float. Чтобы усложнить ситуацию в Oracle, тип NUMBER в Oracle может также представлять целочисленные значения, если «масштаб» равен нулю, поэтому специфический для 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 влияет только на результаты простых строковых SQL-запросов, которые не связаны с типом Numeric SQLAlchemy (или его подклассом).

Изменено в версии 1.2: Система обработки чисел для cx_Oracle была переработана для использования преимуществ новых возможностей cx_Oracle, а также лучшей интеграции обработчиков выходных типов.

python-oracledb

Support for the Oracle database via the python-oracledb driver.

DBAPI

Documentation and download information (if applicable) for python-oracledb is available at: https://oracle.github.io/python-oracledb/

Connecting

Connect String:

oracle+oracledb://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]

python-oracledb выпущен компанией Oracle для замены драйвера cx_Oracle. Он полностью совместим с cx_Oracle и имеет как «тонкий» клиентский режим, не требующий зависимостей, так и «толстый» режим, использующий клиентский интерфейс Oracle так же, как и cx_Oracle.

См.также

cx_Oracle - все замечания cx_Oracle применимы и к драйверу 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, в этот параметр можно передать dict, как в:

engine = sa.create_engine("oracle+oracledb://...", thick_mode={
    "lib_dir": "/path/to/oracle/client/lib", "driver_name": "my-app"
})

Добавлено в версии 2.0.0: добавлена поддержка драйвера oracledb.

Вернуться на верх