Python / SQL: remplacement des chaînes vides d'un DataFrame par une valeur «Null» pour insérer les données dans une base de données

Nov 29 2020

Disons que j'ai ce dataframe:

REFERENCE = ["GZF882348G", "SFGUZBJLNJU", "FTLNGZ242112", "DFBHGVGHG543"]
IBAN = ["FR7343563", "FR4832545", "FR9858331", "FR2001045"]
DEBIT = [26, '', 856, '']
CREDIT = ['', 324, '', 876]
MONTANT = [641, 33, '', 968]

df = pd.DataFrame({'Référence' : REFERENCE, 'IBAN' : IBAN, 'Débit' : DEBIT, 'Crédit' : CREDIT, 'Montant' : MONTANT})

J'ai un problème de format pour insérer ce genre de données dans ma base de données. Les colonnes "Débit", "Crédit", "Montant" sont définies pour obtenir des flottants sous forme de données. Cependant, les données de ces colonnes ne sont pas seulement des entiers, j'ai aussi des chaînes vides et c'est mon problème. Je sais que je dois écrire une condition qui remplace une chaîne vide par une valeur "Null" au format SQL, mais je ne sais pas comment faire cela en python ou en SQL. Je découvre / apprends l'environnement SQL.

Voici mon code:

import pandas as pd
import pyodbc 

server = '...'
database = '...'
username = '...' 
password = '...'
driver = '...'

connection = pyodbc.connect('DRIVER='+driver+';SERVER='+server+';PORT=1433;DATABASE='+database+';UID='+username+';PWD='+password)
cursor = connection.cursor()

for i, row in df.iterrows():


    sql_exe = "INSERT INTO dbo.tbl_data_xml (Réference,IBAN,Débit,Crédit,Montant) VALUES (?,?,?,?,?)"
    cursor.execute(sql_exe, tuple(row))
    
    connection.commit()

N'importe qui peut m'aider s'il vous plaît.

Je vous remercie

Réponses

1 Parfait Nov 30 2020 at 02:13

Vous semblez mélanger des types dans le bloc de données Pandas où la chaîne,, ''est combinée avec un entier dans la même colonne comme en témoignent tous les objecttypes. Dans les bases de données relationnelles, vous ne pouvez pas mélanger les types de données. Et la conversion ''en chaîne 'NULL'ne résoudra pas votre problème. En SQL,NULL <> 'NULL'

df.dtypes

# Référence    object
# IBAN         object
# Débit        object
# Crédit       object
# Montant      object
# dtype: object

Par conséquent, convertissez les colonnes en nombres avec pd.to_numericoù chaîne vide,, ''convertit vers NaNlaquelle cette entité doit se traduire en NULLentité SQL .

df[['Débit', 'Crédit', 'Montant']] = df[['Débit', 'Crédit', 'Montant']].apply(pd.to_numeric)

df.dtypes
# Référence     object
# IBAN          object
# Débit        float64
# Crédit       float64
# Montant      float64
# dtype: object

df
#       Référence       IBAN  Débit  Crédit  Montant
# 0    GZF882348G  FR7343563   26.0     NaN    641.0
# 1   SFGUZBJLNJU  FR4832545    NaN   324.0     33.0
# 2  FTLNGZ242112  FR9858331  856.0     NaN      NaN
# 3  DFBHGVGHG543  FR2001045    NaN   876.0    968.0

Exécutez ensuite votre requête. En fait, évitez la forboucle plus lente avec iterrowset considérez df.to_numpy+ cursor.executemany.

# PREPARED STATEMENT
sql_exe = "INSERT INTO dbo.tbl_data_xml (Réference,IBAN,Débit,Crédit,Montant) VALUES (?,?,?,?,?)"

# CONVERT DATA TO LIST OF NUMPY ARRAYS
sql_data = df.where(pd.notnull(df), None).to_numpy().replace(.tolist()

# EXECUTE ACTION QUERY
cursor.executemany(sql_exe, sql_data)
connection.commit()
1 BarbarosÖzhan Nov 29 2020 at 21:32

Vous pouvez utiliser Pandas.DataFrame.to_sqlcomme

df.to_sql('dbo.tbl_data_xml', con=connection, if_exists='append', index=False )

appendoption représente l'insertion de nouvelles valeurs dans la table, si la version de pandas est 0.15+

DaniMesejo Nov 29 2020 at 21:30

Vous pourriez faire:

df.loc[df['Débit'].eq(''), 'Débit'] = 'NULL'
df.loc[df['Crédit'].eq(''), 'Crédit'] = 'NULL'
df.loc[df['Montant'].eq(''), 'Montant'] = 'NULL'

print(df)

Production

      Référence       IBAN Débit Crédit Montant
0    GZF882348G  FR7343563    26   NULL     641
1   SFGUZBJLNJU  FR4832545  NULL    324      33
2  FTLNGZ242112  FR9858331   856   NULL    NULL
3  DFBHGVGHG543  FR2001045  NULL    876     968

Ou simplement,

df[df[['Débit', 'Crédit', 'Montant']].eq('')] = "NULL"
print(df)

Production

      Référence       IBAN Débit Crédit Montant
0    GZF882348G  FR7343563    26   NULL     641
1   SFGUZBJLNJU  FR4832545  NULL    324      33
2  FTLNGZ242112  FR9858331   856   NULL    NULL
3  DFBHGVGHG543  FR2001045  NULL    876     968
wwnde Nov 29 2020 at 21:35

Convertir dans numericles colonnes respectives etfillna(NULL)

df[['Débit', 'Crédit', 'Montant']]=df.iloc[:,2:].apply(lambda x: pd.to_numeric(x).fillna('NULL'))



     Référence       IBAN Débit Crédit Montant
0    GZF882348G  FR7343563    26   NULL     641
1   SFGUZBJLNJU  FR4832545  NULL    324      33
2  FTLNGZ242112  FR9858331   856   NULL    NULL
3  DFBHGVGHG543  FR2001045  NULL    876     968