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
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
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 object
types. 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_numeric
où chaîne vide,, ''
convertit vers NaN
laquelle cette entité doit se traduire en NULL
entité 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 for
boucle plus lente avec iterrows
et 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()
Vous pouvez utiliser Pandas.DataFrame.to_sql
comme
df.to_sql('dbo.tbl_data_xml', con=connection, if_exists='append', index=False )
où append
option représente l'insertion de nouvelles valeurs dans la table, si la version de pandas est 0.15+
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
Convertir dans numeric
les 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