psycopg2批量插入含ON CONFLICT时混合参数格式报错求助
解决psycopg2参数格式混合错误及ON CONFLICT正确写法
错误原因
你在SQL语句中同时混用了位置参数(%s)和命名参数(%(label_name)s),psycopg2不支持这种混合参数格式,因此触发argument formats can't be mixed错误。
修正方案(统一使用位置参数)
步骤1:修改SQL语句
将%(label_name)s替换为位置参数%s,同时修正ON CONFLICT的WHERE子句(原sessionid=sessionid是恒真条件,会错误更新所有冲突行,需用EXCLUDED指代待插入的行):
ses_crud_sql = """INSERT INTO session_crud(orgid, appid, sessionid, userid, customlabel, uploadedon) VALUES (%s, %s, %s, %s, %s, %s) ON CONFLICT (orgid, appid) DO UPDATE SET customlabel = array_append(session_crud.customlabel, %s) WHERE session_crud.sessionid = EXCLUDED.sessionid """
步骤2:补充参数到每行数据
在ses_crud_rows的每个元组末尾添加label_name参数,确保参数数量与SQL中的%s数量一致:
ses_crud_rows = [ (org_id, app_id, sessionid, userid, [label_name], datetime.strftime(current_time, '%Y-%m-%d %H:%M:%S'), label_name) for sessionid in session_ids ] cursor.executemany(ses_crud_sql, ses_crud_rows)
额外注意事项
- 如果
customlabel是PostgreSQL的数组类型,直接传入Python列表(如[label_name])即可,无需转成字符串(原代码中的str({label_name})会把值转成字符串,导致后续array_append操作出错)。 EXCLUDED是PostgreSQL在ON CONFLICT子句中提供的特殊表,用于访问当前待插入但冲突的行数据,确保只更新与当前插入行sessionid匹配的记录。
可选方案(使用命名参数)
如果更习惯命名参数的可读性,可统一改用命名参数格式:
ses_crud_sql = """INSERT INTO session_crud(orgid, appid, sessionid, userid, customlabel, uploadedon) VALUES (%(orgid)s, %(appid)s, %(sessionid)s, %(userid)s, %(customlabel)s, %(uploadedon)s) ON CONFLICT (orgid, appid) DO UPDATE SET customlabel = array_append(session_crud.customlabel, %(label_name)s) WHERE session_crud.sessionid = EXCLUDED.sessionid """ ses_crud_rows = [ { 'orgid': org_id, 'appid': app_id, 'sessionid': sessionid, 'userid': userid, 'customlabel': [label_name], 'uploadedon': datetime.strftime(current_time, '%Y-%m-%d %H:%M:%S'), 'label_name': label_name } for sessionid in session_ids ] cursor.executemany(ses_crud_sql, ses_crud_rows)
内容的提问来源于stack exchange,提问作者Azima
相关产品推荐
相关产品推荐

