Heroku下通过psycopg2导入CSV到Postgres表报integer语法无效错误求助
问题根因
两个核心问题叠加导致导入失败:
- 你使用的文件是空格分隔的纯文本,并非Postgres默认识别的逗号分隔CSV格式。原语句
FORMAT CSV默认以逗号作为字段分隔符,无法正确拆分每行内容,直接造成字段错位 - 当你删除CSV中的索引数字、仅保留level和word两列内容时,未在COPY语句中指定目标列,Postgres会强制按表结构的字段顺序(id → level → word)匹配CSV内容,将本该传入level列的字符串值直接传入integer类型的id列,触发类型语法报错
你看到的
invalid input syntax for type integer: "0"报错,本质就是字段拆分错位后,内容片段和列类型不匹配导致的解析错误。
可落地方案
根据你是否需要手动指定id列值,二选一调整代码即可:
方案1:保留CSV中的数字作为id列导入
调整COPY语句,显式指定分隔符、列映射关系,同时兼容Django自动生成的identity自增列的插入限制:
# 替换原有的sql_copy语句 sql_copy = """ COPY spellbeeword_tb(id, level, word) FROM stdin WITH ( FORMAT CSV, DELIMITER ' ', HEADER FALSE ) """ # 导入前临时放开自增列的手动插入限制 cur.execute("SET session_replication_role = replica;") cur.copy_expert(sql=sql_copy, file=f) # 导入完成后恢复默认配置 cur.execute("SET session_replication_role = default;")
方案2:使用数据库自动生成的自增id(推荐)
直接删掉CSV里的第一列数字,仅保留level、word两列内容,COPY语句显式指定只导入这两个业务字段:
sql_copy = """ COPY spellbeeword_tb(level, word) FROM stdin WITH ( FORMAT CSV, DELIMITER ' ', HEADER FALSE ) """ cur.copy_expert(sql=sql_copy, file=f)
注意:如果你的文件中字段间是连续多个空格分隔,建议先批量把连续空格替换为单个空格,避免Postgres解析出空字段导致导入错位。
代码细节优化建议
- 删除
finally块里的f.close()代码:你已经用with上下文管理器打开了文件,with块会自动处理文件关闭,手动在finally里关闭反而可能因为文件打开失败、f对象不存在触发NameError - 注意自增列的兼容性:Django 3.2+版本的AutoField默认使用
GENERATED ALWAYS AS IDENTITY规则,不允许手动插入id值,必须通过上述临时放开replication_role的方式才能正常导入带自定义id的数据
内容的提问来源于stack exchange,提问作者Mumtaz Begum C
相关产品推荐
相关产品推荐

