Natürlich unterscheiden sich die Datentypen zwischen Oracle Database und Python. In diesem Artikel werde ich erklären, wie cx_Oracle zwischen den beiden Datentypen vermittelt.
Welche Datentypen in der Oracle-Datenbank letztendlich welchen Python-Datentypen zugeordnet sind, ist in einer Tabelle im Handbuch cx_Oracle (https://cx-oracle.readthedocs.io/) zusammengefasst. de / latest / user_guide / sql_execution.html # fetch-data-types). Wie Sie der verknüpften Tabelle entnehmen können, werden die aus der Oracle-Datenbank erhaltenen Daten einmal in die Daten des Datentyps cx_Oracle konvertiert und über den Datentyp cx_Oracle im Datentyp Python gespeichert. Bei aktualisierten Daten ist der Ablauf umgekehrt. Das Folgende ist die Entsprechung der Hauptdatentypen. Eine vollständige Liste finden Sie im obigen Handbuch.
Oracle Database-Datentyp | cx_Oracle-Datentyp | Python-Datentyp |
---|---|---|
CHAR | cx_Oracle.FIXED_CHAR | str |
VARCHAR2 | cx_Oracle.STRING | str |
NUMBER | cx_Oracle.NUMBER | float oder int |
DATE | cx_Oracle.DATETIME | datetime.datetime |
TIMESTAMP | cx_Oracle.TIMESTAMP | datetime.datetime |
RAW | cx_Oracle.BINARY | bytes |
Hierbei ist zu beachten, dass es zwei Arten von Python-Datentypen gibt, die den Typ NUMBER unterstützen: float und int. Dies hängt von der Definition des NUMBER-Typs und dem gespeicherten Wert ab. Überprüfen Sie das Ausführungsergebnis der folgenden Beispielanwendung.
sample06a.py
import cx_Oracle
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL1 = """
create table sample06a (col1 number, col2 number, col3 number,
col4 number(5, 0), col5 number(5, 0), col6 number(5, 2),
col7 number(5, 2), col8 number(5, 2))
"""
SQL2 = "insert into sample06a values(7, 7.0, 7.1, 7, 7.0, 7, 7.0, 7.1)"
SQL3 = "commit"
SQL4 = "select * from sample06a"
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
cursor.execute(SQL1)
cursor.execute(SQL2)
cursor.execute(SQL3)
row = cursor.execute(SQL4).fetchone()
print(f""7" für NUMMER: {type(row[0])}")
print(f""7" in NUMMER.0」 : {type(row[1])}")
print(f""7" in NUMMER.1」 : {type(row[2])}")
print(f"NUMBER(5, 0)Auf "7": {type(row[3])}")
print(f"NUMBER(5, 0)Zu "7.0」 : {type(row[4])}")
print(f"NUMBER(5, 2)Auf "7": {type(row[5])}")
print(f"NUMBER(5, 2)Zu "7.0」 : {type(row[6])}")
print(f"NUMBER(5, 2)Zu "7.1」 : {type(row[7])}")
Ausführungsergebnis
$ python sample06a.py
"7" für NUMMER: <class 'int'>
"7" in NUMMER.0」 : <class 'int'>
"7" in NUMMER.1」 : <class 'float'>
NUMBER(5, 0)Auf "7": <class 'int'>
NUMBER(5, 0)Zu "7.0」 : <class 'int'>
NUMBER(5, 2)Auf "7": <class 'float'>
NUMBER(5, 2)Zu "7.0」 : <class 'float'>
NUMBER(5, 2)Zu "7.1」 : <class 'float'>
Aus dem Ausführungsergebnis sind die folgenden Regeln ersichtlich.
Es gibt kein besonderes Problem mit dem Typ int, aber das Problem ist der Typ float. Bei Geschäftsanwendungen, bei denen häufig Oracle Database verwendet wird, besteht die Sorge, dass Rundungsfehler auftreten und Probleme verursachen können, insbesondere bei Informationen zu Geld und schwebenden Brüchen. In solchen Fällen verwendet Python das Dezimalmodul, um damit umzugehen, aber cx_Oracle selbst konvertiert nicht in Dezimalzahlen, wie in der obigen Tabelle gezeigt. Cx_Oracle ist jedoch für solche Fälle vorbereitet.
outputtypehandler Wenn Sie aus den oben genannten Gründen die Konvertierungsspezifikation des Standarddatentyps von cx_Oracle nicht verwenden möchten und Ihre eigene Datenkonvertierungsfunktion im Attribut outputtypehandler des Connection-Objekts angeben, wird diese Funktion anstelle der ursprünglichen Konvertierungsregel konvertiert. Wird verwendet. Im Fall von Python → Oracle ist dies das Attribut inputtypehandler.
sample06b.py
import cx_Oracle
import decimal
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = "select * from sample06a"
def num2Dec(cursor, name, defaultType, size, precision, scale):
if defaultType == cx_Oracle.NUMBER:
return cursor.var(decimal.Decimal, arraysize=cursor.arraysize)
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
row = cursor.execute(SQL).fetchone()
print(f"Kein Handler für Ausgabetypen")
print(f"Stellen Sie NUMBER auf "7" und verdreifachen Sie: {row[0] * 3}")
print(f""7" in NUMMER.1 ”wird gesetzt und verdreifacht: {row[2] * 3}")
with connection.cursor() as cursor:
cursor.outputtypehandler = num2Dec
row = cursor.execute(SQL).fetchone()
print(f"Mit Ausgabetyp-Handler")
print(f"Stellen Sie NUMBER auf "7" und verdreifachen Sie: {row[0] * 3}")
print(f""7" in NUMMER.1 ”wird gesetzt und verdreifacht: {row[2] * 3}")
Bitte beachten Sie, dass dieses Skript die Tabelle und die Daten auswählt, die im vorherigen Skript erstellt wurden. Die num2Dec-Funktion in der Mitte des Skripts ist die eigentliche neue Datenkonvertierungsroutine. Wenn Sie die Funktion num2Dec als Ausgabetyphandler in der 5. Zeile von unten festlegen, funktioniert diese Funktion. Sie können einen beliebigen Funktionsnamen und Argumentnamen des Ausgabetyphandlers angeben. Die Angabe des Arguments ist jedoch wie folgt definiert, und alle 6 sind als Argumente erforderlich, auch wenn sie nicht in der Funktion verwendet werden.
Argumentreihenfolge | Bedeutung |
---|---|
1 | Zu bedienendes Cursorobjekt |
2 | Spaltenname |
3 | Spalte cx_Oracle-Datentyp |
4 | Spaltengröße |
5 | Anzahl der Bruchstellen in der Spalte(NUMBER(p,s)S.) |
6 | Gesamtzahl der Stellen in der Spalte(NUMBER(p,s)P.) |
Die var-Methode des Cursor-Objekts im Beispiel ist eine Methode, die die Variableninformationen für die Variable in der entsprechenden Spalte auf die durch das Argument angegebene Form aktualisiert. Geben Sie im ersten Argument den zu ändernden Datentyp an. Muss angegeben werden. Die var-Methode selbst ist eine Methode, die häufig für andere Zwecke als den Ausgabetyphandler verwendet wird. Das zweite und die nachfolgenden Argumente sind als Methodenspezifikation optional. Für die Verwendung des Ausgabetyphandlers ist jedoch ein Parameter namens arraysize erforderlich, und die Arraysize des Cursorobjekts wird festgelegt. Muss eingestellt werden.
Ausführungsergebnis
$ python sample06b.py
Kein Handler für Ausgabetypen
Stellen Sie NUMBER auf "7" und verdreifachen Sie: 21
"7" in NUMMER.1 ”wird gesetzt und verdreifacht: 21.299999999999997
Mit Ausgabetyp-Handler
Stellen Sie NUMBER auf "7" und verdreifachen Sie: 21
"7" in NUMMER.1 ”wird gesetzt und verdreifacht: 21.3
Wenn Sie den Ausgabetyphandler wie das Ausführungsergebnis durchlaufen, wird das Berechnungsergebnis eher erwartet. Natürlich können Sie den outputtypehandler verwenden, anstatt den outputtypehandler zu verwenden, um ihn in einer Python-Float-Typvariablen zu empfangen und dann in eine Dezimalzahl umzuwandeln. Wenn Sie jedoch eine große Anzahl von Spalten haben, können Sie ihn einfach codieren.
Recommended Posts