引用复合外键时触发sqlalchemy.exc.ProgrammingError异常
解决SQLAlchemy复合外键引用的ProgrammingError异常
我来帮你搞定这个问题!你现在的代码里犯了一个常见的复合外键定义错误,导致触发了数据库层面的异常。
问题根源
你在Test2的c和d字段上分别加了ForeignKey(Test1.a)和ForeignKey(Test1.b),这相当于给每个字段单独创建了外键约束,但Test1的主键是a和b的复合主键——单独的字段外键和你后面定义的ForeignKeyConstraint产生了冲突,数据库无法识别正确的约束规则,所以抛出了ProgrammingError。
修正后的代码
Test1的定义没问题,保持不变。重点修改Test2的外键定义,去掉单个字段的ForeignKey,只保留复合外键约束:
class Test1(Base): data = [ [1, 2], [3, 4], ] a = Column(Integer, primary_key=True) b = Column(Integer, primary_key=True) def __init__(self, a, b): self.a = a self.b = b class Test2(Base): data = [ [1, 1, 2], [2, 3, 4], ] id = Column(Integer, primary_key=True) # 去掉单个字段的ForeignKey,只定义字段类型 c = Column(Integer) d = Column(Integer) __table_args__ = ( ForeignKeyConstraint( ['c', 'd'], # 当前表的字段名(用字符串避免初始化顺序问题) ['test1.a', 'test1.b'], # 关联表的表名+字段名(默认表名是类名小写) ), {} ) def __init__(self, id, c, d): self.id = id self.c = c self.d = d
关键说明
- 复合外键必须用
ForeignKeyConstraint定义:因为复合主键的关联需要整体约束,单个字段的外键只能关联对方表的单个主键字段,而Test1的主键是a+b的组合,单独的外键约束逻辑不成立。 - 用字符串指定字段/表名更安全:直接使用字段对象(比如
c、Test1.a)可能会因为类初始化顺序问题导致报错,用字符串形式的表名和字段名能避免这个问题。 - 注意数据库表名:如果你的
Test1对应的数据库表名不是默认的test1(比如自定义了表名),要把['test1.a', 'test1.b']改成对应的表名字段名。
内容的提问来源于stack exchange,提问作者Clayton J Roberts
相关产品推荐
相关产品推荐

