Python / SQL: замена пустых строк DataFrame на значение «Null» для вставки данных в базу данных

Nov 29 2020

Допустим, у меня есть этот фрейм данных:

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})

У меня проблема формата для вставки таких данных в мою базу данных. Столбцы «Débit», «Crédit», «Montant» определены для получения данных с плавающей запятой. Однако данные в этих столбцах - не только целые числа, у меня тоже есть пустые строки, и это моя проблема. Я знаю, что мне нужно написать условие, которое заменяет пустую строку значением «Null» в формате SQL, однако я не знаю, как это сделать в python или в SQL. Я открываю / изучаю среду SQL.

Вот мой код:

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()

Кто-нибудь может мне помочь, пожалуйста.

Спасибо

Ответы

1 Parfait Nov 30 2020 at 02:13

Кажется, вы смешиваете типы во фрейме данных Pandas, где строка,, ''комбинируется с целым числом в одном столбце, что подтверждается всеми objectтипами. В реляционных базах данных нельзя смешивать типы данных. И преобразование ''в строку 'NULL'не решит вашу проблему. В SQLNULL <> 'NULL'

df.dtypes

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

Поэтому преобразуйте столбцы в числовые, pd.to_numericгде, где ''преобразуется пустая строка ,, NaNэта сущность должна преобразовываться в NULLсущность 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

Затем запустите свой запрос. Фактически, избегайте более медленного forцикла iterrowsи учитывайте 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

Вы можете использовать Pandas.DataFrame.to_sqlтакие как

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

где appendопция означает вставку новых значений в таблицу, если версия pandas 0.15+

DaniMesejo Nov 29 2020 at 21:30

Вы могли сделать:

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)

Вывод

      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

Или просто,

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

Вывод

      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

Преобразуйте numericв соответствующие столбцы иfillna(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