You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas向MariaDB插入数据时含空格子查询条件值的转义问题

问题解决:带空格的供应商名称导致MariaDB插入失败

问题描述

使用Python+Pandas将CSV文件导入MariaDB时,插入语句包含两个子查询。当子查询条件值(如供应商名称“example dealer”)包含空格时,子查询仅匹配“example”并返回NULL,触发Column 'Fornitori_idFornitori' cannot be null错误。已尝试修改CSV编码、查询转义,问题未解决。

用户代码片段:

empdata = pd.read_csv(
    "static/files/testfile.csv",
    index_col=False, delimiter=";", on_bad_lines="skip"
)

if conn.is_connected():
    cursor = conn.cursor()
    cursor.execute("select database();")
    record = cursor.fetchone()
    print("You're connected to database: ", record)
    # loop through the data frame
    for i, row in empdata.iterrows():
        sql = "INSERT INTO PRODOTTI (PROD_ATTIVO,EAN13,prod_nome,Prezzo,CAT_IVA_idCAT_IVA,Costo,Quantita,Fornitori_idFornitori,Data_ins) \
                VALUES (%s,%s,%s,%s,(select idCAT_IVA from CAT_IVA where CAT_IVA_aliquota = %s),%s,%s,(select idFornitori from Fornitori where Fornitori_nome = %s),%s)"

解决方案

1. 修复参数化查询的传递逻辑

你的代码仅定义了SQL语句,缺少cursor.execute()的参数传递步骤。若错误使用字符串拼接而非参数绑定传递带空格的字段值,会导致字段被拆分。正确做法是将DataFrame行数据作为元组传入execute():

for i, row in empdata.iterrows():
    sql = "INSERT INTO PRODOTTI (PROD_ATTIVO,EAN13,prod_nome,Prezzo,CAT_IVA_idCAT_IVA,Costo,Quantita,Fornitori_idFornitori,Data_ins) \
            VALUES (%s,%s,%s,%s,(select idCAT_IVA from CAT_IVA where CAT_IVA_aliquota = %s),%s,%s,(select idFornitori from Fornitori where Fornitori_nome = %s),%s)"
    # 替换为DataFrame中对应的列名,确保顺序与SQL中的%s一一对应
    values = (
        row['PROD_ATTIVO'], row['EAN13'], row['prod_nome'], row['Prezzo'],
        row['CAT_IVA_aliquota'], row['Costo'], row['Quantita'],
        row['Fornitori_nome'], row['Data_ins']
    )
    cursor.execute(sql, values)
conn.commit()  # 必须提交事务才能保存数据

2. 处理数据中的前后空格

若Fornitori表的Fornitori_nome字段或CSV中的供应商名称存在前后空格,会导致匹配失败。修改子查询,用TRIM()去除两端空格:

(select idFornitori from Fornitori where TRIM(Fornitori_nome) = TRIM(%s))

3. 预加载映射字典,避免重复子查询

循环中重复执行子查询效率低且易出匹配问题,建议先从数据库读取映射关系,直接在循环中查找:

# 预加载供应商名称与ID的映射
cursor.execute("SELECT idFornitori, Fornitori_nome FROM Fornitori")
fornitori_map = {nome.strip(): id_ for id_, nome in cursor.fetchall()}

# 预加载税目比例与ID的映射
cursor.execute("SELECT idCAT_IVA, CAT_IVA_aliquota FROM CAT_IVA")
iva_map = {str(aliquota): id_ for id_, aliquota in cursor.fetchall()}

# 循环插入数据
for i, row in empdata.iterrows():
    fornitori_id = fornitori_map.get(row['Fornitori_nome'].strip())
    iva_id = iva_map.get(str(row['CAT_IVA_aliquota']))
    
    if not fornitori_id:
        print(f"警告:未找到供应商 {row['Fornitori_nome']},跳过该行")
        continue
    
    sql = "INSERT INTO PRODOTTI (PROD_ATTIVO,EAN13,prod_nome,Prezzo,CAT_IVA_idCAT_IVA,Costo,Quantita,Fornitori_idFornitori,Data_ins) \
            VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
    values = (
        row['PROD_ATTIVO'], row['EAN13'], row['prod_nome'], row['Prezzo'],
        iva_id, row['Costo'], row['Quantita'], fornitori_id, row['Data_ins']
    )
    cursor.execute(sql, values)
conn.commit()

4. 验证CSV读取的完整性

确认Pandas读取的供应商名称是否完整:

print(empdata['Fornitori_nome'].head())

若输出名称被截断或拆分,检查CSV是否用引号包裹带空格的字段(如"example dealer";...),若未包裹,添加quoting参数:

import csv

empdata = pd.read_csv(
    "static/files/testfile.csv",
    index_col=False, delimiter=";", on_bad_lines="skip",
    quoting=csv.QUOTE_ALL
)

内容的提问来源于stack exchange,提问作者TitusI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:32:45