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

使用cursor().execute()向PostgreSQL添加外键无效果(无报错无结果)

问题描述

尝试通过Python代码为PostgreSQL数据库中的表添加外键约束,执行代码后无报错但没有任何效果。将打印出的sql_text复制到pgAdmin的查询工具中执行,却能成功添加关联关系。

手动添加成功后,再次运行Python代码会提示以下错误:

DuplicateObject: constraint "R__t_PL_Re__t_001_P" for relation "t_PL_Res_UP" already exists

这说明数据库连接是有效的,但不清楚操作哪里出了问题。

附上使用的Python代码:

import psycopg2

pgr_cnn = psycopg2.connect( database =  "***",
                            user =      "***",
                            password =  "***",
                            host =      "***",
                            port =      "***")

sql_text =  """ALTER TABLE IF EXISTS public."t_PL_Res_UP"
    ADD CONSTRAINT "R__t_PL_Re__t_001_P" FOREIGN KEY ("up_pr_Code")
    REFERENCES public."t_001_Projects" ("p_Code") MATCH SIMPLE
    ON UPDATE CASCADE
    ON DELETE RESTRICT;"""

print( sql_text)

pgr_cnn.cursor().execute( sql_text)
pgr_cnn.close()
问题原因与解决办法
  • 核心问题:psycopg2默认会开启事务,执行execute()后如果没有手动提交事务,所有修改都会在连接关闭时自动回滚,所以看起来代码执行后没有效果。而pgAdmin执行SQL时会自动提交事务,因此能成功添加约束。
  • 解决办法:
    1. 执行SQL后手动提交事务:
      修改代码,在execute()之后添加commit(),并规范游标使用:
      import psycopg2
      
      pgr_cnn = psycopg2.connect( database =  "***",
                                  user =      "***",
                                  password =  "***",
                                  host =      "***",
                                  port =      "***")
      
      sql_text =  """ALTER TABLE IF EXISTS public."t_PL_Res_UP"
          ADD CONSTRAINT "R__t_PL_Re__t_001_P" FOREIGN KEY ("up_pr_Code")
          REFERENCES public."t_001_Projects" ("p_Code") MATCH SIMPLE
          ON UPDATE CASCADE
          ON DELETE RESTRICT;"""
      
      print(sql_text)
      
      cursor = pgr_cnn.cursor()
      cursor.execute(sql_text)
      pgr_cnn.commit()  # 提交事务
      cursor.close()
      pgr_cnn.close()
      
    2. 开启自动提交:
      在创建数据库连接时设置autocommit=True,让每个SQL执行后自动提交:
      pgr_cnn = psycopg2.connect(
          database="***",
          user="***",
          password="***",
          host="***",
          port="***",
          autocommit=True
      )
      
  • 额外优化:原SQL中的ALTER TABLE IF EXISTS仅判断表是否存在,不判断约束是否存在。如果想避免重复添加时的报错,可以修改SQL为:
    ALTER TABLE IF EXISTS public."t_PL_Res_UP"
    ADD CONSTRAINT IF NOT EXISTS "R__t_PL_Re__t_001_P" FOREIGN KEY ("up_pr_Code")
    REFERENCES public."t_001_Projects" ("p_Code") MATCH SIMPLE
    ON UPDATE CASCADE
    ON DELETE RESTRICT;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:50:47