[Introduction à cx_Oracle] (Partie 6) Mappage des types de données DB et Python

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

Quels types de données dans la base de données Oracle sont finalement mappés vers quels types de données Python sont résumés dans le manuel cx_Oracle sous forme de tableau (https://cx-oracle.readthedocs.io/). fr / latest / user_guide / sql_execution.html # fetch-data-types). Comme vous pouvez le voir dans la table liée, les données obtenues à partir de la base de données Oracle sont une fois converties en données du type de données cx_Oracle et stockées dans le type de données Python via le type de données cx_Oracle. Le flux est l'inverse pour les données mises à jour. Voici la correspondance des principaux types de données. Voir le manuel ci-dessus pour une liste complète.

Type de données Oracle Database cx_Type de données Oracle Type de données Python
CHAR cx_Oracle.FIXED_CHAR str
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

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


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.

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"Aucun gestionnaire de type de sortie")
                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 le gestionnaire de type de sortie")
                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 sample06b.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 6) Mappage des types de données DB et Python
[Introduction à cx_Oracle] (Partie 9) Mappage des types de données DB et Python (version 8 ou ultérieure)
Résolution de l'introduction d'AOJ aux algorithmes et aux structures de données en Python -Partie1-
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-
Entraine toi! !! Introduction au type Python (conseils de type)
[Introduction à Python3 Jour 1] Programmation et Python
[Introduction à cx_Oracle] (Partie 4) Récupération et défilement du jeu de résultats
Introduction à Python Hands On Partie 1
[Introduction to Data Scientists] Bases de Python ♬ Fonctions et classes
[Introduction à Python] Combinaison des données Nikkei Average et NY Dow CSV
[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 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
Introduction au langage Python
Introduction à OpenCV (python) - (2)
Introduction à PyQt4 Partie 1
[Introduction à l'application Udemy Python3 +] 35. Opérateurs de comparaison et opérateurs logiques
[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-
Je veux pouvoir analyser des données avec Python (partie 3)
Introduction à Python Django (2) Win
[Introduction aux Data Scientists] Statistiques descriptives et analyse de régression simple ♬
[Introduction à cx_Oracle] Présentation de cx_Oracle
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
20200329_Introduction à l'analyse de données avec Python 2nd Edition Personal Summary
Introduction à la communication série [Python]