使用psycopg2向PostgreSQL表传入列表时触发异常,求排查方案
问题分析与解决方案
嘿,我来帮你捋捋这个问题~你遇到的异常大概率是手动拼接SQL时的语法错误导致的,加上没用到psycopg2推荐的参数化查询方式,咱们一步步来解决:
你的SQL语句里的明显问题
你打印出来的SQL有几个致命的语法错误:
- 日期、字符串没加单引号:PostgreSQL要求日期(比如
02/14/2018)、字符串类型的值(比如Wednesday、-0.10%)必须用单引号括起来。现在02/14/2018会被数据库当成2÷14÷2018的数值运算,-0.10%里的%会被识别为模运算符号,Wednesday会被当成未定义的标识符,这些都会直接触发语法异常。 - 直接拼接SQL的风险:把列表值硬拼进SQL不仅容易出错,还存在SQL注入的安全隐患,这绝对不是推荐的做法。
正确的解决方式:用psycopg2参数化查询
psycopg2专门提供了参数化查询的语法,会自动帮你处理类型转换、引号添加这些细节,完全不用你手动拼接。
示例代码修改
假设你的pg.py里的insert_pg函数是负责执行插入的,改成下面这样:
# pg.py 中的 insert_pg 函数 def insert_pg(conn, data_list): # 用 %s 作为参数占位符,数量和你要插入的字段数一致 insert_sql = """INSERT INTO prices VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" with conn.cursor() as cur: # 第二个参数直接传入你的列表,psycopg2会自动处理每个值的类型 cur.execute(insert_sql, data_list) conn.commit()
额外优化:日期类型转换
如果你的列表里的日期是字符串格式(比如02/14/2018),可以先把它转换成Python的date对象,这样psycopg2能更准确地映射到PostgreSQL的date类型:
# 在 newsletter.py 中调用前处理日期 from datetime import datetime # 假设你的数据列表是 data,第一个元素是日期字符串 data[0] = datetime.strptime(data[0], "%m/%d/%Y").date() # 然后调用 insert_pg 传入处理后的列表 insert_pg(your_conn, data)
为什么原来的写法会报错?
再回头看你打印的SQL:
insert into prices values (02/14/2018, 2675, 12, 0, 24698, 0.23, 58, 7074, 0.86, 60, 59.09, -0.06, -0.10%, Wednesday);
数据库会把02/14/2018解析成一个小数,-0.10%会被当成-0.10 对某个值取模(但后面没有值,触发语法错误),Wednesday是未定义的变量,这些都会导致数据库抛出语法错误的异常。
用参数化查询之后,这些问题都会被psycopg2自动解决,你再也不用手动处理引号和类型的问题啦~
内容的提问来源于stack exchange,提问作者qorka
相关产品推荐
相关产品推荐

