psycopg2执行含datetime对象的SQL时报offset附近语法错误如何修复
错误原因
- 语法错误根因:你通过
str.format()拼接SQL时,直接把Pythondatetime对象的官方字符串表示(包含tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=330...)这类Python专属语法)塞进了SQL,PostgreSQL完全不识别该格式,直接触发语法报错。 - 事务报错根因:第一条UPDATE执行失败后,当前数据库连接的事务就进入了中止状态,你没有做异常回滚就直接执行第二个UPDATE,PostgreSQL会直接拒绝执行,抛出
InFailedSqlTransaction错误。
修复方案
使用psycopg2官方推荐的参数绑定机制传递参数,不要手动拼接SQL字符串,psycopg2会自动完成Python类型到PostgreSQL类型的转换,同时避免SQL注入风险,修改后代码如下:
def invalidate_values(): try: for k, v in SYSTEMS.items(): timestamps = tuple(v[0]['timestamps']) # 用%s作为占位符,不要手动拼接参数 query = '''UPDATE consumers SET is_valid = False WHERE system_id = %s AND time IN %s;''' # 参数通过execute的第二个参数按顺序传入,IN子句直接传元组即可被自动适配 CURSOR.execute(query, (k, timestamps)) CONNECTION.commit() return 1 except Exception as e: # 执行出错就回滚事务,避免影响后续数据库操作 CONNECTION.rollback() raise e def validate_values(): try: query = "UPDATE consumers SET is_valid = True WHERE created_at >= %s;" # 单个参数也要写成元组格式,末尾加逗号避免被拆分为单个字符 CURSOR.execute(query, (LAST_UNVALIDATED,)) CONNECTION.commit() return 1 except Exception as e: CONNECTION.rollback() raise e
如果你的数据库
time字段是不带时区的timestamp类型,可以先把Python的datetime对象转换为对应时区的 naive datetime 再传参,或者将字段类型修改为timestamptz和数据对齐。
内容的提问来源于stack exchange,提问作者Cool Breeze
相关产品推荐
相关产品推荐

