Python脚本导入多列CSV到MySQL时出现参数不足错误的求助
Python脚本导入多列CSV到MySQL时出现参数不足错误的求助
嗨,别担心,这个问题其实挺常见的,咱们一步步来解决它!
首先看你遇到的Not enough parameters for the SQL statement错误,核心原因是你传给SQL的参数数量和语句里的%s数量不匹配。你现在的代码里,for row in f循环拿到的row是一整行的字符串(比如"192.168.1.16,192.168.1.255,..."),然后你把它作为单个参数(row,)传给execute方法,但你的SQL语句里有84个%s,自然就会报错参数不够啦。
接下来咱们一步步修正代码:
1. 正确读取CSV内容,拆分每一行的字段
不要直接遍历文件行,而是用Python内置的csv模块来读取,它会自动帮你把每一行拆分成对应的字段列表,还能处理可能的特殊情况(比如字段里包含逗号的场景)。
2. 跳过CSV的表头(如果有的话)
如果你的实际CSV第一行是表头(比如src_ip,dst_ip,...),记得要跳过,不然会把表头字符串插入到数值类型的字段里,导致新的类型不匹配错误。
3. 替换SQL语句里的'%s'为%s,避免SQL注入风险
你现在的SQL里写的是'%s'(带单引号),但用参数化查询的时候,MySQL连接器会自动处理字符串的引号,不需要手动加,手动加反而会导致参数解析错误,还存在SQL注入的安全隐患。
4. 数据类型转换
你的MySQL表字段有INT、FLOAT、DATETIME等类型,从CSV读出来的都是字符串,需要把对应的字段转换成正确的类型,不然插入的时候可能会报错类型不兼容。
修正后的完整代码
import mysql.connector import csv from datetime import datetime # 连接数据库 db = mysql.connector.connect( host="localhost", user="root", passwd="root", database="Apollo" ) mycursor = db.cursor() # 表创建函数(安装时调用) def db_setup(): create_table_sql = """ CREATE TABLE NetworkLogs ( id INT AUTO_INCREMENT PRIMARY KEY, src_ip VARCHAR(15), dst_ip VARCHAR(15), src_port INT, dst_port INT, src_mac VARCHAR(17), dst_mac VARCHAR(17), protocol INT, timestamp DATETIME, flow_duration FLOAT, flow_byts_s FLOAT, flow_pkts_s FLOAT, fwd_pkts_s FLOAT, bwd_pkts_s FLOAT, tot_fwd_pkts INT, tot_bwd_pkts INT, totlen_fwd_pkts INT, totlen_bwd_pkts INT, fwd_pkt_len_max FLOAT, fwd_pkt_len_min FLOAT, fwd_pkt_len_mean FLOAT, fwd_pkt_len_std FLOAT, bwd_pkt_len_max FLOAT, bwd_pkt_len_min FLOAT, bwd_pkt_len_mean FLOAT, bwd_pkt_len_std FLOAT, pkt_len_max FLOAT, pkt_len_min FLOAT, pkt_len_mean FLOAT, pkt_len_std FLOAT, pkt_len_var FLOAT, fwd_header_len INT, bwd_header_len INT, fwd_seg_size_min INT, fwd_act_data_pkts INT, flow_iat_mean FLOAT, flow_iat_max FLOAT, flow_iat_min FLOAT, flow_iat_std FLOAT, fwd_iat_tot FLOAT, fwd_iat_max FLOAT, fwd_iat_min FLOAT, fwd_iat_mean FLOAT, fwd_iat_std FLOAT, bwd_iat_tot FLOAT, bwd_iat_max FLOAT, bwd_iat_min FLOAT, bwd_iat_mean FLOAT, bwd_iat_std FLOAT, fwd_psh_flags INT, bwd_psh_flags INT, fwd_urg_flags INT, bwd_urg_flags INT, fin_flag_cnt INT, syn_flag_cnt INT, rst_flag_cnt INT, psh_flag_cnt INT, ack_flag_cnt INT, urg_flag_cnt INT, ece_flag_cnt INT, down_up_ratio FLOAT, pkt_size_avg FLOAT, init_fwd_win_byts INT, init_bwd_win_byts INT, active_max FLOAT, active_min FLOAT, active_mean FLOAT, active_std FLOAT, idle_max FLOAT, idle_min FLOAT, idle_mean FLOAT, idle_std FLOAT, fwd_byts_b_avg FLOAT, fwd_pkts_b_avg FLOAT, bwd_byts_b_avg FLOAT, bwd_pkts_b_avg FLOAT, fwd_blk_rate_avg FLOAT, bwd_blk_rate_avg FLOAT, fwd_seg_size_avg FLOAT, bwd_seg_size_avg FLOAT, cwe_flag_count INT, subflow_fwd_pkts INT, subflow_bwd_pkts INT, subflow_fwd_byts INT, subflow_bwd_byts INT ) """ mycursor.execute(create_table_sql) # 插入数据到数据库 def db_post(): csv_file_path = 'src/cicflowmeter/test1.csv' # 定义字段的类型转换函数,按顺序对应表的字段(除了自增的id) type_converters = [ str, str, int, int, str, str, int, lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S'), float, float, float, float, float, int, int, int, int, float, float, float, float, float, float, float, float, float, float, float, float, float, int, int, int, int, float, float, float, float, float, float, float, float, float, float, float, float, float, float, int, int, int, int, int, int, int, int, int, int, int, float, float, int, int, float, float, float, float, float, float, float, float, float, float, float, float, int, int, int, int, int ] with open(csv_file_path, 'r') as f: csv_reader = csv.reader(f) # 如果你的CSV有表头,取消下面这行注释跳过表头 # next(csv_reader) for row in csv_reader: # 转换每个字段的类型 converted_row = [converter(val) for converter, val in zip(type_converters, row)] # 自动生成占位符,避免手动写84个%s placeholders = ', '.join(['%s'] * len(converted_row)) query = f""" INSERT INTO NetworkLogs ( src_ip, dst_ip, src_port, dst_port, src_mac, dst_mac, protocol, timestamp, flow_duration, flow_byts_s, flow_pkts_s, fwd_pkts_s, bwd_pkts_s, tot_fwd_pkts, tot_bwd_pkts, totlen_fwd_pkts, totlen_bwd_pkts, fwd_pkt_len_max, fwd_pkt_len_min, fwd_pkt_len_mean, fwd_pkt_len_std, bwd_pkt_len_max, bwd_pkt_len_min, bwd_pkt_len_mean, bwd_pkt_len_std, pkt_len_max, pkt_len_min, pkt_len_mean, pkt_len_std, pkt_len_var, fwd_header_len, bwd_header_len, fwd_seg_size_min, fwd_act_data_pkts, flow_iat_mean, flow_iat_max, flow_iat_min, flow_iat_std, fwd_iat_tot, fwd_iat_max, fwd_iat_min, fwd_iat_mean, fwd_iat_std, bwd_iat_tot, bwd_iat_max, bwd_iat_min, bwd_iat_mean, bwd_iat_std, fwd_psh_flags, bwd_psh_flags, fwd_urg_flags, bwd_urg_flags, fin_flag_cnt, syn_flag_cnt, rst_flag_cnt, psh_flag_cnt, ack_flag_cnt, urg_flag_cnt, ece_flag_cnt, down_up_ratio, pkt_size_avg, init_fwd_win_byts, init_bwd_win_byts, active_max, active_min, active_mean, active_std, idle_max, idle_min, idle_mean, idle_std, fwd_byts_b_avg, fwd_pkts_b_avg, bwd_byts_b_avg, bwd_pkts_b_avg, fwd_blk_rate_avg, bwd_blk_rate_avg, fwd_seg_size_avg, bwd_seg_size_avg, cwe_flag_count, subflow_fwd_pkts, subflow_bwd_pkts, subflow_fwd_byts, subflow_bwd_byts ) VALUES ({placeholders}) """ mycursor.execute(query, converted_row) db.commit() print("数据插入成功!") db_post()
额外注意事项
- 如果你CSV的第一行是表头,一定要取消代码里
next(csv_reader)的注释,否则会把表头字符串插入到数值字段中,引发类型错误。 - 代码里的类型转换逻辑确保了每个字段和MySQL表的类型匹配,比如把端口号转成INT、时间字符串转成
datetime对象,避免插入时的类型不兼容问题。 - 用
csv.reader比直接遍历文件行更可靠,它能处理标准CSV格式的各种特殊情况。 - 自动生成占位符的方式,避免了手动写84个
%s的麻烦,也减少了写错的概率。
试试看这个修正后的代码,应该就能解决你的问题啦!如果还有其他报错,可以再告诉我具体的错误信息哦~
备注:内容来源于stack exchange,提问作者Ryan Casey
相关产品推荐
相关产品推荐

