psycopg2调用executemany插入PostgreSQL数据报string index out of range错误
问题根因
- 直接原因:
executemany方法的第二个参数要求传入由每行参数组成的序列(列表/元组,每个元素对应一行的参数组),你当前传入的entity_list是从文本文件读取的完整字符串,psycopg2遍历字符串时会把单个字符当成参数行,参数数量不匹配就抛出字符串索引越界错误。 - 逻辑问题:中间新增的文本文件中转步骤完全多余,手动拼接SQL值字符串的行为不仅容易出错,还存在SQL注入风险,不符合psycopg2的参数绑定规范。
修复方案
- 删掉冗余的文本文件中转逻辑,读取Excel时直接生成参数列表,每个元素是
(ENTITY_ID值, SECT_CD值)的元组,不需要手动加引号、拼接SQL结构。 - 调用
executemany时直接传入这个参数列表即可。
修正后代码
import pandas as pd import psycopg2 def get_insert_params(excel_file, sheet_index, row_for_header): df = pd.read_excel(excel_file, sheet_name=sheet_index, header=None) new_header = df.iloc[row_for_header] df = df[row_for_header+1:] df.columns = new_header rows_to_insert = [] for _, row in df.iterrows(): entity_id = row['ENTITY_ID'] sect_cd = row['SECT_CD'] # 跳过ENTITY_ID为空的行 if pd.isnull(entity_id): continue # 直接存参数元组,不需要拼接字符串 rows_to_insert.append((str(entity_id), str(sect_cd))) return rows_to_insert def insert_entity_list(params_list): sql = """ INSERT into esg.entity(entity_id,sector_key,creat_by,creat_dtm,last_upd_by,last_upd_dtm) VALUES(%s,(select sector_key from esg.sector where sector_cd=%s),current_user,now() at time zone 'utc',current_user,now() at time zone 'utc') """ conn = None try: conn = psycopg2.connect(host="localhost",database="abc",user="abcde",password="abcdefg") cur = conn.cursor() # 传入参数列表,每个元素对应一行的两个占位符参数 cur.executemany(sql, params_list) conn.commit() cur.close() except (Exception, psycopg2.DatabaseError) as error: print(error) if conn: conn.rollback() finally: if conn is not None: conn.close() if __name__ == "__main__": insert_params = get_insert_params('EntityTableImportTest.xlsx', 0, 0) insert_entity_list(insert_params)
额外注意事项
- psycopg2的参数绑定会自动处理数据类型转换、特殊字符转义,不需要手动给值加引号。
- 新增了异常时的事务回滚逻辑,避免出错后数据库连接残留未提交的无效事务。
内容的提问来源于stack exchange,提问作者Kavya
相关产品推荐
相关产品推荐

