Python / SQL: reemplazar las cadenas vacías de un DataFrame por un valor "Null" para insertar los datos en una base de datos
Digamos que tengo este marco de datos:
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})
Tengo un problema de formato para insertar este tipo de datos en mi base de datos. Las columnas "Débit", "Crédit", "Montant" se definen para obtener flotantes como datos. Sin embargo, los datos de estas columnas no son solo números enteros, también tengo cadenas vacías y ese es mi problema. Sé que tengo que escribir una condición que reemplace una cadena vacía por un valor "Nulo" en el formato SQL, sin embargo, no sé cómo hacerlo en Python o SQL. Estoy descubriendo / aprendiendo el entorno SQL.
Aquí está mi código:
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()
Cualquiera puede ayudarme por favor.
Gracias
Respuestas
Parece que está mezclando tipos en el marco de datos de Pandas donde la cadena,, ''
se combina con un entero en la misma columna, como lo demuestran todos los object
tipos. En las bases de datos relacionales no se pueden mezclar tipos de datos. Y la conversión ''
a cadena 'NULL'
no resolverá su problema. En SQL,NULL <> 'NULL'
df.dtypes
# Référence object
# IBAN object
# Débit object
# Crédit object
# Montant object
# dtype: object
Por lo tanto, convierta las columnas a numéricas con pd.to_numeric
donde la cadena vacía,, se ''
convierte a lo NaN
que esta entidad debería traducirse a la NULL
entidad de 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
Luego ejecute su consulta. De hecho, evite el for
ciclo más lento con iterrows
y considere 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()
Puedes usar Pandas.DataFrame.to_sql
como
df.to_sql('dbo.tbl_data_xml', con=connection, if_exists='append', index=False )
donde append
opción significa insertar nuevos valores en la tabla, si la versión de pandas es 0.15+
Podrías hacerlo:
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)
Salida
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
O simplemente,
df[df[['Débit', 'Crédit', 'Montant']].eq('')] = "NULL"
print(df)
Salida
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
Convierta a numeric
las columnas respectivas yfillna(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