pymysql用list做insert操作两个“难缠”问题

在使用pymysql进行批量insert操作时,可能会遇到错误220,原因是字典列表中元素的键值数量不一致。此外,即使不报错,如果键值顺序不同,也可能导致插入的数据错误。解决方案是先对字典列表进行预处理,确保所有元素具有相同的键且按相同顺序排列,这样可以避免上述问题。
摘要由CSDN通过智能技术生成

用pymysql做批量insert操作时,一般是用list第一个元素进行sql语句拼装,比如:

INSERT INTO order_status (code, description) values (%s, %s)

上述语句中的字段名code和description是根据0号元素的key值用代码拼装出来的:

    # 拼接insert字符串
    def __concatInsertSqlStr(self, table_name, dict_list, insert_str = 'INSERT'):
        dict_key = dict_list[0]
    
        fields_str = ''
        bind_str = ''
        for field_name in dict_key.keys(): # 字段名
            if len(fields_str) == 0:
                fields_str = '(' + field_name
                bind_str = 'values(%s'
            else:
                fields_str = fields_str + ',' + field_name
                bind_str = bind_str + ',%s'
        sql_str = insert_str + ' INTO ' + table_name + ' ' + fields_str + ') ' + bind_str + ')'
        
        return sql_str

如此,即可封装一个通用的list批量insert函数。

但是,可能出现两个难缠的问题。

第一个:220报错,比较明确

错误220 not enough arguments for format string

这个问题错误原因比较明确,就是因为list中的某个元素key值数量不对,多了或少了。因为python的字典list太过灵活,在list量大的时候很难查。

上面这个错误是由这个语句引发的:

r_log = [{'code': '9', 'description': '描述1'}, {'code': '7', }]
ret = dbopr_pool.insertDictList('order_status', r_log)

r_log数组list的1号元素少了description键值。

要解决这个问题,只需要找出键值数不一致的元素即可。

第二个:没有报错,但是结果不对

这个问题很难发现,因为insert语句成功了,也插入预期的记录数,但是字段值不对。

原因是,list各元素的键值顺序不一致,而拼接insert语句是基于0号元素的字典键值顺序。同时,pymysql会进行数据类型的强制转换,因此尽管可能数据类型不匹配,但也会被转换为目标数据类型。

例如:

r_log = [{'code': '9', 'description': '描述1'}, {'description': '描述2', 'code': '7', }]
ret = dbopr_pool.insertDictList('order_status', r_log)

r_log数组list的1号元素键值顺序与0号元素不同。这个语句insert结果不会出错,也成功插入了两条记录,但是第二条记录的字段值全错了。

解决方法

要解决这两个问题,只需要预先对list进行“整理”:

  1. 以0号元素为基准,检查各元素键值是否都与0号元素一致;

  1. 对各元素按键值进行排序。

代码如下:

    def __preProcDictList(self, dict_list):
        if (type(dict_list) != type([])) or (dict_list == None) or (len(dict_list) < 1):
            return None
        
        new_dict_list = []
        sorted_key = sorted(dict_list[0])
        for dl in dict_list:
            if len(dl) != len(dict_list[0]):
                return None
            
            new_dl = {}
            for key in sorted_key:
                if key not in dl:
                    return None
                else:
                    new_dl[key] = dl[key]
            new_dict_list.append(new_dl)
            
        return new_dict_list 

整理好list之后,再按照0号元素key值进行insert语句拼接。

搞定收工!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值