为什么我无法向 SQL Server 插入 NaN?

问题描述 投票:0回答:1

此代码是将Excel文件导入到SQL Server的SQL转换器。 但我无法将空单元格插入 SQL Server 中的 Null 值。

import pandas as pd
import pyodbc
from tkinter import *
from tkinter import filedialog,ttk,messagebox
import os

window = Tk()
window.title("Tooling")
window.geometry('800x500')

def import_data_to_database():
    file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])

    if file_path:
        df = pd.read_excel(file_path)
        file_name = os.path.basename(file_path)
        connect = pyodbc.connect('Driver={SQL Server};'
                          'Server=PBG'
                          'Database=Name;'
                          'Trusted_Connection=yes;')
        cursor = connect.cursor()
        table_name = select_table.get()
        columns = ', '.join(df.columns)
        placeholders = ', '.join(['?']*len(df.columns))
    
        check = pd.read_sql(f"SELECT DISTINCT FileName FROM {table_name}",connect)
        check_list = check[check.columns[0]].values.tolist()
        for x in check_list:
            if file_name == x:
                messagebox.showerror('Error','This File is Imported')
            else:
                df['FileName'] = file_name
                print(df)
                query = f"INSERT INTO {table_name} ({columns}, FileName) VALUES ({placeholders},?)"
                cursor.executemany(query,df.values.tolist())
                connect.commit()
                cursor.close()
                connect.close()
                msg = f"Data has been imported to {table_name} from {file_path}."
                status_label.config(text=msg)

table = ["dbo.PartItem","dbo.Item", "dbo.Part","dbo.Orders","dbo.Material","dbo.PartMat","dbo.Vendor"]
label1 = Label(window, text='Select Table to Import to SQL Server')
label1.grid(row=0, column=0, padx=5)

select_table = ttk.Combobox(window, values= table)
select_table.grid(row=1, column=0, padx=5)

import_button1 = Button(window,text="Import Data",command=import_data_to_database)
import_button1.grid(row=3, column=0, padx=5)

bank1 = Label(window, text="")
bank1.grid(row=4, column=0, padx=5)

status_label = Label(window, text="", fg = "green")
status_label.grid(row=2, column=0, padx=5)

window.mainloop()

有错误: 光标.executemany(查询,df.values.tolist()) pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server 驱动程序][SQL Server]传入的表格数据流 (TDS) 远程过程调用 (RPC) 协议流不正确。参数 8 ("" ): 提供的值不是 float 数据类型的有效实例。请检查源数据中是否存在无效值。无效值的示例是小数位数大于精度的数字类型数据。(8023) (SQLExecDirectW)')

但是我已经设置了表可以为空

python sql-server pandas tkinter pyodbc
1个回答
0
投票

您遇到的错误表明插入 SQL Server 表中的数据类型存在问题。具体来说,错误消息提到为“参数 8”提供的值不是数据类型 float 的有效实例。这表明 Excel 文件中某一列的数据类型与 SQL Server 表中相应列的数据类型不匹配。

要处理此问题并在 SQL Server 中将 NaN(表示 pandas 中的空值或缺失值)插入为 NULL,您需要确保 pandas DataFrame 中列的数据类型与您的 pandas DataFrame 中列的数据类型相匹配。 SQL Server 表。此外,在将 NaN 值插入数据库之前,您应该将其转换为 Python 的

None

以下是如何修改代码以处理 NaN 值和数据类型不匹配的方法:

# ... (your imports and GUI code)

def import_data_to_database():
    file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx")])

    if file_path:
        df = pd.read_excel(file_path)
        file_name = os.path.basename(file_path)
        connect = pyodbc.connect('Driver={SQL Server};'
                          'Server=PBG;'
                          'Database=Name;'
                          'Trusted_Connection=yes;')
        cursor = connect.cursor()
        table_name = select_table.get()

        # Iterate through the columns and convert NaN to None
        for column in df.columns:
            df[column] = df[column].apply(lambda x: x if pd.notna(x) else None)

        columns = ', '.join(df.columns)
        placeholders = ', '.join(['?']*len(df.columns))
    
        check = pd.read_sql(f"SELECT DISTINCT FileName FROM {table_name}",connect)
        check_list = check[check.columns[0]].values.tolist()
        
        for x in check_list:
            if file_name == x:
                messagebox.showerror('Error','This File is Imported')
            else:
                df['FileName'] = file_name
                print(df)
                query = f"INSERT INTO {table_name} ({columns}, FileName) VALUES ({placeholders}, ?)"
                cursor.executemany(query, df.values.tolist())
                connect.commit()
                cursor.close()
                connect.close()
                msg = f"Data has been imported to {table_name} from {file_path}."
                status_label.config(text=msg)

# ... (your GUI code)

window.mainloop()

在此代码中,关键的更改在于循环遍历 DataFrame 的列并将 NaN 值转换为 Python 的

None
。这可确保您将有效值插入到 SQL Server 表中,并且 NULL 值将得到正确处理。

请务必调整“Server=PBG;”以及代码中的其他连接参数,以匹配您实际的 SQL Server 设置。

© www.soinside.com 2019 - 2024. All rights reserved.