SQLAlchemy 2.0 Dokumentation
Dialekte
- PostgreSQL
- MySQL und MariaDB
- SQLite
- Oracle¶
- Unterstützung für die Oracle Database Datenbank.
- Auto Increment Verhalten
- Transaktionsisolationsstufe / Autocommit
- Bezeichner-Groß-/Kleinschreibung
- Maximale Bezeichnerlängen
- LIMIT/OFFSET/FETCH Unterstützung
- RETURNING Unterstützung
- ON UPDATE CASCADE
- Oracle Database 8 Kompatibilität
- Synonym-/DBLINK-Reflexion
- Constraint-Reflexion
- Tabellennamen mit SYSTEM/SYSAUX Tablespaces
- FLOAT / DOUBLE Unterstützung und Verhalten
- DateTime Kompatibilität
- Oracle Database Tabellenoptionen
- Oracle Database spezifische Indexoptionen
- Oracle Database Datentypen
- python-oracledb
- DBAPI
- Verbinden
- Beschreibung
- Thick Mode Unterstützung
- Verbindung zur Oracle Database
- Connection Pooling
- Verwendung von Oracle Database Resident Connection Pooling (DRCP)
- Engine-Optionen, die vom SQLAlchemy oracledb Dialekt außerhalb des Treibers verbraucht werden
- Unicode
- Feingranulare Steuerung der python-oracledb Datenbindung mit setinputsizes
- LOB Datentypen
- RETURNING Unterstützung
- Zwei-Phasen-Transaktionsunterstützung
- Präzisions-Numerics
- cx_Oracle
- DBAPI
- Verbinden
- Beschreibung
- DSN vs. Hostname Verbindungen
- Übergabe von cx_Oracle Connect-Argumenten
- Optionen, die vom SQLAlchemy cx_Oracle Dialekt außerhalb des Treibers verbraucht werden
- Verwendung des cx_Oracle SessionPools
- Verwendung von Oracle Database Resident Connection Pooling (DRCP)
- Unicode
- Feingranulare Kontrolle über die Performance der cx_Oracle-Datenbindung mit setinputsizes
- LOB Datentypen
- RETURNING Unterstützung
- Zwei-Phasen-Transaktionen nicht unterstützt
- Präzisions-Numerics
- Microsoft SQL Server
Projektversionen
- Vorher: SQLite
- Nächste: Microsoft SQL Server
- Nach oben: Startseite
- Auf dieser Seite
- Oracle
- Unterstützung für die Oracle Database Datenbank.
- Auto Increment Verhalten
- Transaktionsisolationsstufe / Autocommit
- Bezeichner-Groß-/Kleinschreibung
- Maximale Bezeichnerlängen
- LIMIT/OFFSET/FETCH Unterstützung
- RETURNING Unterstützung
- ON UPDATE CASCADE
- Oracle Database 8 Kompatibilität
- Synonym-/DBLINK-Reflexion
- Constraint-Reflexion
- Tabellennamen mit SYSTEM/SYSAUX Tablespaces
- FLOAT / DOUBLE Unterstützung und Verhalten
- DateTime Kompatibilität
- Oracle Database Tabellenoptionen
- Oracle Database spezifische Indexoptionen
- Oracle Database Datentypen
- python-oracledb
- DBAPI
- Verbinden
- Beschreibung
- Thick Mode Unterstützung
- Verbindung zur Oracle Database
- Connection Pooling
- Verwendung von Oracle Database Resident Connection Pooling (DRCP)
- Engine-Optionen, die vom SQLAlchemy oracledb Dialekt außerhalb des Treibers verbraucht werden
- Unicode
- Feingranulare Steuerung der python-oracledb Datenbindung mit setinputsizes
- LOB Datentypen
- RETURNING Unterstützung
- Zwei-Phasen-Transaktionsunterstützung
- Präzisions-Numerics
- cx_Oracle
- DBAPI
- Verbinden
- Beschreibung
- DSN vs. Hostname Verbindungen
- Übergabe von cx_Oracle Connect-Argumenten
- Optionen, die vom SQLAlchemy cx_Oracle Dialekt außerhalb des Treibers verbraucht werden
- Verwendung des cx_Oracle SessionPools
- Verwendung von Oracle Database Resident Connection Pooling (DRCP)
- Unicode
- Feingranulare Kontrolle über die Performance der cx_Oracle-Datenbindung mit setinputsizes
- LOB Datentypen
- RETURNING Unterstützung
- Zwei-Phasen-Transaktionen nicht unterstützt
- Präzisions-Numerics
Oracle¶
Unterstützung für die Oracle Database Datenbank.
Die folgende Tabelle fasst die aktuellen Support-Level für Datenbank-Release-Versionen zusammen.
Support-Typ |
Versionen |
|---|---|
11+ |
|
9+ |
DBAPI Unterstützung¶
Die folgenden Dialekt-/DBAPI-Optionen sind verfügbar. Bitte beachten Sie die einzelnen DBAPI-Abschnitte für Verbindungsinformationen.
Auto Increment Verhalten¶
SQLAlchemy Table-Objekte, die Integer-Primärschlüssel enthalten, werden normalerweise als "autoincrementing" angenommen, d.h. sie können ihre eigenen Primärschlüsselwerte bei einem INSERT generieren. Für die Verwendung in der Oracle Database stehen zwei Optionen zur Verfügung: die Verwendung von IDENTITY-Spalten (nur Oracle Database 12 und höher) oder die Zuordnung einer SEQUENCE zur Spalte.
Angabe von GENERATED AS IDENTITY (Oracle Database 12 und höher)¶
Ab Version 12 kann Oracle Database Identitätsspalten mit Hilfe von Identity verwenden, um das autoincrementing Verhalten anzugeben.
t = Table(
"mytable",
metadata,
Column("id", Integer, Identity(start=3), primary_key=True),
Column(...),
...,
)Die CREATE TABLE für das obige Table-Objekt wäre
CREATE TABLE mytable (
id INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 3),
...,
PRIMARY KEY (id)
)Das Identity Objekt unterstützt viele Optionen zur Steuerung des "autoincrementing" Verhaltens der Spalte, wie z.B. den Startwert, den Inkrementwert usw. Zusätzlich zu den Standardoptionen unterstützt Oracle Database das Setzen von Identity.always auf None, um den generierten Standardmodus zu verwenden und GENERATED AS IDENTITY in der DDL darzustellen. Es unterstützt auch das Setzen von Identity.on_null auf True, um ON NULL in Verbindung mit einer 'BY DEFAULT' Identitätsspalte anzugeben.
Verwendung einer SEQUENCE (alle Oracle Database Versionen)¶
Ältere Versionen von Oracle Database hatten keine "autoincrement"-Funktion: SQLAlchemy setzt auf Sequenzen, um diese Werte zu erzeugen. Bei älteren Oracle Database Versionen *muss immer explizit eine Sequenz angegeben werden, um Autoincrement zu aktivieren*. Dies weicht von den meisten Dokumentationsbeispielen ab, die die Verwendung einer datenbankfähigen Datenbank annehmen. Um Sequenzen anzugeben, verwenden Sie das Objekt sqlalchemy.schema.Sequence, das einem Column-Konstrukt übergeben wird.
t = Table(
"mytable",
metadata,
Column("id", Integer, Sequence("id_seq", start=1), primary_key=True),
Column(...),
...,
)Dieser Schritt ist auch bei der Verwendung von Tabellenreflexion erforderlich, d.h. autoload_with=engine
t = Table(
"mytable",
metadata,
Column("id", Integer, Sequence("id_seq", start=1), primary_key=True),
autoload_with=engine,
)Geändert in Version 1.4: `Identity`-Konstrukt in einer Column hinzugefügt, um die Option einer autoincrementing Spalte anzugeben.
Transaktionsisolationslevel / Autocommit¶
Oracle Database unterstützt die Isolationsmodi "READ COMMITTED" und "SERIALIZABLE". Der AUTOCOMMIT-Isolationslevel wird auch von den python-oracledb und cx_Oracle Dialekten unterstützt.
Einstellung über per-Verbindungs-Ausführungsoptionen
connection = engine.connect()
connection = connection.execution_options(isolation_level="AUTOCOMMIT")Für READ COMMITTED und SERIALIZABLE setzt der Oracle Database Dialekt den Level auf Session-Ebene mit ALTER SESSION, der wieder auf seine Standardeinstellung zurückgesetzt wird, wenn die Verbindung an den Connection Pool zurückgegeben wird.
Gültige Werte für isolation_level sind
READ COMMITTEDAUTOCOMMITSERIALIZABLE
Hinweis
Die Implementierung für die Methode Connection.get_isolation_level(), wie sie von den Oracle Database Dialekten implementiert wird, erzwingt notwendigerweise den Start einer Transaktion unter Verwendung der Oracle Database DBMS_TRANSACTION.LOCAL_TRANSACTION_ID Funktion; andernfalls ist kein Level normalerweise lesbar.
Darüber hinaus löst die Methode Connection.get_isolation_level() eine Ausnahme aus, wenn die v$transaction Ansicht aufgrund von Berechtigungen oder aus anderen Gründen nicht verfügbar ist, was in Oracle Database Installationen ein häufiges Vorkommnis ist.
Die python-oracledb und cx_Oracle Dialekte versuchen, die Methode Connection.get_isolation_level() aufzurufen, wenn der Dialekt seine erste Verbindung zur Datenbank herstellt, um den "Standard"-Isolationslevel zu ermitteln. Dieser Standardlevel ist erforderlich, damit der Level nach einer vorübergehenden Änderung über die Methode Connection.execution_options() auf einer Verbindung zurückgesetzt werden kann. In dem häufigen Fall, dass die Methode Connection.get_isolation_level() aufgrund von nicht lesbarem v$transaction oder anderen datenbankbezogenen Fehlern eine Ausnahme auslöst, wird der Level auf "READ COMMITTED" gesetzt. Für diesen anfänglichen Erstverbindungsfall wird keine Warnung ausgegeben, da dies eine häufige Einschränkung bei Oracle-Datenbanken ist.
Neu in Version 1.3.16: Unterstützung für AUTOCOMMIT zum cx_Oracle Dialekt hinzugefügt, sowie die Vorstellung eines Standard-Isolationslevels.
Neu in Version 1.3.21: Unterstützung für SERIALIZABLE sowie Live-Lesen des Isolationslevels hinzugefügt.
Geändert in Version 1.3.22: Wenn der Standard-Isolationslevel aufgrund von Berechtigungen für die v$transaction Ansicht nicht gelesen werden kann, was bei Oracle-Installationen üblich ist, wird der Standard-Isolationslevel auf "READ COMMITTED" fest codiert, was dem Verhalten vor 1.3.21 entsprach.
Bezeichner-Groß-/Kleinschreibung¶
In Oracle Database stellt das Datenwörterbuch alle Groß-/Kleinschreibungsunempfindlichen Bezeichnernamen als Großbuchstaben dar. Dies steht im Widerspruch zu den Erwartungen von SQLAlchemy, das annimmt, dass ein Groß-/Kleinschreibungsunempfindlicher Name als Kleinbuchstaben dargestellt wird.
Als Beispiel für Groß-/Kleinschreibungsunempfindliche Bezeichnernamen, betrachten Sie die folgende Tabelle
CREATE TABLE MyTable (Identifier INTEGER PRIMARY KEY)Wenn Sie Oracle Database nach Informationen über diese Tabelle abfragen würden, würde der Tabellenname als MYTABLE und der Spaltenname als IDENTIFIER gemeldet werden. Vergleichen Sie dies mit den meisten anderen Datenbanken wie PostgreSQL und MySQL, die diese Namen als mytable und identifier melden würden. Die Namen sind nicht in Anführungszeichen gesetzt, daher sind sie Groß-/Kleinschreibungsunempfindlich. Die spezielle Groß-/Kleinschreibung von MyTable und Identifier würde nur beibehalten, wenn sie in der Tabellendefinition in Anführungszeichen gesetzt wären.
CREATE TABLE "MyTable" ("Identifier" INTEGER PRIMARY KEY)Beim Erstellen eines SQLAlchemy Table Objekts, wird ein vollständig kleingeschriebener Name als Groß-/Kleinschreibungsunempfindlich betrachtet. Die folgende Tabelle nimmt also Groß-/Kleinschreibungsunempfindliche Namen an.
Table("mytable", metadata, Column("identifier", Integer, primary_key=True))Während bei gemischten oder GROSSBUCHSTABEN Namen Groß-/Kleinschreibung angenommen wird.
Table("MyTable", metadata, Column("Identifier", Integer, primary_key=True))Eine ähnliche Situation tritt auf der Ebene des Datenbanktreibers auf, wenn eine textuelle SQL SELECT-Anweisung ausgegeben wird und Spaltennamen im DBAPI cursor.description Attribut betrachtet werden. Eine Datenbank wie PostgreSQL normalisiert Groß-/Kleinschreibungsunempfindliche Namen zu Kleinbuchstaben.
>>> pg_engine = create_engine("postgresql://scott:tiger@localhost/test")
>>> pg_connection = pg_engine.connect()
>>> result = pg_connection.exec_driver_sql("SELECT 1 AS SomeName")
>>> result.cursor.description
(Column(name='somename', type_code=23),)Während Oracle sie zu GROSSBUCHSTABEN normalisiert.
>>> oracle_engine = create_engine("oracle+oracledb://scott:tiger@oracle18c/xe")
>>> oracle_connection = oracle_engine.connect()
>>> result = oracle_connection.exec_driver_sql(
... "SELECT 1 AS SomeName FROM DUAL"
... )
>>> result.cursor.description
[('SOMENAME', <DbType DB_TYPE_NUMBER>, 127, None, 0, -127, True)]Um die plattformübergreifende Gleichheit für die beiden Fälle a. Tabellenreflexion und b. rein textuelle SQL-Abfragen zu erreichen, führt SQLAlchemy einen Schritt namens Namensnormalisierung durch, wenn der Oracle-Dialekt verwendet wird. Dieser Prozess kann auch auf andere Drittanbieter-Dialekte angewendet werden, die eine ähnliche GROSSBUCHSTABEN-Handhabung von Groß-/Kleinschreibungsunempfindlichen Namen aufweisen.
Bei der Namensnormalisierung versucht SQLAlchemy zu erkennen, ob ein Name Groß-/Kleinschreibungsunempfindlich ist, indem es prüft, ob alle Zeichen GROSSBUCHSTABEN sind; falls ja, geht es davon aus, dass es sich um einen Groß-/Kleinschreibungsunempfindlichen Namen handelt und liefert ihn als kleingeschriebenen Namen aus.
Für die Tabellenreflexion wird angenommen, dass ein Tabellenname, der in den Oracle Database Katalogtabellen vollständig in GROSSBUCHSTABEN dargestellt wird, einen Groß-/Kleinschreibungsunempfindlichen Namen hat. Dies ermöglicht es der Table Definition, kleingeschriebene Namen zu verwenden und sowohl aus Sicht der Reflexion auf Oracle Database als auch auf allen anderen Datenbanken wie PostgreSQL und MySQL kompatibel zu sein.
# matches a table created with CREATE TABLE mytable
Table("mytable", metadata, autoload_with=some_engine)Oben ist der kleingeschriebene Name "mytable" Groß-/Kleinschreibungsunempfindlich; er wird mit einer von PostgreSQL gemeldeten Tabelle "mytable" und einer von Oracle gemeldeten Tabelle "MYTABLE" übereinstimmen. Wenn keine Namensnormalisierung vorhanden wäre, wäre es für die obige Table Definition nicht möglich, Datenbank-übergreifend introspektierbar zu sein, da wir es mit einem Groß-/Kleinschreibungsunempfindlichen Namen zu tun haben, der von jeder Datenbank nicht auf die gleiche Weise gemeldet wird.
Die Groß-/Kleinschreibung kann in diesem Fall erzwungen werden, z. B. wenn wir den in Anführungszeichen gesetzten Tabellennamen "MYTABLE" mit genau dieser Schreibweise darstellen möchten, am einfachsten durch Verwendung dieser Schreibweise direkt, die als groß-/kleinschreibungssensitiv angesehen wird.
# matches a table created with CREATE TABLE "MYTABLE"
Table("MYTABLE", metadata, autoload_with=some_engine)Für den ungewöhnlichen Fall eines in Anführungszeichen gesetzten, vollständig kleingeschriebenen Namens kann das Konstrukt quoted_name verwendet werden.
from sqlalchemy import quoted_name
# matches a table created with CREATE TABLE "mytable"
Table(
quoted_name("mytable", quote=True), metadata, autoload_with=some_engine
)Namensnormalisierung findet auch bei der Verarbeitung von Ergebnismengen aus rein textuellen SQL-Zeichenfolgen statt, die keine andere Table oder Column Metadaten zugeordnet haben. Dies schließt SQL-Zeichenfolgen ein, die mit Connection.exec_driver_sql() ausgeführt werden, und SQL-Zeichenfolgen, die mit dem Konstrukt text() ausgeführt werden, die keine Column Metadaten enthalten.
Wenn wir zur Oracle Database SELECT-Anweisung zurückkehren, sehen wir, dass obwohl cursor.description den Spaltennamen als SOMENAME meldet, SQLAlchemy dies zu somename normalisiert.
>>> oracle_engine = create_engine("oracle+oracledb://scott:tiger@oracle18c/xe")
>>> oracle_connection = oracle_engine.connect()
>>> result = oracle_connection.exec_driver_sql(
... "SELECT 1 AS SomeName FROM DUAL"
... )
>>> result.cursor.description
[('SOMENAME', <DbType DB_TYPE_NUMBER>, 127, None, 0, -127, True)]
>>> result.keys()
RMKeyView(['somename'])Das einzige Szenario, in dem das obige Verhalten ungenaue Ergebnisse liefert, ist die Verwendung eines vollständig großgeschriebenen, in Anführungszeichen gesetzten Namens. SQLAlchemy kann nicht feststellen, ob ein bestimmter Name in cursor.description in Anführungszeichen gesetzt wurde und daher groß-/kleinschreibungssensitiv ist, oder ob er nicht in Anführungszeichen gesetzt wurde und daher normalisiert werden sollte.
>>> result = oracle_connection.exec_driver_sql(
... 'SELECT 1 AS "SOMENAME" FROM DUAL'
... )
>>> result.cursor.description
[('SOMENAME', <DbType DB_TYPE_NUMBER>, 127, None, 0, -127, True)]
>>> result.keys()
RMKeyView(['somename'])Für diesen Fall wird in SQLAlchemy 2.1 eine neue Funktion verfügbar sein, um das Namensnormalisierungsverhalten in bestimmten Fällen zu deaktivieren.
Maximale Bezeichnerlängen¶
SQLAlchemy ist empfindlich gegenüber der maximalen Bezeichnerlänge, die von Oracle Database unterstützt wird. Dies wirkt sich auf generierte SQL-Labelnamen sowie auf die Generierung von Constraint-Namen aus, insbesondere wenn die unter Konfiguration von Constraint-Benennungskonventionen beschriebene Funktion zur Benennung von Constraints verwendet wird.
Oracle Database 12.2 erhöhte die maximale Standardbezeichnerlänge von 30 auf 128. Ab SQLAlchemy 1.4 beträgt die maximale Standardbezeichnerlänge für die Oracle-Dialekte 128 Zeichen. Bei der ersten Verbindung wird die tatsächlich von der Datenbank unterstützte Maximallänge ermittelt. In allen Fällen umgeht die Einstellung des Parameters create_engine.max_identifier_length diese Änderung und der angegebene Wert wird unverändert verwendet.
engine = create_engine(
"oracle+oracledb://scott:tiger@localhost:1521?service_name=freepdb1",
max_identifier_length=30,
)Wenn create_engine.max_identifier_length nicht gesetzt ist, verwendet der oracledb Dialekt intern das Attribut max_identifier_length, das auf Treiberverbindungen seit python-oracledb Version 2.5 verfügbar ist. Bei Verwendung einer älteren Treiberversion oder des cx_Oracle Dialekts versucht SQLAlchemy stattdessen, die Abfrage SELECT value FROM v$parameter WHERE name = 'compatible' bei der ersten Verbindung abzurufen, um die effektive Kompatibilitätsversion der Datenbank zu ermitteln. Die "Kompatibilitätsversion" ist eine Versionsnummer, die unabhängig von der tatsächlichen Datenbankversion ist. Sie wird zur Unterstützung von Datenbankmigrationen verwendet. Sie wird durch einen Oracle Database Initialisierungsparameter konfiguriert. Die Kompatibilitätsversion bestimmt dann die maximal zulässige Bezeichnerlänge für die Datenbank. Wenn die V$-Ansicht nicht verfügbar ist, wird stattdessen die Datenbankversionsinformation verwendet.
Die maximale Bezeichnerlänge kommt sowohl bei der Generierung von anonymisierten SQL-Labels in SELECT-Anweisungen als auch, was noch wichtiger ist, bei der Generierung von Constraint-Namen aus einer Benennungskonvention zum Tragen. Gerade in diesem Bereich besteht die Notwendigkeit, dass SQLAlchemy diese Standardeinstellung konservativ ändert. Zum Beispiel erzeugt die folgende Benennungskonvention zwei sehr unterschiedliche Constraint-Namen basierend auf der Bezeichnerlänge.
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))Bei einer Bezeichnerlänge von 30 sieht der obige CREATE INDEX wie folgt aus:
CREATE INDEX ix_some_column_name_1s_70cd ON t
(some_column_name_1, some_column_name_2, some_column_name_3)Mit einer Länge von 128 wird er jedoch zu:
.. sourcecode:: sqlCREATE 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)
Anwendungen, die Versionen von SQLAlchemy vor 1.4 auf Oracle Database Version 12.2 oder höher ausgeführt haben, sind daher von dem Szenario einer Datenbankmigration betroffen, die "DROP CONSTRAINT" auf einen Namen ausführen möchte, der zuvor mit der kürzeren Länge generiert wurde. Diese Migration schlägt fehl, wenn die Bezeichnerlänge geändert wird, ohne dass der Name des Index oder Constraints zuerst angepasst wird. Solchen Anwendungen wird dringend empfohlen, create_engine.max_identifier_length zu verwenden, um die Kontrolle über die Generierung abgeschnittener Namen zu behalten, und alle Datenbankmigrationen in einer Staging-Umgebung gründlich zu überprüfen und zu testen, wenn dieser Wert geändert wird, um sicherzustellen, dass die Auswirkungen dieser Änderung abgemildert wurden.
Geändert in Version 1.4: Die Standard-max_identifier_length für Oracle Database beträgt 128 Zeichen, die bei der ersten Verbindung auf 30 reduziert wird, wenn die Oracle Database oder ihre Kompatibilitätseinstellung niedriger als Version 12.2 sind.
LIMIT/OFFSET/FETCH Unterstützung¶
Methoden wie Select.limit() und Select.offset() verwenden die Syntax FETCH FIRST N ROW / OFFSET N ROWS unter der Annahme von Oracle Database 12c oder höher und unter der Annahme, dass die SELECT-Anweisung nicht in eine zusammengesetzte Anweisung wie UNION eingebettet ist. Diese Syntax ist auch direkt über die Methode Select.fetch() verfügbar.
Geändert in Version 2.0: Die Oracle Database Dialekte verwenden jetzt FETCH FIRST N ROW / OFFSET N ROWS für alle Select.limit() und Select.offset() Verwendungen, einschließlich innerhalb des ORM und des Legacy Query. Um das Legacy-Verhalten mithilfe von Fensterfunktionen zu erzwingen, geben Sie den Dialektparameter enable_offset_fetch=False an create_engine().
Die Verwendung von FETCH FIRST / OFFSET kann bei jeder Oracle Database Version deaktiviert werden, indem enable_offset_fetch=False an create_engine() übergeben wird, was den Modus "Legacy" erzwingt, der Fensterfunktionen verwendet. Dieser Modus wird auch automatisch ausgewählt, wenn eine Oracle Database Version vor 12c verwendet wird.
Bei der Verwendung des Legacy-Modus oder wenn eine Select Anweisung mit limit/offset in einer zusammengesetzten Anweisung eingebettet ist, wird ein emulierter Ansatz für LIMIT / OFFSET basierend auf Fensterfunktionen verwendet, der die Erstellung einer Unterabfrage mit ROW_NUMBER beinhaltet, die anfällig für Leistungsprobleme sowie Probleme bei der SQL-Konstruktion für komplexe Anweisungen ist. Dieser Ansatz wird jedoch von allen Oracle Database Versionen unterstützt. Siehe Hinweise unten.
Hinweise zur LIMIT / OFFSET Emulation (wenn die fetch() Methode nicht verwendet werden kann)¶
Bei Verwendung von Select.limit() und Select.offset(), oder im ORM die Methoden Query.limit() und Query.offset() auf einer Oracle Database Version vor 12c, gelten die folgenden Hinweise.
SQLAlchemy verwendet derzeit ROWNUM, um LIMIT/OFFSET zu erreichen; die genaue Methodik ist entnommen aus https://blogs.oracle.com/oraclemagazine/on-rownum-and-limiting-results.
Das Optimierungs-Schlüsselwort "FIRST_ROWS()" wird nicht standardmäßig verwendet. Um die Verwendung dieser Optimierungsanweisung zu aktivieren, geben Sie
optimize_limits=Trueancreate_engine()an.Geändert in Version 1.4: Der Oracle Database Dialekt rendert Limit/Offset Ganzzahlwerte mit einem "Post-Compile"-Schema, das die Ganzzahl direkt rendert, bevor die Anweisung an den Cursor zur Ausführung übergeben wird. Das Flag
use_binds_for_limitshat keine Auswirkung mehr.
RETURNING Unterstützung¶
Oracle Database unterstützt RETURNING vollständig für INSERT-, UPDATE- und DELETE-Anweisungen, die mit einer einzelnen Sammlung von gebundenen Parametern aufgerufen werden (d. h. eine cursor.execute()-Stil-Anweisung; SQLAlchemy unterstützt im Allgemeinen kein RETURNING mit executemany Anweisungen). Mehrere Zeilen können ebenfalls zurückgegeben werden.
Geändert in Version 2.0: Das Oracle Database Backend hat vollständige Unterstützung für RETURNING im Einklang mit anderen Backends.
ON UPDATE CASCADE¶
Oracle Database hat keine native ON UPDATE CASCADE Funktionalität. Eine Trigger-basierte Lösung ist verfügbar unter https://web.archive.org/web/20090317041251/https://asktom.oracle.com/tkyte/update_cascade/index.html.
Bei Verwendung des SQLAlchemy ORM hat das ORM eine begrenzte Fähigkeit, Kaskadierende Updates manuell auszugeben - geben Sie ForeignKey-Objekte mit den Schlüsselwortargumenten "deferrable=True, initially='deferred'" an und geben Sie "passive_updates=False" für jede Beziehung an().
Oracle Database 8 Kompatibilität¶
Warnung
Der Status der Oracle Database 8 Kompatibilität ist für SQLAlchemy 2.0 unbekannt.
Wenn Oracle Database 8 erkannt wird, konfiguriert sich der Dialekt intern wie folgt:
Das Flag use_ansi wird auf False gesetzt. Dies hat den Effekt, alle JOIN-Phrasen in die WHERE-Klausel zu konvertieren und im Falle von LEFT OUTER JOIN den (+) Operator von Oracle zu verwenden.
Die Datentypen NVARCHAR2 und NCLOB werden nicht mehr als DDL generiert, wenn
Unicodeverwendet wird - stattdessen werden VARCHAR2 und CLOB ausgegeben. Dies liegt daran, dass diese Typen auf Oracle 8 anscheinend nicht korrekt funktionieren, obwohl sie verfügbar sind. Die TypenNVARCHARundNCLOBwerden immer NVARCHAR2 und NCLOB generieren.
Synonym-/DBLINK-Reflexion¶
Bei der Verwendung von Reflexion mit Table-Objekten kann der Dialekt optional nach Tabellen suchen, die durch Synonyme angegeben sind, entweder in lokalen oder entfernten Schemas oder über DBLINK zugegriffen werden, indem das Flag oracle_resolve_synonyms=True als Schlüsselwortargument an das Table Konstrukt übergeben wird.
some_table = Table(
"some_table", autoload_with=some_engine, oracle_resolve_synonyms=True
)Wenn dieses Flag gesetzt ist, wird der angegebene Name (wie z.B. some_table oben) nicht nur in der Ansicht ALL_TABLES, sondern auch in der Ansicht ALL_SYNONYMS gesucht, um zu sehen, ob dieser Name tatsächlich ein Synonym für einen anderen Namen ist. Wenn das Synonym gefunden wird und auf einen DBLINK verweist, weiß der Oracle Database Dialekt, wie er die Tabelleninformationen unter Verwendung der DBLINK-Syntax (z. B. @dblink) finden kann.
oracle_resolve_synonyms wird überall dort akzeptiert, wo Reflexionsargumente akzeptiert werden, einschließlich Methoden wie MetaData.reflect() und Inspector.get_columns().
Wenn Synonyme nicht verwendet werden, sollte dieses Flag deaktiviert bleiben.
Constraint-Reflexion¶
Die Oracle Database Dialekte können Informationen über Fremdschlüssel-, eindeutige und CHECK-Constraints sowie Indizes für Tabellen zurückgeben.
Rohinformationen zu diesen Constraints können über Inspector.get_foreign_keys(), Inspector.get_unique_constraints(), Inspector.get_check_constraints() und Inspector.get_indexes() abgerufen werden.
Geändert in Version 1.2: Der Oracle Database Dialekt kann nun UNIQUE- und CHECK-Constraints reflektieren.
Bei der Verwendung von Reflexion auf Table-Ebene werden diese Constraints auch in der Table enthalten sein.
Beachten Sie die folgenden Einschränkungen:
Bei der Verwendung der Methode
Inspector.get_check_constraints()erstellt Oracle Database einen speziellen "IS NOT NULL"-Constraint für Spalten, die "NOT NULL" spezifizieren. Dieser Constraint wird standardmäßig nicht zurückgegeben. Um die "IS NOT NULL"-Constraints einzuschließen, übergeben Sie das Flaginclude_all=True.from sqlalchemy import create_engine, inspect engine = create_engine( "oracle+oracledb://scott:tiger@localhost:1521?service_name=freepdb1" ) inspector = inspect(engine) all_check_constraints = inspector.get_check_constraints( "some_table", include_all=True )
In den meisten Fällen ist bei der Reflexion einer
Tableein UNIQUE-Constraint nicht alsUniqueConstraintObjekt verfügbar, da Oracle Database eindeutige Constraints in den meisten Fällen mit einem UNIQUE-Index spiegelt (die Ausnahme scheint zu sein, wenn zwei oder mehr eindeutige Constraints dieselben Spalten darstellen). DieTablestellt diese stattdessen überIndexmit dem Flagunique=Truedar.Oracle Database erstellt einen impliziten Index für den Primärschlüssel einer Tabelle; dieser Index ist von allen Indexergebnissen ausgeschlossen.
Die Liste der für einen Index reflektierten Spalten enthält keine Spaltennamen, die mit SYS_NC beginnen.
Tabellennamen mit SYSTEM/SYSAUX Tablespaces¶
Die Methoden Inspector.get_table_names() und Inspector.get_temp_table_names() geben jeweils eine Liste von Tabellennamen für die aktuelle Engine zurück. Diese Methoden sind auch Teil der Reflexion, die innerhalb einer Operation wie MetaData.reflect() stattfindet. Standardmäßig schließen diese Operationen die Tabellenspaces SYSTEM und SYSAUX aus. Um dies zu ändern, kann die Standardliste der ausgeschlossenen Tabellenspaces auf Engine-Ebene über den Parameter exclude_tablespaces geändert werden.
# exclude SYSAUX and SOME_TABLESPACE, but not SYSTEM
e = create_engine(
"oracle+oracledb://scott:tiger@localhost:1521/?service_name=freepdb1",
exclude_tablespaces=["SYSAUX", "SOME_TABLESPACE"],
)FLOAT / DOUBLE Unterstützung und Verhalten¶
Die SQLAlchemy Float und Double Datentypen sind generische Datentypen, die sich für ein bestimmtes Backend auf den "am wenigsten überraschenden" Datentyp auflösen. Für Oracle Database bedeutet dies, dass sie sich auf die Datentypen FLOAT und DOUBLE auflösen.
>>> from sqlalchemy import cast, literal, Float
>>> from sqlalchemy.dialects import oracle
>>> float_datatype = Float()
>>> print(cast(literal(5.0), float_datatype).compile(dialect=oracle.dialect()))
CAST(:param_1 AS FLOAT)Die Datentypen FLOAT / DOUBLE von Oracle sind Aliase für NUMBER. Oracle Database speichert NUMBER-Werte mit voller Genauigkeit, nicht mit Gleitkomma-Genauigkeit, was bedeutet, dass FLOAT / DOUBLE sich nicht wirklich wie native FP-Werte verhalten. Oracle Database bietet stattdessen spezielle Datentypen BINARY_FLOAT und BINARY_DOUBLE, um echte 4- und 8-Byte-FP-Werte zu liefern.
SQLAlchemy unterstützt diese Datentypen direkt über BINARY_FLOAT und BINARY_DOUBLE. Um die Datentypen Float oder Double datenbankagnostisch zu verwenden und gleichzeitig Oracle-Backends die Nutzung eines dieser Typen zu ermöglichen, verwenden Sie die Methode TypeEngine.with_variant(), um eine Variante einzurichten.
>>> from sqlalchemy import cast, literal, Float
>>> from sqlalchemy.dialects import oracle
>>> float_datatype = Float().with_variant(oracle.BINARY_FLOAT(), "oracle")
>>> print(cast(literal(5.0), float_datatype).compile(dialect=oracle.dialect()))
CAST(:param_1 AS BINARY_FLOAT)z. B. zur Verwendung dieses Datentyps in einer Table-Definition.
my_table = Table(
"my_table",
metadata,
Column(
"fp_data", Float().with_variant(oracle.BINARY_FLOAT(), "oracle")
),
)DateTime-Kompatibilität¶
Oracle Database hat keinen Datentyp namens DATETIME, sondern nur DATE, der tatsächlich ein Datum und eine Uhrzeit speichern kann. Aus diesem Grund stellen die Oracle Database-Dialekte einen Typ DATE bereit, der eine Unterklasse von DateTime ist. Dieser Typ hat kein spezielles Verhalten und dient nur als "Markierung" für diesen Typ; zusätzlich wird, wenn eine Datenbankspalte reflektiert wird und der Typ als DATE gemeldet wird, der zeitsupportierende Typ DATE verwendet.
Oracle Database Tabellenoptionen¶
Die CREATE TABLE-Klausel unterstützt die folgenden Optionen mit Oracle Database-Dialekten in Verbindung mit dem Table-Konstrukt.
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)
Der Parameter
oracle_compressakzeptiert entweder eine Integer-Kompressionsstufe oderTrue, um die Standard-Kompressionsstufe zu verwenden.TABLESPACE:Table("mytable", metadata, ..., oracle_tablespace="EXAMPLE_TABLESPACE")
Der Parameter
oracle_tablespacegibt den Tablespace an, in dem die Tabelle erstellt werden soll. Dies ist nützlich, wenn Sie eine Tabelle in einem anderen Tablespace als dem Standard-Tablespace des Benutzers erstellen möchten.Neu in Version 2.0.37.
Oracle Database spezifische Indexoptionen¶
Bitmap-Indizes¶
Sie können den Parameter oracle_bitmap angeben, um anstelle eines B-Tree-Index einen Bitmap-Index zu erstellen.
Index("my_index", my_table.c.data, oracle_bitmap=True)Bitmap-Indizes können nicht eindeutig sein und nicht komprimiert werden. SQLAlchemy prüft diese Einschränkungen nicht, nur die Datenbank tut dies.
Indexkomprimierung¶
Oracle Database verfügt über einen effizienteren Speichermodus für Indizes mit vielen wiederholten Werten. Verwenden Sie den Parameter oracle_compress, um die Schlüsselkomprimierung zu aktivieren.
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,
)Der Parameter oracle_compress akzeptiert entweder eine ganze Zahl, die die Anzahl der zu komprimierenden Präfixspalten angibt, oder True, um den Standardwert zu verwenden (alle Spalten für nicht eindeutige Indizes, alle außer der letzten Spalte für eindeutige Indizes).
Oracle Database Datentypen¶
Wie bei allen SQLAlchemy-Dialekten sind alle GROSSGESCHRIEBENEN Typen, von denen bekannt ist, dass sie mit Oracle Database gültig sind, aus der obersten Ebene des Dialekts importierbar, unabhängig davon, ob sie aus sqlalchemy.types oder aus dem lokalen Dialekt stammen.
from sqlalchemy.dialects.oracle import (
BFILE,
BLOB,
CHAR,
CLOB,
DATE,
DOUBLE_PRECISION,
FLOAT,
INTERVAL,
LONG,
NCLOB,
NCHAR,
NUMBER,
NVARCHAR,
NVARCHAR2,
RAW,
TIMESTAMP,
VARCHAR,
VARCHAR2,
)Neu in Version 1.2.19: NCHAR zur Liste der vom Oracle-Dialekt exportierten Datentypen hinzugefügt.
Typen, die spezifisch für Oracle Database sind oder Oracle-spezifische Konstruktorargumente haben, sind wie folgt:
| Objektname | Beschreibung |
|---|---|
Implementiert den Oracle |
|
Implementiert den Oracle |
|
Bietet den Oracle Database DATE-Typ. |
|
Oracle Database FLOAT. |
|
Alias für |
|
Oracle Database ROWID-Typ. |
|
Oracle Database Implementierung von |
- Klasse sqlalchemy.dialects.oracle.BFILE¶
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.BFILE(sqlalchemy.types.LargeBinary)-
Methode
sqlalchemy.dialects.oracle.BFILE.__init__(length: int | None = None)¶ geerbt von der
sqlalchemy.types.LargeBinary.__init__Methode vonLargeBinaryKonstruiert einen LargeBinary-Typ.
- Parameter:
length¶ – optional, eine Länge für die Spalte zur Verwendung in DDL-Anweisungen für binäre Typen, die eine Länge akzeptieren, wie z. B. der MySQL BLOB-Typ.
-
Methode
- Klasse sqlalchemy.dialects.oracle.BINARY_DOUBLE¶
Implementiert den Oracle
BINARY_DOUBLE-Datentyp.Dieser Datentyp unterscheidet sich vom Oracle
DOUBLE-Datentyp darin, dass er einen echten 8-Byte-FP-Wert liefert. Der Datentyp kann mit einem generischenDouble-Datentyp überTypeEngine.with_variant()kombiniert werden.Siehe auch
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.BINARY_DOUBLE(sqlalchemy.types.Double)-
Methode
sqlalchemy.dialects.oracle.BINARY_DOUBLE.__init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)¶ geerbt von der
sqlalchemy.types.Float.__init__Methode vonFloatKonstruiert einen Float.
- Parameter:
precision¶ –
die numerische Genauigkeit für die Verwendung in DDL
CREATE TABLE. Backends **sollten** versuchen, diese Genauigkeit als Anzahl von Ziffern für den generischenFloat-Datentyp anzugeben.Hinweis
Für den Oracle Database-Backend wird der Parameter
Float.precisionbei der Wiedergabe von DDL nicht akzeptiert, da Oracle Database keine Float-Genauigkeit in Form von Dezimalstellen unterstützt. Verwenden Sie stattdessen den Oracle Database-spezifischen DatentypFLOATund geben Sie den ParameterFLOAT.binary_precisionan. Dies ist neu in Version 2.0 von SQLAlchemy.Um einen datenbankagnostischen
Floatzu erstellen, der separat die binäre Genauigkeit für Oracle Database angibt, verwenden SieTypeEngine.with_variant()wie folgt: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¶ – das gleiche Flag wie bei
Numeric, aber standardmäßig aufFalsegesetzt. Beachten Sie, dass das Setzen dieses Flags aufTruezu einer Gleitkommakonvertierung führt.decimal_return_scale¶ – Skala, die standardmäßig beim Konvertieren von Gleitkommazahlen in Python-Dezimalzahlen verwendet wird. Gleitkommazahlen sind aufgrund von Dezimalungenauigkeiten typischerweise viel länger, und die meisten Gleitkomma-Datenbanktypen haben keine Vorstellung von "Skala". Daher sucht der Float-Typ standardmäßig nach den ersten zehn Dezimalstellen bei der Konvertierung. Die Angabe dieses Werts überschreibt diese Länge. Beachten Sie, dass die MySQL-Float-Typen, die "Skala" enthalten, "Skala" als Standard für decimal_return_scale verwenden, sofern nicht anders angegeben.
-
Methode
- Klasse sqlalchemy.dialects.oracle.BINARY_FLOAT¶
Implementiert den Oracle
BINARY_FLOAT-Datentyp.Dieser Datentyp unterscheidet sich vom Oracle
FLOAT-Datentyp darin, dass er einen echten 4-Byte-FP-Wert liefert. Der Datentyp kann mit einem generischenFloat-Datentyp überTypeEngine.with_variant()kombiniert werden.Siehe auch
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.BINARY_FLOAT(sqlalchemy.types.Float)-
Methode
sqlalchemy.dialects.oracle.BINARY_FLOAT.__init__(precision: int | None = None, asdecimal: bool = False, decimal_return_scale: int | None = None)¶ geerbt von der
sqlalchemy.types.Float.__init__Methode vonFloatKonstruiert einen Float.
- Parameter:
precision¶ –
die numerische Genauigkeit für die Verwendung in DDL
CREATE TABLE. Backends **sollten** versuchen, diese Genauigkeit als Anzahl von Ziffern für den generischenFloat-Datentyp anzugeben.Hinweis
Für den Oracle Database-Backend wird der Parameter
Float.precisionbei der Wiedergabe von DDL nicht akzeptiert, da Oracle Database keine Float-Genauigkeit in Form von Dezimalstellen unterstützt. Verwenden Sie stattdessen den Oracle Database-spezifischen DatentypFLOATund geben Sie den ParameterFLOAT.binary_precisionan. Dies ist neu in Version 2.0 von SQLAlchemy.Um einen datenbankagnostischen
Floatzu erstellen, der separat die binäre Genauigkeit für Oracle Database angibt, verwenden SieTypeEngine.with_variant()wie folgt: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¶ – das gleiche Flag wie bei
Numeric, aber standardmäßig aufFalsegesetzt. Beachten Sie, dass das Setzen dieses Flags aufTruezu einer Gleitkommakonvertierung führt.decimal_return_scale¶ – Skala, die standardmäßig beim Konvertieren von Gleitkommazahlen in Python-Dezimalzahlen verwendet wird. Gleitkommazahlen sind aufgrund von Dezimalungenauigkeiten typischerweise viel länger, und die meisten Gleitkomma-Datenbanktypen haben keine Vorstellung von "Skala". Daher sucht der Float-Typ standardmäßig nach den ersten zehn Dezimalstellen bei der Konvertierung. Die Angabe dieses Werts überschreibt diese Länge. Beachten Sie, dass die MySQL-Float-Typen, die "Skala" enthalten, "Skala" als Standard für decimal_return_scale verwenden, sofern nicht anders angegeben.
-
Methode
- Klasse sqlalchemy.dialects.oracle.DATE¶
Bietet den Oracle Database DATE-Typ.
Dieser Typ hat kein spezielles Python-Verhalten, außer dass er
DateTimeuntererbt; dies liegt daran, dass derDATE-Typ von Oracle Database einen Zeitwert unterstützt.Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.DATE(sqlalchemy.dialects.oracle.types._OracleDateLiteralRender,sqlalchemy.types.DateTime)-
Methode
sqlalchemy.dialects.oracle.DATE.__init__(timezone: bool = False)¶ geerbt von der
sqlalchemy.types.DateTime.__init__Methode vonDateTimeErstellt ein neues
DateTime.- Parameter:
timezone¶ – boolesch. Gibt an, dass der Datetime-Typ die Zeitzonenunterstützung aktivieren soll, falls dies im **Basisdatums/-zeit-Typ** verfügbar ist. Es wird empfohlen, direkt den Datentyp
TIMESTAMPzu verwenden, da einige Datenbanken separate generische Datums-/Zeittypen aufweisen, die sich vom zeitzonenfähigen TIMESTAMP-Datentyp unterscheiden, wie z. B. Oracle Database.
-
Methode
- Klasse sqlalchemy.dialects.oracle.FLOAT¶
Oracle Database FLOAT.
Dies ist dasselbe wie
FLOAT, mit der Ausnahme, dass ein Oracle Database-spezifischer ParameterFLOAT.binary_precisionakzeptiert wird und der ParameterFloat.precisionnicht akzeptiert wird.Oracle Database FLOAT-Typen geben die Genauigkeit in "binärer Genauigkeit" an, die standardmäßig 126 beträgt. Für einen REAL-Typ beträgt der Wert 63. Dieser Parameter lässt sich nicht sauber auf eine bestimmte Anzahl von Dezimalstellen abbilden, entspricht aber ungefähr der gewünschten Anzahl von Dezimalstellen geteilt durch 0,3103.
Neu in Version 2.0.
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.FLOAT(sqlalchemy.types.FLOAT)-
Methode
sqlalchemy.dialects.oracle.FLOAT.__init__(binary_precision=None, asdecimal=False, decimal_return_scale=None)¶ Erstellt einen FLOAT.
- Parameter:
binary_precision¶ – Oracle Database binäre Genauigkeit, die in DDL wiedergegeben wird. Dies kann durch die Formel "dezimale Genauigkeit = 0,30103 * binäre Genauigkeit" an die Anzahl der Dezimalstellen angenähert werden. Der von Oracle Database für FLOAT / DOUBLE PRECISION verwendete Standardwert ist 126.
asdecimal¶ – Siehe
Float.asdecimaldecimal_return_scale¶ – Siehe
Float.decimal_return_scale
-
Methode
- Klasse sqlalchemy.dialects.oracle.INTERVAL¶
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.INTERVAL(sqlalchemy.types.NativeForEmulated,sqlalchemy.types._AbstractInterval)-
Methode
sqlalchemy.dialects.oracle.INTERVAL.__init__(day_precision=None, second_precision=None)¶ Erstellt ein INTERVAL.
Beachten Sie, dass nur DAY TO SECOND-Intervalle unterstützt werden. Dies liegt an der fehlenden Unterstützung für YEAR TO MONTH-Intervalle in den verfügbaren DBAPIs.
- Parameter:
-
Methode
- Klasse sqlalchemy.dialects.oracle.NCLOB¶
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.NCLOB(sqlalchemy.types.Text)-
Methode
sqlalchemy.dialects.oracle.NCLOB.__init__(length: int | None = None, collation: str | None = None)¶ geerbt von der
sqlalchemy.types.String.__init__Methode vonStringErstellt einen String-speichernden Typ.
- Parameter:
length¶ – optional, eine Länge für die Spalte zur Verwendung in DDL- und CAST-Ausdrücken. Kann sicher weggelassen werden, wenn kein
CREATE TABLEausgeführt wird. Bestimmte Datenbanken erfordern möglicherweise einelengthfür die Verwendung in DDL und lösen eine Ausnahme aus, wenn dieCREATE TABLEDDL ausgeführt wird, wenn einVARCHARohne Länge enthalten ist. Ob der Wert als Bytes oder Zeichen interpretiert wird, ist datenbankspezifisch.collation¶ –
Optional, eine Spalten-Kollation zur Verwendung in DDL- und CAST-Ausdrücken. Wird mit dem COLLATE-Schlüsselwort gerendert, das von SQLite, MySQL und PostgreSQL unterstützt wird. Z.B.
>>> from sqlalchemy import cast, select, String >>> print(select(cast("some string", String(collation="utf8"))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1Hinweis
In den meisten Fällen sollten die Datentypen
UnicodeoderUnicodeTextfür eineColumnverwendet werden, die nicht-ASCII-Daten speichern soll. Diese Datentypen stellen sicher, dass die korrekten Typen in der Datenbank verwendet werden.
-
Methode
-
Attribut
sqlalchemy.dialects.oracle..sqlalchemy.dialects.oracle.NVARCHAR2¶ Alias für
NVARCHAR
- Klasse sqlalchemy.dialects.oracle.NUMBER¶
Klassensignatur
class
sqlalchemy.dialects.oracle.NUMBER(sqlalchemy.types.Numeric,sqlalchemy.types.Integer)
- Klasse sqlalchemy.dialects.oracle.LONG¶
Mitglieder
Klassensignatur
class
sqlalchemy.dialects.oracle.LONG(sqlalchemy.types.Text)-
Methode
sqlalchemy.dialects.oracle.LONG.__init__(length: int | None = None, collation: str | None = None)¶ geerbt von der
sqlalchemy.types.String.__init__Methode vonStringErstellt einen String-speichernden Typ.
- Parameter:
length¶ – optional, eine Länge für die Spalte zur Verwendung in DDL- und CAST-Ausdrücken. Kann sicher weggelassen werden, wenn kein
CREATE TABLEausgeführt wird. Bestimmte Datenbanken erfordern möglicherweise einelengthfür die Verwendung in DDL und lösen eine Ausnahme aus, wenn dieCREATE TABLEDDL ausgeführt wird, wenn einVARCHARohne Länge enthalten ist. Ob der Wert als Bytes oder Zeichen interpretiert wird, ist datenbankspezifisch.collation¶ –
Optional, eine Spalten-Kollation zur Verwendung in DDL- und CAST-Ausdrücken. Wird mit dem COLLATE-Schlüsselwort gerendert, das von SQLite, MySQL und PostgreSQL unterstützt wird. Z.B.
>>> from sqlalchemy import cast, select, String >>> print(select(cast("some string", String(collation="utf8"))))
SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1Hinweis
In den meisten Fällen sollten die Datentypen
UnicodeoderUnicodeTextfür eineColumnverwendet werden, die nicht-ASCII-Daten speichern soll. Diese Datentypen stellen sicher, dass die korrekten Typen in der Datenbank verwendet werden.
-
Methode
- Klasse sqlalchemy.dialects.oracle.RAW¶
Klassensignatur
class
sqlalchemy.dialects.oracle.RAW(sqlalchemy.types._Binary)
- Klasse sqlalchemy.dialects.oracle.ROWID¶
Oracle Database ROWID-Typ.
Beim Verwenden in einer cast() oder ähnlichem wird ROWID generiert.
Klassensignatur
class
sqlalchemy.dialects.oracle.ROWID(sqlalchemy.types.TypeEngine)
- Klasse sqlalchemy.dialects.oracle.TIMESTAMP¶
Oracle Database Implementierung von
TIMESTAMP, die zusätzliche Oracle Database-spezifische Modi unterstützt.Neu in Version 2.0.
Mitglieder
Klassensignatur
Klasse
sqlalchemy.dialects.oracle.TIMESTAMP(sqlalchemy.types.TIMESTAMP)-
Methode
sqlalchemy.dialects.oracle.TIMESTAMP.__init__(timezone: bool = False, local_timezone: bool = False)¶ Konstruiert ein neues
TIMESTAMP.
-
Methode
python-oracledb¶
Unterstützung für die Oracle Database über den python-oracledb-Treiber.
DBAPI¶
Dokumentations- und Downloadinformationen (falls zutreffend) für python-oracledb sind verfügbar unter: https://oracle.github.io/python-oracledb/
Verbinden¶
Verbindungszeichenfolge
oracle+oracledb://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]Beschreibung¶
Python-oracledb ist der Treiber für Oracle Database unter Python. Er verfügt über einen standardmäßigen „Thin“-Client-Modus, der keine Abhängigkeiten erfordert, und einen optionalen „Thick“-Modus, der Oracle Client-Bibliotheken verwendet. Er unterstützt SQLAlchemy-Funktionen, einschließlich Zweiphasentransaktionen und Asyncio.
Python-oracle ist der umbenannte, aktualisierte cx_Oracle-Treiber. Oracle veröffentlicht keine neuen Versionen mehr im cx_Oracle-Namespace.
Das SQLAlchemy oracledb-Dialekt bietet sowohl eine synchrone als auch eine asynchrone Implementierung unter demselben Dialektnamen. Die richtige Version wird ausgewählt, je nachdem, wie die Engine erstellt wird
Aufruf von
create_engine()mitoracle+oracledb://...wählt automatisch die synchrone Version ausfrom sqlalchemy import create_engine sync_engine = create_engine( "oracle+oracledb://scott:tiger@localhost?service_name=FREEPDB1" )
Aufruf von
create_async_engine()mitoracle+oracledb://...wählt automatisch die asynchrone Version ausfrom sqlalchemy.ext.asyncio import create_async_engine asyncio_engine = create_async_engine( "oracle+oracledb://scott:tiger@localhost?service_name=FREEPDB1" )
Die Asyncio-Version des Dialekts kann auch explizit mit dem Suffix
oracledb_asyncangegeben werdenfrom sqlalchemy.ext.asyncio import create_async_engine asyncio_engine = create_async_engine( "oracle+oracledb_async://scott:tiger@localhost?service_name=FREEPDB1" )
Neu in Version 2.0.25: Unterstützung für die asynchrone Version von oracledb hinzugefügt.
Unterstützung für den Thick-Modus¶
Standardmäßig läuft der python-oracledb-Treiber im „Thin“-Modus, für den keine Oracle Client-Bibliotheken installiert sein müssen. Der Treiber unterstützt auch einen „Thick“-Modus, der Oracle Client-Bibliotheken verwendet, um Funktionalitäten wie Oracle Application Continuity zu nutzen.
Um den Thick-Modus zu aktivieren, rufen Sie oracledb.init_oracle_client() explizit auf oder übergeben Sie den Parameter thick_mode=True an create_engine(). Um benutzerdefinierte Argumente an init_oracle_client() zu übergeben, wie z. B. den lib_dir-Pfad, kann ein Dictionary übergeben werden, z. B.
engine = sa.create_engine(
"oracle+oracledb://...",
thick_mode={
"lib_dir": "/path/to/oracle/client/lib",
"config_dir": "/path/to/network_config_file_directory",
"driver_name": "my-app : 1.0.0",
},
)Beachten Sie, dass die Angabe eines lib_dir-Pfades nur unter macOS oder Windows erfolgen sollte. Unter Linux funktioniert dies nicht wie erwartet.
Siehe auch
python-oracledb-Dokumentation Aktivieren des Thick-Modus von python-oracledb
Verbindung mit Oracle Database herstellen¶
python-oracledb bietet mehrere Möglichkeiten zur Angabe der Ziel-Datenbank. Der Dialekt übersetzt aus einer Reihe von verschiedenen URL-Formaten.
Bei Angabe von Hostname, Port und Servicename der Ziel-Datenbank können Sie sich in SQLAlchemy über den Abfragezeichenkettenparameter service_name verbinden
engine = create_engine(
"oracle+oracledb://scott:tiger@hostname:port?service_name=myservice"
)Verbindung mit Easy Connect-Zeichenketten herstellen¶
Sie können jede gültige python-oracledb-Verbindungszeichenkette als Wert für den Schlüssel dsn in einem create_engine.connect_args-Dictionary übergeben. Siehe die Dokumentation von python-oracledb zu Oracle Net Services Connection Strings.
Zum Beispiel zur Verwendung einer Easy Connect-Zeichenkette mit einem Timeout, um zu verhindern, dass die Verbindungsherstellung blockiert, wenn der Netzwerktransport zur Datenbank nicht innerhalb von 30 Sekunden hergestellt werden kann, und auch zur Einstellung einer Keep-Alive-Zeit von 60 Sekunden, um zu verhindern, dass inaktive Netzwerkverbindungen von einer Firewall beendet werden
e = create_engine(
"oracle+oracledb://@",
connect_args={
"user": "scott",
"password": "tiger",
"dsn": "hostname:port/myservice?transport_connect_timeout=30&expire_time=60",
},
)Die Easy Connect-Syntax wurde im Laufe der Oracle Database weiterentwickelt. Überprüfen Sie die Dokumentation für Ihre Datenbankversion. Die aktuelle Dokumentation finden Sie unter Verständnis der Easy Connect-Namensgebungsmethode.
Die allgemeine Syntax ist ähnlich wie
[[protocol:]//]host[:port][/[service_name]][?parameter_name=value{¶meter_name=value}]Beachten Sie, dass die SQLAlchemy-URL-Syntax hostname:port/dbname der Oracle Easy Connect-Syntax ähnelt, aber anders ist. SQLAlchemy-URLs erfordern einen Systembezeichner (SID) für die dbname-Komponente
engine = create_engine("oracle+oracledb://scott:tiger@hostname:port/sid")Die Easy Connect-Syntax unterstützt keine SIDs. Sie verwendet Servicenamen, die für die Verbindung mit Oracle Database bevorzugt werden.
Übergabe von python-oracledb-Verbindungsargumenten¶
Andere Verbindungsoptionen des python-oracledb-Treibers können in connect_args übergeben werden. Zum Beispiel
e = create_engine(
"oracle+oracledb://@",
connect_args={
"user": "scott",
"password": "tiger",
"dsn": "hostname:port/myservice",
"events": True,
"mode": oracledb.AUTH_MODE_SYSDBA,
},
)Verbindung mit tnsnames.ora TNS-Aliassen herstellen¶
Wenn kein Port, Datenbankname oder Servicename angegeben ist, verwendet der Dialekt eine Oracle Database DSN-„Verbindungszeichenkette“. Diese verwendet den „Hostname“-Teil der URL als Datenquellenname. Wenn beispielsweise die tnsnames.ora-Datei einen TNS-Alias namens myalias wie folgt enthält
myalias =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.example.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orclpdb1)
)
)Der python-oracledb-Dialekt stellt eine Verbindung zu diesem Datenbankdienst her, wenn myalias der Hostname-Teil der URL ist, ohne Angabe eines Ports, Datenbanknamens oder service_name
engine = create_engine("oracle+oracledb://scott:tiger@myalias")Verbindung mit Oracle Autonomous Database herstellen¶
Benutzer von Oracle Autonomous Database sollten entweder die oben gezeigte TNS-Alias-URL verwenden oder den TNS-Alias als Wert für den Schlüssel dsn in einem create_engine.connect_args-Dictionary übergeben.
Wenn Oracle Autonomous Database für gegenseitige TLS-„mTLS“-Verbindungen konfiguriert ist, sind zusätzliche Konfigurationen erforderlich, wie in Verbindung mit Oracle Cloud Autonomous Databases beschrieben. Zusammenfassend lässt sich sagen, dass Benutzer des Thick-Modus die Dateipfade konfigurieren und den Wallet-Pfad in sqlnet.ora entsprechend einstellen sollten
e = create_engine(
"oracle+oracledb://@",
thick_mode={
# directory containing tnsnames.ora and cwallet.so
"config_dir": "/opt/oracle/wallet_dir",
},
connect_args={
"user": "scott",
"password": "tiger",
"dsn": "mydb_high",
},
)Benutzer des Thin-Modus von mTLS sollten die entsprechenden Verzeichnisse und das PEM-Wallet-Passwort beim Erstellen der Engine übergeben, ähnlich wie
e = create_engine(
"oracle+oracledb://@",
connect_args={
"user": "scott",
"password": "tiger",
"dsn": "mydb_high",
"config_dir": "/opt/oracle/wallet_dir", # directory containing tnsnames.ora
"wallet_location": "/opt/oracle/wallet_dir", # directory containing ewallet.pem
"wallet_password": "top secret", # password for the PEM file
},
)Typischerweise sind config_dir und wallet_location dasselbe Verzeichnis, in das die Oracle Autonomous Database Wallet-Zip-Datei extrahiert wurde. Beachten Sie, dass dieses Verzeichnis geschützt sein sollte.
Verbindungspooling¶
Anwendungen mit mehreren gleichzeitigen Benutzern sollten Verbindungspooling verwenden. Ein Verbindungspool mit minimaler Größe ist auch für langlaufende Einzelbenutzeranwendungen von Vorteil, die keine häufige Verbindung verwenden.
Der python-oracledb-Treiber bietet eine eigene Implementierung des Verbindungspoolings, die anstelle der SQLAlchemy-Pooling-Funktionalität verwendet werden kann. Der Treiberpool unterstützt Hochverfügbarkeitsfunktionen wie die Erkennung von toten Verbindungen, das schrittweise Abschalten von Verbindungen für geplante Datenbankausfälle, die Unterstützung von Oracle Application Continuity und Transparent Application Continuity und bietet Unterstützung für Database Resident Connection Pooling (DRCP).
Um den pool von python-oracledb zu nutzen, verwenden Sie den Parameter create_engine.creator, um eine Funktion bereitzustellen, die eine neue Verbindung zurückgibt, und setzen Sie create_engine.pool_class auf NullPool, um das SQLAlchemy-Pooling zu deaktivieren
import oracledb
from sqlalchemy import create_engine
from sqlalchemy import text
from sqlalchemy.pool import NullPool
# Uncomment to use the optional python-oracledb Thick mode.
# Review the python-oracledb doc for the appropriate parameters
# oracledb.init_oracle_client(<your parameters>)
pool = oracledb.create_pool(
user="scott",
password="tiger",
dsn="localhost:1521/freepdb1",
min=1,
max=4,
increment=1,
)
engine = create_engine(
"oracle+oracledb://", creator=pool.acquire, poolclass=NullPool
)Die obige Engine kann dann normal verwendet werden. Intern verwaltet python-oracledb das Verbindungspooling
with engine.connect() as conn:
print(conn.scalar(text("select 1 from dual")))Beachten Sie die Dokumentation von python-oracledb für oracledb.create_pool() für die Argumente, die beim Erstellen eines Verbindungspools verwendet werden können.
Verwendung von Oracle Database Resident Connection Pooling (DRCP)¶
Bei der Verwendung von Oracle Database Resident Connection Pooling (DRCP) ist es am besten, eine Verbindungsklasse und „Purity“ anzugeben. Beachten Sie die Dokumentation von python-oracledb zu DRCP. Zum Beispiel
import oracledb
from sqlalchemy import create_engine
from sqlalchemy import text
from sqlalchemy.pool import NullPool
# Uncomment to use the optional python-oracledb Thick mode.
# Review the python-oracledb doc for the appropriate parameters
# oracledb.init_oracle_client(<your parameters>)
pool = oracledb.create_pool(
user="scott",
password="tiger",
dsn="localhost:1521/freepdb1",
min=1,
max=4,
increment=1,
cclass="MYCLASS",
purity=oracledb.PURITY_SELF,
)
engine = create_engine(
"oracle+oracledb://", creator=pool.acquire, poolclass=NullPool
)Die obige Engine kann dann normal verwendet werden, wobei python-oracledb das Anwendungspooling verwaltet und Oracle Database zusätzlich DRCP verwendet
with engine.connect() as conn:
print(conn.scalar(text("select 1 from dual")))Wenn Sie unterschiedliche Verbindungsklassen oder Puritys für verschiedene Verbindungen verwenden möchten, umschließen Sie pool.acquire()
import oracledb
from sqlalchemy import create_engine
from sqlalchemy import text
from sqlalchemy.pool import NullPool
# Uncomment to use python-oracledb Thick mode.
# Review the python-oracledb doc for the appropriate parameters
# oracledb.init_oracle_client(<your parameters>)
pool = oracledb.create_pool(
user="scott",
password="tiger",
dsn="localhost:1521/freepdb1",
min=1,
max=4,
increment=1,
cclass="MYCLASS",
purity=oracledb.PURITY_SELF,
)
def creator():
return pool.acquire(cclass="MYOTHERCLASS", purity=oracledb.PURITY_NEW)
engine = create_engine(
"oracle+oracledb://", creator=creator, poolclass=NullPool
)Engine-Optionen, die vom SQLAlchemy oracledb-Dialekt außerhalb des Treibers verwendet werden¶
Es gibt auch Optionen, die vom SQLAlchemy oracledb-Dialekt selbst verbraucht werden. Diese Optionen werden immer direkt an create_engine() übergeben, wie z. B.
e = create_engine("oracle+oracledb://user:pass@tnsalias", arraysize=500)Die vom oracledb-Dialekt akzeptierten Parameter sind folgende:
arraysize– Legt den Wertarraysizedes Treibercursors fest. Standardmäßig ist dieser WertNone, was bedeutet, dass der Standardwert des Treibers von 100 verwendet wird. Diese Einstellung steuert, wie viele Zeilen beim Abrufen von Zeilen gepuffert werden, und kann sich erheblich auf die Leistung auswirken, wenn sie für Abfragen mit vielen Zeilen erhöht wird.Geändert in Version 2.0.26: Der Standardwert wurde von 50 auf None geändert, um den Standardwert des Treibers selbst zu verwenden.
auto_convert_lobs– Standardmäßig True; siehe LOB-Datentypen.coerce_to_decimal– siehe Präzisions-Numerics für Details.encoding_errors– siehe Encoding Errors für Details.
Unicode¶
Wie bei allen DBAPIs unter Python 3 sind alle Zeichenketten von Natur aus Unicode-Zeichenketten.
Sicherstellen der korrekten Client-Kodierung¶
In python-oracledb ist die Kodierung für alle Zeichendaten „UTF-8“.
Unicode-spezifische Spaltendatentypen¶
Die Core Expression Language verarbeitet Unicode-Daten mithilfe der Datentypen Unicode und UnicodeText. Diese Typen entsprechen standardmäßig den Oracle Database Datentypen VARCHAR2 und CLOB. Bei Verwendung dieser Datentypen mit Unicode-Daten wird erwartet, dass die Datenbank mit einer Unicode-fähigen Zeichensatzkonfiguration eingerichtet ist, damit die Datentypen VARCHAR2 und CLOB die Daten aufnehmen können.
Wenn die Oracle Database nicht mit einem Unicode-Zeichensatz konfiguriert ist, bestehen die beiden Optionen darin, die Datentypen NCHAR und NCLOB explizit zu verwenden oder das Flag use_nchar_for_unicode=True an create_engine() zu übergeben, was dazu führt, dass der SQLAlchemy-Dialekt NCHAR/NCLOB für die Datentypen Unicode / UnicodeText anstelle von VARCHAR/CLOB verwendet.
Geändert in Version 1.3: Die Datentypen Unicode und UnicodeText entsprechen nun den Oracle Database Datentypen VARCHAR2 und CLOB, es sei denn, use_nchar_for_unicode=True wird beim Aufruf von create_engine() an den Dialekt übergeben.
Encoding Errors¶
Für den ungewöhnlichen Fall, dass Daten in der Oracle-Datenbank mit einer beschädigten Kodierung vorhanden sind, akzeptiert der Dialekt einen Parameter encoding_errors, der an die Unicode-Dekodierungsfunktionen weitergegeben wird, um zu beeinflussen, wie Dekodierungsfehler behandelt werden. Der Wert wird letztendlich von der Python decode-Funktion verbraucht und sowohl über den Parameter encodingErrors von python-oracledb, der von Cursor.var() verbraucht wird, als auch über die eigene Dekodierungsfunktion von SQLAlchemy weitergegeben, da der python-oracledb-Dialekt beides unter verschiedenen Umständen nutzt.
Neu ab Version 1.3.11.
Feingranulare Steuerung der python-oracledb-Datenbindung mit setinputsizes¶
Die python-oracle DBAPI hat eine tiefe und grundlegende Abhängigkeit von der Verwendung des DBAPI-Aufrufs setinputsizes(). Der Zweck dieses Aufrufs ist es, die Datentypen festzulegen, die an eine SQL-Anweisung für Python-Werte gebunden werden, die als Parameter übergeben werden. Während praktisch kein anderer DBAPI dem setinputsizes()-Aufruf irgendeine Verwendung zuweist, ist die python-oracledb DBAPI in ihren Interaktionen mit der Oracle-Datenbank stark darauf angewiesen, und in einigen Szenarien ist es für SQLAlchemy nicht möglich, genau zu wissen, wie Daten gebunden werden sollen, da einige Einstellungen zu sehr unterschiedlichen Leistungseigenschaften führen können, während sich gleichzeitig das Verhalten der Typumwandlung ändert.
Benutzer des oracledb-Dialekts werden **dringend aufgefordert**, die Liste der integrierten Datentyp-Symbole von python-oracledb unter Datenbanktypen zu lesen. Beachten Sie, dass in einigen Fällen erhebliche Leistungseinbußen auftreten können, wenn diese Typen verwendet werden im Vergleich zur Nichtverwendung.
Auf der SQLAlchemy-Seite kann das Ereignis DialectEvents.do_setinputsizes() sowohl für die Laufzeitsichtbarkeit (z. B. Protokollierung) des setinputsizes-Schritts als auch zur vollständigen Steuerung der Verwendung von setinputsizes() pro Anweisung verwendet werden.
Neu in Version 1.2.9: DialectEvents.setinputsizes() hinzugefügt
Beispiel 1 – Protokollierung aller setinputsizes-Aufrufe¶
Das folgende Beispiel zeigt, wie die Zwischenwerte aus SQLAlchemy-Perspektive protokolliert werden, bevor sie in das rohe setinputsizes()-Parameter-Dictionary konvertiert werden. Die Schlüssel des Dictionaries sind BindParameter-Objekte, die ein .key- und ein .type-Attribut haben
from sqlalchemy import create_engine, event
engine = create_engine(
"oracle+oracledb://scott:tiger@localhost:1521?service_name=freepdb1"
)
@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,
)Beispiel 2 – Entfernen aller Bindungen zu CLOB¶
Aus Leistungsgründen ist das Abrufen von LOB-Datentypen aus der Oracle-Datenbank standardmäßig für den Text-Typ in SQLAlchemy eingestellt. Diese Einstellung kann wie folgt geändert werden
from sqlalchemy import create_engine, event
from oracledb import CLOB
engine = create_engine(
"oracle+oracledb://scott:tiger@localhost:1521?service_name=freepdb1"
)
@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]LOB-Datentypen¶
LOB-Datentypen beziehen sich auf die „Large Object“-Datentypen wie CLOB, NCLOB und BLOB. Oracle Database kann diese Datentypen effizient als einen einzigen Puffer zurückgeben. SQLAlchemy nutzt standardmäßig Typ-Handler, um dies zu tun.
Um die Verwendung der Typ-Handler zu deaktivieren und LOB-Objekte als klassische gepufferte Objekte mit einer read()-Methode zu liefern, kann der Parameter auto_convert_lobs=False an create_engine() übergeben werden.
RETURNING-Unterstützung¶
Der oracledb-Dialekt implementiert RETURNING mit OUT-Parametern. Der Dialekt unterstützt RETURNING vollständig.
Zweiphasentransaktionsunterstützung¶
Zweiphasentransaktionen werden mit python-oracledb vollständig unterstützt. (Der Thin-Modus erfordert python-oracledb 2.3). APIs für Zweiphasentransaktionen sind auf der Core-Ebene über Connection.begin_twophase() und Session.twophase für transparente ORM-Nutzung verfügbar.
Geändert in Version 2.0.32: Unterstützung für Zweiphasentransaktionen hinzugefügt
Präzisions-Numerics¶
SQLAlchemy-numerische Typen können Werte als Python Decimal-Objekte oder Float-Objekte empfangen und zurückgeben. Wenn ein Numeric-Objekt oder eine Unterklasse wie Float, DOUBLE_PRECISION usw. verwendet wird, bestimmt das Flag Numeric.asdecimal, ob Werte bei der Rückgabe zu Decimal konvertiert oder als Float-Objekte zurückgegeben werden sollen. Um die Sache unter Oracle Database zu erschweren, kann der NUMBER-Typ auch Ganzzahlen darstellen, wenn die „Skala“ Null ist. Der Oracle-spezifische Typ NUMBER berücksichtigt dies ebenfalls.
Der oracledb-Dialekt verwendet intensiv auf Verbindungs- und Cursor-Ebene „outputtypehandler“-Aufrufbare, um numerische Werte wie gewünscht zu konvertieren. Diese Aufrufbaren sind spezifisch für die jeweilige Variante von Numeric sowie wenn keine SQLAlchemy-Typobjekte vorhanden sind. Es gibt beobachtete Szenarien, in denen Oracle Database unvollständige oder mehrdeutige Informationen über die zurückgegebenen numerischen Typen sendet, wie z. B. eine Abfrage, bei der die numerischen Typen unter mehreren Ebenen von Unterabfragen versteckt sind. Die Typ-Handler tun ihr Bestes, um in allen Fällen die richtige Entscheidung zu treffen, und weichen auf den zugrunde liegenden python-oracledb DBAPI für alle Fälle zurück, in denen der Treiber die beste Entscheidung treffen kann.
Wenn keine Typobjekte vorhanden sind, wie bei der Ausführung von reinen SQL-Zeichenketten, ist ein Standard-„outputtypehandler“ vorhanden, der im Allgemeinen numerische Werte zurückgibt, die Präzision und Skala als Python Decimal-Objekte angeben. Um diese Konvertierung nach Decimal aus Leistungsgründen zu deaktivieren, übergeben Sie das Flag coerce_to_decimal=False an create_engine()
engine = create_engine(
"oracle+oracledb://scott:tiger@tnsalias", coerce_to_decimal=False
)Das Flag coerce_to_decimal beeinflusst nur die Ergebnisse von reinen SQL-Zeichenkettenanweisungen, die nicht anderweitig mit einem Numeric SQLAlchemy-Typ (oder einer Unterklasse davon) verknüpft sind.
Geändert in Version 1.2: Das System zur Handhabung von Zahlen für die Oracle-Dialekte wurde überarbeitet, um neuere Treiberfunktionen sowie eine bessere Integration von Output-Handlern zu nutzen.
Neu in Version 2.0.0: Unterstützung für den python-oracledb-Treiber hinzugefügt.
cx_Oracle¶
Unterstützung für die Oracle Database über den cx-Oracle-Treiber.
DBAPI¶
Dokumentations- und Downloadinformationen (falls zutreffend) für cx-Oracle sind verfügbar unter: https://oracle.github.io/python-cx_Oracle/
Verbinden¶
Verbindungszeichenfolge
oracle+cx_oracle://user:pass@hostname:port[/dbname][?service_name=<service>[&key=value&key=value...]]Beschreibung¶
cx_Oracle war der ursprüngliche Treiber für Oracle Database. Er wurde durch python-oracledb abgelöst, das stattdessen verwendet werden sollte.
DSN vs. Hostname-Verbindungen¶
cx_Oracle bietet mehrere Möglichkeiten zur Angabe der Ziel-Datenbank. Der Dialekt übersetzt aus einer Reihe von verschiedenen URL-Formen.
Hostname-Verbindungen mit Easy Connect-Syntax¶
Bei Angabe von Hostname, Port und Servicename der Ziel-Datenbank, zum Beispiel aus der Oracle Database Easy Connect-Syntax, verbinden Sie sich in SQLAlchemy über den Abfragezeichenkettenparameter service_name
engine = create_engine(
"oracle+cx_oracle://scott:tiger@hostname:port?service_name=myservice&encoding=UTF-8&nencoding=UTF-8"
)Beachten Sie, dass der Standardtreiberwert für Encoding und Nencoding in cx_Oracle 8.0 auf „UTF-8“ geändert wurde, sodass diese Parameter bei Verwendung dieser oder späterer Versionen weggelassen werden können.
Um eine vollständige Easy Connect-Zeichenkette zu verwenden, übergeben Sie sie als Wert für den Schlüssel dsn in einem create_engine.connect_args-Dictionary
import cx_Oracle
e = create_engine(
"oracle+cx_oracle://@",
connect_args={
"user": "scott",
"password": "tiger",
"dsn": "hostname:port/myservice?transport_connect_timeout=30&expire_time=60",
},
)Verbindungen mit tnsnames.ora oder zu Oracle Autonomous Database¶
Alternativ, wenn kein Port, Datenbankname oder Servicename angegeben ist, verwendet der Dialekt eine Oracle Database DSN-„Verbindungszeichenkette“. Diese verwendet den „Hostname“-Teil der URL als Datenquellenname. Wenn beispielsweise die tnsnames.ora-Datei einen TNS-Alias namens myalias wie folgt enthält
myalias =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.example.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orclpdb1)
)
)Der cx_Oracle-Dialekt stellt eine Verbindung zu diesem Datenbankdienst her, wenn myalias der Hostname-Teil der URL ist, ohne Angabe eines Ports, Datenbanknamens oder service_name
engine = create_engine("oracle+cx_oracle://scott:tiger@myalias")Benutzer von Oracle Autonomous Database sollten diese Syntax verwenden. Wenn die Datenbank für mTLS-Verbindungen konfiguriert ist, müssen Sie auch das Cloud-Wallet wie in der cx_Oracle-Dokumentation unter Verbindung mit autonomen Datenbanken beschrieben konfigurieren.
SID-Verbindungen¶
Um die veraltete System-Identifier-Verbindungssyntax von Oracle Database zu verwenden, kann die SID im „Datenbankname“-Teil der URL übergeben werden
engine = create_engine(
"oracle+cx_oracle://scott:tiger@hostname:port/dbname"
)Oben wird die an cx_Oracle übergebene DSN von cx_Oracle.makedsn() wie folgt erstellt:
>>> import cx_Oracle
>>> cx_Oracle.makedsn("hostname", 1521, sid="dbname")
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1521))(CONNECT_DATA=(SID=dbname)))'Beachten Sie, dass die SQLAlchemy-Syntax hostname:port/dbname der Oracle Easy Connect-Syntax ähnelt, aber anders ist. Sie verwendet eine SID anstelle des von Easy Connect benötigten Servicenamens. Die Easy Connect-Syntax unterstützt keine SIDs.
Übergabe von cx_Oracle-Verbindungsargumenten¶
Zusätzliche Verbindungsargumente können normalerweise über die URL-Abfragezeichenkette übergeben werden; bestimmte Symbole wie SYSDBA werden abgefangen und in das korrekte Symbol konvertiert
e = create_engine(
"oracle+cx_oracle://user:pass@dsn?encoding=UTF-8&nencoding=UTF-8&mode=SYSDBA&events=true"
)Geändert in Version 1.3: Der cx_Oracle-Dialekt akzeptiert nun alle Argumentnamen innerhalb der URL-Zeichenkette selbst, die an die cx_Oracle DBAPI übergeben werden. Wie bereits zuvor, aber nicht korrekt dokumentiert, akzeptiert der Parameter create_engine.connect_args ebenfalls alle cx_Oracle DBAPI-Verbindungsargumente.
Um Argumente direkt an .connect() zu übergeben, ohne die Abfragezeichenkette zu verwenden, verwenden Sie das Dictionary create_engine.connect_args. Beliebige cx_Oracle-Parameterwerte und/oder Konstanten können übergeben werden, wie z. B.
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,
},
)Beachten Sie, dass der Standardtreiberwert für encoding und nencoding in cx_Oracle 8.0 auf „UTF-8“ geändert wurde, sodass diese Parameter bei Verwendung dieser oder späterer Versionen weggelassen werden können.
Optionen, die vom SQLAlchemy cx_Oracle-Dialekt außerhalb des Treibers verwendet werden¶
Es gibt auch Optionen, die vom SQLAlchemy cx_oracle Dialekt selbst verbraucht werden. Diese Optionen werden immer direkt an create_engine() übergeben, wie z. B.
e = create_engine(
"oracle+cx_oracle://user:pass@dsn", coerce_to_decimal=False
)Die vom cx_oracle Dialekt akzeptierten Parameter sind wie folgt:
arraysize- setzt den Wert von cx_oracle.arraysize auf Cursors; Standard istNone, was bedeutet, dass der Standardtreiber verwendet wird (typischerweise ist der Wert 100). Diese Einstellung steuert, wie viele Zeilen beim Abrufen von Zeilen gepuffert werden, und kann sich bei Änderungen erheblich auf die Leistung auswirken.Geändert in Version 2.0.26: Der Standardwert wurde von 50 auf None geändert, um den Standardwert des Treibers selbst zu verwenden.
auto_convert_lobs- Standard ist True; Siehe LOB-Datentypen.coerce_to_decimal- siehe Präzisions-Numeriken für Details.encoding_errors- siehe Encoding-Fehler für Details.
Verwendung des cx_Oracle SessionPool¶
Der cx_Oracle-Treiber bietet eine eigene Implementierung eines Connection Pools, die anstelle der Pooling-Funktionalität von SQLAlchemy verwendet werden kann. Der Treiber-Pool unterstützt Oracle Database-Funktionen wie die Erkennung toter Verbindungen, das "Draining" von Verbindungen für geplante Datenbankausfallzeiten, die Unterstützung für Oracle Application Continuity und Transparent Application Continuity sowie die Unterstützung für Database Resident Connection Pooling (DRCP).
Die Verwendung des Treiber-Pools kann durch die Angabe des Parameters create_engine.creator erreicht werden, um eine Funktion bereitzustellen, die eine neue Verbindung zurückgibt, sowie durch die Einstellung von create_engine.pool_class auf NullPool, um das Pooling von SQLAlchemy zu deaktivieren.
import cx_Oracle
from sqlalchemy import create_engine
from sqlalchemy.pool import NullPool
pool = cx_Oracle.SessionPool(
user="scott",
password="tiger",
dsn="orclpdb",
min=1,
max=4,
increment=1,
threaded=True,
encoding="UTF-8",
nencoding="UTF-8",
)
engine = create_engine(
"oracle+cx_oracle://", creator=pool.acquire, poolclass=NullPool
)Die oben genannte Engine kann dann normal verwendet werden, wobei der cx_Oracle-Pool das Verbindungs-Pooling übernimmt.
with engine.connect() as conn:
print(conn.scalar("select 1 from dual"))Neben der Bereitstellung einer skalierbaren Lösung für Multi-User-Anwendungen unterstützt der cx_Oracle Session Pool einige Oracle-Funktionen wie DRCP und Application Continuity.
Beachten Sie, dass die Parameter für die Pool-Erstellung threaded, encoding und nencoding in späteren cx_Oracle-Versionen als veraltet markiert wurden.
Verwendung von Oracle Database Resident Connection Pooling (DRCP)¶
Bei der Verwendung von DRCP der Oracle-Datenbank ist es bewährte Praxis, beim Abrufen einer Verbindung aus dem SessionPool eine Verbindungsklasse und "purity" zu übergeben. Beachten Sie die cx_Oracle DRCP-Dokumentation.
Dies kann durch Umschließen von pool.acquire() erreicht werden.
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
)Die oben genannte Engine kann dann normal verwendet werden, wobei cx_Oracle das Session-Pooling übernimmt und die Oracle-Datenbank zusätzlich DRCP verwendet.
with engine.connect() as conn:
print(conn.scalar("select 1 from dual"))Unicode¶
Wie bei allen DBAPIs unter Python 3 sind alle Zeichenketten inhärent Unicode-Zeichenketten. In allen Fällen benötigt der Treiber jedoch eine explizite Codierungskonfiguration.
Sicherstellung der korrekten Client-Codierung¶
Der lange etablierte Standard zur Festlegung der Client-Codierung für fast alle Oracle-Datenbank-bezogenen Software ist über die Umgebungsvariable NLS_LANG. Ältere Versionen von cx_Oracle verwenden diese Umgebungsvariable als Quelle ihrer Codierungskonfiguration. Das Format dieser Variablen ist Territory_Country.CharacterSet; ein typischer Wert wäre AMERICAN_AMERICA.AL32UTF8. cx_Oracle Version 8 und neuer verwenden standardmäßig die Zeichensatz "UTF-8" und ignorieren die Zeichensatzkomponente von NLS_LANG.
Der cx_Oracle-Treiber unterstützte auch eine programmatische Alternative, nämlich die Übergabe der Parameter encoding und nencoding direkt an seine Funktion .connect(). Diese können in der URL wie folgt vorhanden sein:
engine = create_engine(
"oracle+cx_oracle://scott:tiger@tnsalias?encoding=UTF-8&nencoding=UTF-8"
)Die Bedeutung der Parameter encoding und nencoding finden Sie unter Zeichensätze und National Language Support (NLS).
Siehe auch
Zeichensätze und National Language Support (NLS) - in der cx_Oracle-Dokumentation.
Unicode-spezifische Spaltendatentypen¶
Die Core Expression Language verarbeitet Unicode-Daten mithilfe der Datentypen Unicode und UnicodeText. Diese Typen entsprechen standardmäßig den Oracle Database-Datentypen VARCHAR2 und CLOB. Bei der Verwendung dieser Datentypen mit Unicode-Daten wird erwartet, dass die Datenbank mit einem Unicode-fähigen Zeichensatz konfiguriert ist und dass die Umgebungsvariable NLS_LANG entsprechend gesetzt ist (dies gilt für ältere Versionen von cx_Oracle), damit die Datentypen VARCHAR2 und CLOB die Daten aufnehmen können.
Wenn die Oracle Database nicht mit einem Unicode-Zeichensatz konfiguriert ist, bestehen die beiden Optionen darin, die Datentypen NCHAR und NCLOB explizit zu verwenden oder das Flag use_nchar_for_unicode=True an create_engine() zu übergeben, was dazu führt, dass der SQLAlchemy-Dialekt NCHAR/NCLOB für die Datentypen Unicode / UnicodeText anstelle von VARCHAR/CLOB verwendet.
Geändert in Version 1.3: Die Datentypen Unicode und UnicodeText entsprechen nun den Oracle Database Datentypen VARCHAR2 und CLOB, es sei denn, use_nchar_for_unicode=True wird beim Aufruf von create_engine() an den Dialekt übergeben.
Encoding-Fehler¶
Für den ungewöhnlichen Fall, dass Daten in der Oracle-Datenbank mit einem fehlerhaften Encoding vorhanden sind, akzeptiert der Dialekt den Parameter encoding_errors, der an Unicode-Dekodierungsfunktionen übergeben wird, um zu beeinflussen, wie Dekodierungsfehler behandelt werden. Der Wert wird letztendlich von der Python-Funktion decode verbraucht und wird sowohl über den cx_Oracle-Parameter encodingErrors, der von Cursor.var() verbraucht wird, als auch über die eigene Dekodierungsfunktion von SQLAlchemy übergeben, da der cx_Oracle-Dialekt diese unter verschiedenen Umständen nutzt.
Neu ab Version 1.3.11.
Feingranulare Steuerung der Leistung der cx_Oracle-Datenbindung mit setinputsizes¶
Der cx_Oracle DBAPI hat eine tiefe und grundlegende Abhängigkeit von der Verwendung des DBAPI-Aufrufs setinputsizes(). Der Zweck dieses Aufrufs ist es, die Datentypen festzulegen, die an eine SQL-Anweisung für Python-Werte gebunden werden, die als Parameter übergeben werden. Während praktisch kein anderer DBAPI dem setinputsizes()-Aufruf eine Verwendung zuweist, verlässt sich der cx_Oracle DBAPI stark darauf in seiner Interaktion mit der Oracle Database-Client-Schnittstelle, und in einigen Szenarien ist es für SQLAlchemy nicht möglich, genau zu wissen, wie Daten gebunden werden sollen, da einige Einstellungen tiefgreifend unterschiedliche Leistungseigenschaften aufweisen und gleichzeitig das Typumwandlungsverhalten ändern können.
Benutzer des cx_Oracle-Dialekts werden **dringend gebeten**, die Liste der integrierten Datentypsymbole von cx_Oracle unter https://cx-oracle.readthedocs.io/en/latest/api_manual/module.html#database-types zu lesen. Beachten Sie, dass in einigen Fällen signifikante Leistungsabfälle auftreten können, wenn diese Typen verwendet werden im Vergleich zur Nichtverwendung, insbesondere bei der Angabe von cx_Oracle.CLOB.
Auf der SQLAlchemy-Seite kann das Ereignis DialectEvents.do_setinputsizes() sowohl für die Laufzeitsichtbarkeit (z. B. Protokollierung) des setinputsizes-Schritts als auch zur vollständigen Steuerung der Verwendung von setinputsizes() pro Anweisung verwendet werden.
Neu in Version 1.2.9: DialectEvents.setinputsizes() hinzugefügt
Beispiel 1 - Protokollierung aller setinputsizes-Aufrufe¶
Das folgende Beispiel zeigt, wie die Zwischenwerte aus SQLAlchemy-Perspektive protokolliert werden, bevor sie in das rohe setinputsizes()-Parameter-Dictionary konvertiert werden. Die Schlüssel des Dictionaries sind BindParameter-Objekte, die ein .key- und ein .type-Attribut haben
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,
)Beispiel 2 - Entfernen aller Bindungen zu CLOB¶
Der CLOB-Datentyp in cx_Oracle verursacht einen erheblichen Leistungsaufwand, wird jedoch standardmäßig für den Text-Typ in der SQLAlchemy 1.2-Serie gesetzt. Diese Einstellung kann wie folgt geändert werden:
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]LOB-Datentypen¶
LOB-Datentypen beziehen sich auf "Large Object"-Datentypen wie CLOB, NCLOB und BLOB. Moderne Versionen von cx_Oracle sind für diese Datentypen optimiert, um als ein einzelner Puffer geliefert zu werden. Daher verwendet SQLAlchemy standardmäßig diese neueren Typ-Handler.
Um die Verwendung neuerer Typ-Handler zu deaktivieren und LOB-Objekte als klassische gepufferte Objekte mit einer read()-Methode zu liefern, kann der Parameter auto_convert_lobs=False an create_engine() übergeben werden, was nur engine-weit geschieht.
RETURNING-Unterstützung¶
Der cx_Oracle-Dialekt implementiert RETURNING über OUT-Parameter. Der Dialekt unterstützt RETURNING vollständig.
Zwei-Phasen-Transaktionen werden nicht unterstützt¶
Zwei-Phasen-Transaktionen werden unter cx_Oracle **nicht unterstützt**, da die Treiberunterstützung hierfür schlecht ist. Der neuere python-oracledb-Dialekt **unterstützt** jedoch Zwei-Phasen-Transaktionen.
Präzisions-Numeriken¶
SQLAlchemy-numerische Typen können Werte als Python Decimal-Objekte oder Float-Objekte empfangen und zurückgeben. Wenn ein Numeric-Objekt oder eine Unterklasse wie Float, DOUBLE_PRECISION usw. verwendet wird, bestimmt das Flag Numeric.asdecimal, ob Werte bei der Rückgabe zu Decimal konvertiert oder als Float-Objekte zurückgegeben werden sollen. Um die Sache unter Oracle Database zu erschweren, kann der NUMBER-Typ auch Ganzzahlen darstellen, wenn die „Skala“ Null ist. Der Oracle-spezifische Typ NUMBER berücksichtigt dies ebenfalls.
Der cx_Oracle-Dialekt verwendet umfassend auf Verbindungs- und Cursor-Ebene aufrufbare "outputtypehandler", um numerische Werte nach Bedarf umzuwandeln. Diese Aufrufbaren sind spezifisch für die jeweilige Art von Numeric, die verwendet wird, sowie wenn keine SQLAlchemy-Typobjekte vorhanden sind. Es gibt beobachtete Szenarien, in denen die Oracle-Datenbank unvollständige oder mehrdeutige Informationen über die zurückgegebenen numerischen Typen sendet, z. B. eine Abfrage, bei der die numerischen Typen unter mehreren Ebenen von Unterabfragen verborgen sind. Die Typ-Handler tun ihr Bestes, um in allen Fällen die richtige Entscheidung zu treffen, und greifen auf den zugrunde liegenden cx_Oracle DBAPI für all jene Fälle zurück, in denen der Treiber die beste Entscheidung treffen kann.
Wenn keine Typobjekte vorhanden sind, wie bei der Ausführung von reinen SQL-Zeichenketten, ist ein Standard-„outputtypehandler“ vorhanden, der im Allgemeinen numerische Werte zurückgibt, die Präzision und Skala als Python Decimal-Objekte angeben. Um diese Konvertierung nach Decimal aus Leistungsgründen zu deaktivieren, übergeben Sie das Flag coerce_to_decimal=False an create_engine()
engine = create_engine("oracle+cx_oracle://dsn", coerce_to_decimal=False)Das Flag coerce_to_decimal beeinflusst nur die Ergebnisse von reinen SQL-Zeichenkettenanweisungen, die nicht anderweitig mit einem Numeric SQLAlchemy-Typ (oder einer Unterklasse davon) verknüpft sind.
Geändert in Version 1.2: Das System zur Behandlung von numerischen Werten für cx_Oracle wurde überarbeitet, um neuere cx_Oracle-Funktionen sowie eine bessere Integration von outputtypehandlern zu nutzen.
Die Designs von flambé! dem Drachen und Der Alchemist wurden von Rotem Yaari erstellt und großzügig gespendet.
Erstellt mit Sphinx 7.2.6. Dokumentation zuletzt generiert: Di 11 Mär 2025 14:40:17 EDT