Python / SQL: substituindo as strings vazias de um DataFrame por um valor “Null” para inserir os dados em um banco de dados
Digamos que eu tenha este 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})
Estou com um problema de formato para inserir este tipo de dados em meu banco de dados. As colunas "Débit", "Crédit", "Montant" são definidas para obter flutuações como dados. No entanto, os dados dessas colunas não são apenas inteiros, também tenho strings vazias e esse é o meu problema. Eu sei que tenho que escrever uma condição que substitua uma string vazia por um valor "Nulo" no formato SQL, mas não sei como fazer isso em python ou em SQL. Estou descobrindo / aprendendo o ambiente SQL.
Aqui está o meu 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()
Alguém pode me ajudar, por favor.
Obrigado
Respostas
Você parece estar misturando tipos no quadro de dados do Pandas, onde string ''
,, é combinado com um inteiro na mesma coluna, conforme evidenciado por todos os object
tipos. Em bancos de dados relacionais, você não pode misturar tipos de dados. E a conversão ''
para string 'NULL'
não resolverá seu problema. No SQL,NULL <> 'NULL'
df.dtypes
# Référence object
# IBAN object
# Débit object
# Crédit object
# Montant object
# dtype: object
Portanto, converta colunas em numéricas com pd.to_numeric
onde string vazia,, ''
converte para a NaN
qual essa entidade deve ser convertida em NULL
entidade 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
Em seguida, execute sua consulta. Na verdade, evite o for
loop mais lento com iterrows
e 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()
Você pode usar Pandas.DataFrame.to_sql
como
df.to_sql('dbo.tbl_data_xml', con=connection, if_exists='append', index=False )
onde append
opção significa inserir novos valores na tabela, se a versão do pandas for 0,15+
Você poderia fazer:
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)
Resultado
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 simplesmente,
df[df[['Débit', 'Crédit', 'Montant']].eq('')] = "NULL"
print(df)
Resultado
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
Converta para numeric
as respectivas colunas efillna(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