Serie: Einführung in den Inhalt von cx_Oracle
cx_Oracle gibt die Ergebnismenge als Liste von Tupeln zurück. Es kann jedoch Fälle geben, in denen Sie dies als Liste oder Wörterbuch zurückgeben möchten. Cx_Oracle ist auf diesen Fall vorbereitet, daher werde ich erklären, wie es geht.
Cursor.rowfactory Das rowfactory-Attribut des Cursor-Objekts definiert die Methode, die beim Abrufen von Datensätzen aufgerufen wird. Dieses Attribut erzeugt standardmäßig Taples. Durch Überschreiben dieser Bewegung ist es möglich, das Format des Datensatzes in eine andere Form zu ändern.
Werfen wir einen Blick auf die tatsächliche Codierung, indem wir die folgende Anwendung überarbeiten.
sample15a.py
import cx_Oracle
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
select object_id, owner, object_name, object_type
from all_objects
order by object_id
fetch first 5 rows only
"""
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
for row in cursor.execute(SQL):
print(row)
$ python sample15a.py
(2, 'SYS', 'C_OBJ#', 'CLUSTER')
(3, 'SYS', 'I_OBJ#', 'INDEX')
(4, 'SYS', 'TAB$', 'TABLE')
(5, 'SYS', 'CLU$', 'TABLE')
(6, 'SYS', 'C_TS#', 'CLUSTER')
sample15b.py(Auszug)
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
cursor.execute(SQL)
cursor.rowfactory = lambda *args: list(args)
rows = cursor.fetchall()
for row in rows:
print(row)
Die vierte Zeile von unten ist die Implementierung von rowfactory. Ich verwende einen Lambda-Ausdruck, um jeden Datensatz von einem Taple in eine Liste zu konvertieren. Es wurde nur diese eine Zeile hinzugefügt und keine andere Codierung wurde geändert. Die Ausführungsergebnisse sind unten aufgeführt.
$ python sample15b.py
[2, 'SYS', 'C_OBJ#', 'CLUSTER']
[3, 'SYS', 'I_OBJ#', 'INDEX']
[4, 'SYS', 'TAB$', 'TABLE']
[5, 'SYS', 'CLU$', 'TABLE']
[6, 'SYS', 'C_TS#', 'CLUSTER']
Es ist auch möglich, Datensätze in einem Wörterbuch mit Spaltennamen als Elemente zurückzugeben.
sample15c.py(Auszug)
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
cursor.execute(SQL)
columns = [col[0] for col in cursor.description]
cursor.rowfactory = lambda *args: dict(zip(columns, args))
rows = cursor.fetchall()
for row in rows:
print(row)
for row in rows:
print(row["OBJECT_NAME"])
Der Spaltenname wird in der 4. Zeile von oben abgerufen. cursor.description ist ein schreibgeschütztes Attribut in Form einer Liste von Tupeln, in denen die Metadaten für jede Spalte gespeichert sind. Die Elementnummer 0 jedes Taples dieses Attributs ist der Spaltenname. In der fünften Zeile von oben wird ein Lambda-Ausdruck verwendet, um ein Wörterbuch mit den Informationen aus der vorherigen Zeile zu erstellen. Das Ausführungsergebnis ist ein Wörterbuch wie unten gezeigt.
$ python sample15c.py
{'OBJECT_ID': 2, 'OWNER': 'SYS', 'OBJECT_NAME': 'C_OBJ#', 'OBJECT_TYPE': 'CLUSTER'}
{'OBJECT_ID': 3, 'OWNER': 'SYS', 'OBJECT_NAME': 'I_OBJ#', 'OBJECT_TYPE': 'INDEX'}
{'OBJECT_ID': 4, 'OWNER': 'SYS', 'OBJECT_NAME': 'TAB$', 'OBJECT_TYPE': 'TABLE'}
{'OBJECT_ID': 5, 'OWNER': 'SYS', 'OBJECT_NAME': 'CLU$', 'OBJECT_TYPE': 'TABLE'}
{'OBJECT_ID': 6, 'OWNER': 'SYS', 'OBJECT_NAME': 'C_TS#', 'OBJECT_TYPE': 'CLUSTER'}
C_OBJ#
I_OBJ#
TAB$
CLU$
C_TS#
rowfactory ist auch mit Data Class kompatibel, einer neuen Funktion in Python 3.7. Das Erstellen derselben Datenklasse wie die Ergebnismenge scheint nützlich zu sein. Unten finden Sie eine Beschreibung der Datenklasse.
Ab Python 3.7 werden "Datenklassen" möglicherweise zum Standard für Klassendefinitionen
Unten finden Sie Beispiele und Ausführungsergebnisse.
sample15d.py
import cx_Oracle
from dataclasses import dataclass
@dataclass
class AllObject:
object_id: int
owner: str
object_name: str
object_type: str
def display(self):
return f"{self.owner}.{self.object_name}Ist{self.object_type}(ID:{self.object_id})ist"
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
select object_id, owner, object_name, object_type
from all_objects
order by object_id
fetch first 5 rows only
"""
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
cursor.execute(SQL)
cursor.rowfactory = lambda *args: AllObject(*args)
rows = cursor.fetchall()
[print(r.display()) for r in rows]
$ python sample15d.py
SYS.C_OBJ#Ist CLUSTER(ID:2)ist
SYS.I_OBJ#Ist INDEX(ID:3)ist
SYS.TAB$Ist TABELLE(ID:4)ist
SYS.CLU$Ist TABELLE(ID:5)ist
SYS.C_TS#Ist CLUSTER(ID:6)ist
Recommended Posts