You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

psycopg2 execute_values在Supabase中处理超100行数据异常求助

问题分析与解决思路

核心原因推测

你的问题和psycopg2.extras.execute_values的默认行为直接相关:这个函数默认按每100条数据拆分一个批次执行SQL。当数据量超过100时,会自动分成多个批次处理,而你提前用mogrify结合AsIs构造SQL的方式,和execute_values的批量逻辑冲突,导致后续批次的语句出现异常,进而产生将csm_id设为NULL的错误插入。

具体问题点

你通过mogrify把VALUES %s替换成了AsIs("%s"),但execute_values本身会自动生成VALUES (...), (...), ...的批量格式。当拆分批次时,后续批次的SQL语句会因为提前的占位符替换,出现字段引用错误(比如EXCLUDED关键字的解析异常),最终导致部分字段被错误地设为NULL。

修正方案

1. 重构SQL语句构造逻辑

不要用mogrify提前处理整个SQL,改用psycopg2.sql模块安全地构造动态表名和字段,让execute_values负责处理批量VALUES部分:

from psycopg2 import sql
from psycopg2.extras import execute_values

# 安全构造动态SQL,避免SQL注入
statement = sql.SQL('''
    INSERT INTO {} ({}) VALUES %s 
    ON CONFLICT (company_id, crm_id)
    DO UPDATE SET {} = {} 
    RETURNING crm_id, id
''').format(
    sql.Identifier(db_table),  # 动态表名
    sql.SQL(',').join(map(sql.Identifier, keys)),  # 插入字段列表
    sql.SQL(',').join(map(sql.Identifier, update_keys)),  # 更新字段列表
    sql.SQL(',').join(
        map(lambda k: sql.SQL('EXCLUDED.{}').format(sql.Identifier(k)), update_keys)
    )  # 引用EXCLUDED的字段
)

# 直接执行,无需提前mogrify
output = execute_values(cur, statement, args, fetch=True)

2. 验证批次处理行为(可选)

如果想临时验证批次拆分的影响,可以强制execute_values用单个批次执行所有数据:

output = execute_values(cur, statement, args, batch_size=len(args), fetch=True)

如果这样操作后问题消失,就完全确认是批次拆分时的语句构造冲突导致的。

3. 排查字段引用正确性

检查你的update_keys是否包含csm_id,如果包含,确保在DO UPDATE部分正确引用了EXCLUDED.csm_id——之前的excluded_keys如果是手动拼接的字符串,可能在批次拆分时出现解析错误,导致该字段没有被正确赋值,最终被设为NULL。

辅助调试建议

查看Postgres的详细错误日志,找到异常批次对应的SQL语句,对比正常批次和异常批次的语句差异,能更直接地定位语法或字段引用的问题。


内容的提问来源于stack exchange,提问作者gkv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 18:40:45