web-dev-qa-db-fra.com

pandas to_sql toutes les colonnes en tant que nvarchar

J'ai un pandas dataframe qui est créé dynamiquement avec des noms de colonnes qui varient. J'essaie de les pousser vers sql, mais je ne veux pas qu'ils aillent à mssqlserver comme type de données par défaut "text" "(quelqu'un peut-il expliquer pourquoi il s'agit de la valeur par défaut? Ne serait-il pas logique d'utiliser un type de données plus courant?)

Est-ce que quelqu'un sait comment je peux spécifier un type de données pour toutes les colonnes?

column_errors.to_sql('load_errors',Push_conn, if_exists = 'append', index = False, dtype = #Data type for all columns#)

l'argument dtype prend un dict, et comme je ne sais pas quelles seront les colonnes, il est difficile de les définir toutes comme 'sqlalchemy.types.NVARCHAR'

Voici ce que je voudrais faire:

column_errors.to_sql('load_errors',Push_conn, if_exists = 'append', index = False, dtype = 'sqlalchemy.types.NVARCHAR')

Toute aide/compréhension sur la meilleure façon de spécifier tous les types de colonnes serait très appréciée!

13
flyingmeatball

Vous pouvez créer ce dict dynamiquement si vous ne connaissez pas à l'avance les noms des colonnes:

from sqlalchemy.types import NVARCHAR
df.to_sql(...., dtype={col_name: NVARCHAR for col_name in df})

Notez que vous devez passer l'objet de type sqlalchemy lui-même (ou une instance pour spécifier des paramètres comme NVARCHAR(length=10)) et not une chaîne comme dans votre exemple.

23
joris

Pour utiliser dtype , passez un dictionnaire composé de chaque colonne de trame de données avec les types sqlalchemy correspondants . Modifiez les clés en noms de colonne de bloc de données réels:

import sqlalchemy
import pandas as pd
...

column_errors.to_sql('load_errors',Push_conn, 
                      if_exists = 'append', 
                      index = False, 
                      dtype={'datefld': sqlalchemy.DateTime(), 
                             'intfld':  sqlalchemy.types.INTEGER(),
                             'strfld': sqlalchemy.types.NVARCHAR(length=255)
                             'floatfld': sqlalchemy.types.Float(precision=3, asdecimal=True)
                             'booleanfld': sqlalchemy.types.Boolean})

Vous pouvez même être en mesure de créer dynamiquement ce dictionnaire dtype étant donné que vous ne connaissez pas les noms ou types de colonnes au préalable:

def sqlcol(dfparam):    

    dtypedict = {}
    for i,j in Zip(dfparam.columns, dfparam.dtypes):
        if "object" in str(j):
            dtypedict.update({i: sqlalchemy.types.NVARCHAR(length=255)})

        if "datetime" in str(j):
            dtypedict.update({i: sqlalchemy.types.DateTime()})

        if "float" in str(j):
            dtypedict.update({i: sqlalchemy.types.Float(precision=3, asdecimal=True)})

        if "int" in str(j):
            dtypedict.update({i: sqlalchemy.types.INT()})

    return dtypedict

outputdict = sqlcol(df)    
column_errors.to_sql('load_errors', 
                     Push_conn, 
                     if_exists = 'append', 
                     index = False, 
                     dtype = outputdict)
21
Parfait