[Introduction à cx_Oracle] (Partie 9) Mappage des types de données DB et Python (version 8 ou ultérieure)

Environnement de vérification

--Utilisation d'Oracle Cloud

introduction

Bien sûr, les types de données sont différents entre Oracle Database et Python. Dans cet article, j'expliquerai comment cx_Oracle sert d'intermédiaire entre les deux types de données.

Présentation du mappage des types de données

Quel type de données de la base de données Oracle est finalement mappé à quel type de données Python peut être trouvé dans le manuel cx_Oracle (https://cx-oracle.readthedocs.io/en/latest/user_guide/sql_execution.html). Il est résumé dans # fetch-data-types). Échange de types de données entre Oracle Database et Python Type de données Oracle Database ⇔ Type de données cx_Oracle ⇔ Type de données Python Il sera converti via le flux. Fondamentalement, il existe un type de données cx_Oracle avec un nom commençant par "DB_TYPE_" qui correspond à un certain type de données Oracle Database. Le type de données cx_Oracle qui était utilisé jusqu'à cx_Oracle 7.3 (avant 8) peut toujours être utilisé comme synonim, mais comme il sera obsolète à l'avenir, lors de la création d'une nouvelle application avec la version 8 ou de l'utilisation du type de données cx_Oracle Si des révisions doivent être effectuées, essayez d'utiliser le type de données cx_Oracle qui commence par "DB_TYPE_". En outre, les types de données définis dans l'API DB continueront d'être pris en charge.

■ Mappage des types de données

Type de données Oracle Database cx_Type de données Oracle Type de données Python
CHA cx_Oracle.DB_TYPE_CHAR str
VARCHAR2 cx_Oracle.DB_TYPE_VARCHAR str
NUMBER cx_Oracle.DB_TYPE_NUMBER float ou int
DATE cx_Oracle.DB_TYPE_DATE datetime.datetime
TIMESTAMP cx_Oracle.DB_TYPE_TIMESTAMP datetime.datetime
RAW cx_Oracle.DB_TYPE_RAW bytes

■ Mappage de type de données conforme à DB API

Type de données Oracle Database cx_Type de données Oracle Type de données Python
CHAR, VARCHAR2 cx_Oracle.STRING str
NUMBER cx_Oracle.NUMBER float ou int
DATE cx_Oracle.DATETIME datetime.datetime
TIMESTAMP cx_Oracle.TIMESTAMP datetime.datetime
RAW cx_Oracle.BINARY bytes

■ Référence du manuel Type de données cx_Oracle conforme à l'API DB type de données propriétaire cx_Oracle

Il convient de noter ici qu'il existe deux types de types de données Python qui prennent en charge le type NUMBER: float et int. Cela dépend de la définition du type NUMBER et de la valeur stockée. Vérifiez le résultat de l'exécution de l'exemple d'application ci-dessous.

sample06a.py(Republier)


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" pour NUMBER: {type(row[0])}")
                print(f""7" en NUMBER.0」 : {type(row[1])}")
                print(f""7" en NUMBER.1」 : {type(row[2])}")
                print(f"NUMBER(5, 0)Vers "7": {type(row[3])}")
                print(f"NUMBER(5, 0)Vers "7.0」 : {type(row[4])}")
                print(f"NUMBER(5, 2)Vers "7": {type(row[5])}")
                print(f"NUMBER(5, 2)Vers "7.0」 : {type(row[6])}")
                print(f"NUMBER(5, 2)Vers "7.1」 : {type(row[7])}")

Résultat d'exécution


$ python sample06a.py
"7" pour NUMBER: <class 'int'>
"7" en NUMBER.0」 : <class 'int'>
"7" en NUMBER.1」 : <class 'float'>
NUMBER(5, 0)Vers "7": <class 'int'>
NUMBER(5, 0)Vers "7.0」 : <class 'int'>
NUMBER(5, 2)Vers "7": <class 'float'>
NUMBER(5, 2)Vers "7.0」 : <class 'float'>
NUMBER(5, 2)Vers "7.1」 : <class 'float'>

À partir du résultat de l'exécution, les règles suivantes peuvent être vues.

Il n'y a pas de problème particulier avec le type int, mais le problème est le type float. Pour les applications métier où Oracle Database est souvent utilisé, il est à craindre que des erreurs d'arrondi puissent se produire et causer des problèmes, en particulier lorsqu'il s'agit d'informations sur l'argent et les fractions flottantes. Dans de tels cas, Python utilise le module décimal pour le gérer, mais cx_Oracle lui-même ne se convertit pas en décimal, comme indiqué dans le tableau ci-dessus. Cependant, cx_Oracle fournit de tels cas.

outputtypehandler Pour les raisons mentionnées ci-dessus, si vous ne souhaitez pas utiliser la spécification de conversion du type de données par défaut de cx_Oracle, si vous spécifiez votre propre fonction de conversion de données dans l'attribut outputtypehandler de l'objet Connection, cette fonction sera convertie à la place de la règle de conversion d'origine. Sera utilisé. Dans le cas de la direction Python → Oracle, il s'agit de l'attribut inputtypehandler.

sample09a.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.DB_TYPE_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"Aucun OutputTypeHandler")
                print(f"Définissez NUMBER sur «7» et tripler: {row[0] * 3}")
                print(f""7" en NUMBER.1 "est défini et triplé: {row[2] * 3}")
        with connection.cursor() as cursor:
                cursor.outputtypehandler = num2Dec
                row = cursor.execute(SQL).fetchone()
                print(f"Avec OutputTypeHandler")
                print(f"Définissez NUMBER sur «7» et tripler: {row[0] * 3}")
                print(f""7" en NUMBER.1 "est défini et triplé: {row[2] * 3}")

Veuillez noter que ce script SELECTs la table et les données créées dans le script précédent. La fonction num2Dec au milieu du script est la nouvelle routine de conversion de données. En définissant la fonction num2Dec comme gestionnaire de type de sortie sur la 5ème ligne à partir du bas, cette fonction fonctionnera. Vous pouvez spécifier n'importe quel nom de fonction et nom d'argument du gestionnaire de type de sortie, mais la spécification de l'argument est définie comme suit, et les 6 sont obligatoires comme arguments même s'ils ne sont pas utilisés dans la fonction.

Ordre des arguments sens
1 Objet curseur à utiliser
2 Nom de colonne
3 Colonne cx_Type de données Oracle
4 Taille de la colonne
5 Nombre de chiffres fractionnaires dans la colonne(NUMBER(p,s)S)
6 Nombre total de chiffres dans la colonne(NUMBER(p,s)P)

La méthode var de l'objet Cursor dans l'exemple est une méthode qui met à jour les informations de variable pour la variable dans la colonne correspondante sous la forme spécifiée par l'argument. Dans le premier argument, spécifiez le type de données à modifier. Doit être spécifié. La méthode var elle-même est une méthode largement utilisée à des fins autres que outputtypehandler, et le deuxième argument et les suivants sont facultatifs en tant que spécification de méthode, mais pour l'utilisation du outputtypehandler, un paramètre appelé arraysize est requis et la taille du tableau de l'objet Cursor est définie. Doit être réglé.

Résultat d'exécution


$ python sample09a.py
Aucun gestionnaire de type de sortie
Définissez NUMBER sur «7» et tripler: 21
"7" en NUMBER.1 "est défini et triplé: 21.299999999999997
Avec le gestionnaire de type de sortie
Définissez NUMBER sur «7» et tripler: 21
"7" en NUMBER.1 "est défini et triplé: 21.3

Si vous passez par le gestionnaire de type de sortie comme le résultat de l'exécution, le résultat du calcul sera plus attendu. Bien sûr, au lieu d'utiliser le outputtypehandler, vous pouvez le recevoir dans une variable de type float Python, puis le convertir en décimal, mais si vous avez un grand nombre de colonnes prises en charge, vous pouvez facilement coder en utilisant le outputtypehandler.

Recommended Posts

[Introduction à cx_Oracle] (Partie 9) Mappage des types de données DB et Python (version 8 ou ultérieure)
[Introduction à cx_Oracle] (Partie 6) Mappage des types de données DB et Python
Résolution de l'introduction d'AOJ aux algorithmes et aux structures de données en Python -Partie2-
Résolution de l'introduction d'AOJ aux algorithmes et aux structures de données en Python -Partie4-
Résolution de l'introduction d'AOJ aux algorithmes et aux structures de données en Python -Partie3-
Introduction à Python (version Python APG4b)
[Introduction à cx_Oracle] (Partie 4) Récupération et défilement du jeu de résultats
[Introduction to Data Scientists] Bases de Python ♬ Fonctions et classes
[Introduction à Python] Combinaison des données Nikkei Average et NY Dow CSV
Entraine toi! !! Introduction au type Python (conseils de type)
[Introduction à Python3 Jour 1] Programmation et Python
Introduction à Python Hands On Partie 1
[AWS SAM] Présentation de la version Python
[Introduction à cx_Oracle] (Partie 2) Principes de base de la connexion et de la déconnexion à Oracle Database
[Introduction to Data Scientists] Bases de Python ♬ Branchements conditionnels et boucles
[Introduction à Python] Comment utiliser l'opérateur booléen (et ・ ou ・ non)
[Introduction aux Data Scientists] Bases de Python ♬ Fonctions et fonctions anonymes, etc.
[Introduction à l'application Udemy Python3 +] 28. Type collectif
[Introduction à Python3, jour 17] Chapitre 8 Destinations de données (8.1-8.2.5)
[Introduction à Python3, jour 17] Chapitre 8 Destinations de données (8.3-8.3.6.1)
Web-WF Python Tornado Partie 3 (Introduction à Openpyexcel)
[Introduction à l'application Udemy Python3 +] 21. Type Taple
[Introduction à Python3 Jour 19] Chapitre 8 Destinations de données (8.4-8.5)
[Introduction à cx_Oracle] (12e) Gestion des exceptions DB
[Introduction à cx_Oracle] (17e) Gestion du type de date
[Introduction à Python3 Day 18] Chapitre 8 Destinations de données (8.3.6.2 à 8.3.6.3)
[Introduction à l'application Udemy Python3 +] 24. Type de dictionnaire
Compressez les données python et écrivez sur sqlite
[Introduction à l'application Udemy Python3 +] 16. Type de liste
[Introduction au Data Scientist] Bases de Python ♬
[Introduction à Python3 Jour 12] Chapitre 6 Objets et classes (6.3-6.15)
[Cx_Oracle Primer] (Partie 3) Bases de la navigation dans les tableaux
[Python] Comment lire les données de CIFAR-10 et CIFAR-100
[Introduction à Python3, jour 22] Chapitre 11 Traitement parallèle et mise en réseau (11.1 à 11.3)
[Introduction à Python] Comment gérer les données au format JSON
[Introduction à l'application Udemy Python3 +] 64. Espace de noms et portée
[Introduction à Python3 Jour 11] Chapitre 6 Objets et classes (6.1-6.2)
[Introduction à cx_Oracle] (5e) Gestion des données japonaises
[Introduction à cx_Oracle] (Partie 7) Gestion des variables de liaison
[Python3] Connexion à Oracle Database et exécution de SQL [cx_Oracle]
Essayez le fonctionnement de la base de données avec Python et visualisez avec d3
Note de lecture: Introduction à l'analyse de données avec Python
[Introduction à cx_Oracle] (Partie 11) Bases de l'exécution PL / SQL
[Introduction à Udemy Python3 + Application] 68. Instruction d'importation et AS
Python # Comment vérifier le type et le type pour les super débutants
[Introduction à cx_Oracle] (13e) Connexion utilisant le pool de connexions (côté client)
Introduction à Python numpy pandas matplotlib (pour ~ B3 ~ part2)
[Livre technique] Introduction à l'analyse de données avec Python -1 Chapitre Introduction-
Notes de lecture (en Python et Stan) pour une introduction à la modélisation statistique pour l'analyse de données (Midorimoto)
Introduction au langage Python
Introduction à OpenCV (python) - (2)
Introduction à PyQt4 Partie 1
Je veux pouvoir analyser des données avec Python (partie 3)
Mettre à jour Raspberry Pi Python vers 3.7 ou version ultérieure avec pyenv
[Introduction aux Data Scientists] Statistiques descriptives et analyse de régression simple ♬
Je veux pouvoir analyser des données avec Python (partie 1)
[Introduction à l'application Udemy Python3 +] 42. pour instruction, instruction break et instruction continue
[Introduction à l'application Udemy Python3 +] 39. instruction while, instruction continue et instruction break
[Introduction à cx_Oracle] (10e) Instruction Update DML et DDL / DCL
[Introduction à l'application Udemy Python3 +] 36. Utilisation de In et Not