使用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时会自动提交事务,因此能成功添加约束。 - 解决办法:
- 执行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() - 开启自动提交:
在创建数据库连接时设置autocommit=True,让每个SQL执行后自动提交:pgr_cnn = psycopg2.connect( database="***", user="***", password="***", host="***", port="***", autocommit=True )
- 执行SQL后手动提交事务:
- 额外优化:原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
相关产品推荐
相关产品推荐

