我试图通过执行 sqlalchemy
来反映一个表:
PilotCycle = Table('PilotCycle', pr_meta, schema='dbo', autoload=True, autoload_with=pr_engine)
但是,我收到错误消息: "ArgumentError: ForeignKeyConstraint with duplicate source column references are not supported."
我想我通过检查表的外键找出导致这种情况的原因。
from sqlalchemy import inspect
insp = inspect(pr_engine)
fks = insp.get_foreign_keys('PilotCycle')
print(fks)
这将返回一个dicts列表,其中每个元素都是外键约束。我找到了一个外键'FK_PilotCycle_Equipment'
,它有重复的约束列(EquipmentID
)和重复的引用列(ID
)。这是我所指的列表中的字典:
{
'name': 'FK_PilotCycle_Equipment',
'constrained_columns': ['EquipmentID', 'EquipmentID'],
'referred_schema': None,
'referred_table': 'Equipment',
'referred_columns': ['ID', 'ID']
}
我只读取了对数据库的访问权限。我怎样才能解决这个问题?
答案 0 :(得分:0)
我花了整整一天时间解决同一问题,并且至少追踪了它的来源,如果没有解决的话。
此错误是由同一数据库中的两个名称相同的PRIMARY KEY引起的-即使外键位于彼此无关的架构和表中。
根本问题是在dialects/mssql/base.py
中编写数据库检查查询的方式:
```SELECT [C].[COLUMN_NAME],
[R].[TABLE_SCHEMA],
[R].[TABLE_NAME],
[R].[COLUMN_NAME],
[INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[CONSTRAINT_NAME],
[INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[MATCH_OPTION],
[INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[UPDATE_RULE],
[INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[DELETE_RULE]
FROM [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] AS [C], [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] AS [R], [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS]
WHERE [C].[TABLE_NAME] = CAST('MYTABLE' AS NVARCHAR(max)) AND [C].[TABLE_SCHEMA] = CAST('MYSCHEMA' AS NVARCHAR(max)) AND [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[CONSTRAINT_SCHEMA] = [C].[TABLE_SCHEMA] AND [C].[CONSTRAINT_NAME] = [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[CONSTRAINT_NAME] AND [R].[CONSTRAINT_NAME] = [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[UNIQUE_CONSTRAINT_NAME] AND [C].[ORDINAL_POSITION] = [R].[ORDINAL_POSITION] ORDER BY [INFORMATION_SCHEMA].[REFERENTIAL_CONSTRAINTS].[CONSTRAINT_NAME], [R].[ORDINAL_POSITION]``
如果将MYTABLE
和MYSCHEMA
替换为数据库中有问题的表,则应该看到返回的行具有相同的约束名称,但来自完全不同的表。
以下查询将在数据库中找到所有冲突的主键名称:
select CONSTRAINT_NAME, count(*)
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where CONSTRAINT_TYPE = 'PRIMARY KEY'
group by CONSTRAINT_NAME
having count(*) > 1
不幸的是,如果您无权更改DB DDL,那么我认为没有简单的解决方案。
我同时提交了问题和PR,并修复了SQLAlchemy错误:
如果您处于绑定状态,尽管我自己没有尝试过,但您可能可以使用我的PR和猴子补丁SQLAlchemy。