Я использую этот сценарий T-SQL здесь для обнаружения потенциально дублирующих ограничений FK - и он также создает необходимые операторы ALTER TABLE...DROP CONSTRAINT
в последнем столбце вывода.
Вы не можете надежно автоматически обнаруживать ивыберите, какое из нескольких ограничений FK отбрасывать - так что вы в основном должны их обнаружить, а затем вручную выбрать, какие из них отбрасывать (используя оператор сброса, созданный моим запросом).
;WITH FKData AS
(
SELECT
fk.parent_object_id,
fkc.parent_column_id,
fk.referenced_object_id,
fkc.referenced_column_id,
FKCount = COUNT(*)
FROM
sys.foreign_keys fk
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
GROUP BY
fk.parent_object_id, fkc.parent_column_id, fk.referenced_object_id, fkc.referenced_column_id
HAVING
COUNT(*) > 1
),
DuplicateFK AS
(
SELECT
FKName = fk.Name,
ParentSchema = s1.Name,
ParentTable = t1.Name,
ParentColumn = c1.Name,
ReferencedTable = t2.Name,
ReferencedColumn = c2.Name
FROM
sys.foreign_keys fk
INNER JOIN
sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
INNER JOIN
FKData f ON fk.parent_object_id = f.parent_object_id
AND fk.referenced_object_id = f.referenced_object_id
AND fkc.parent_column_id = f.parent_column_id
AND fkc.referenced_column_id = f.referenced_column_id
INNER JOIN
sys.tables t1 ON f.parent_object_id = t1.object_id
INNER JOIN
sys.columns c1 ON f.parent_object_id = c1.object_id AND f.parent_column_id = c1.column_id
INNER JOIN
sys.schemas s1 ON t1.schema_id = s1.schema_id
INNER JOIN
sys.tables t2 ON f.referenced_object_id = t2.object_id
INNER JOIN
sys.columns c2 ON f.referenced_object_id = c2.object_id AND f.referenced_column_id = c2.column_id
)
SELECT
FKName,
ParentSchema, ParentTable, ParentColumn,
ReferencedTable, ReferencedColumn,
DropStmt = 'ALTER TABLE ' + ParentSchema + '.' + ParentTable +
' DROP CONSTRAINT ' + FKName
FROM
DuplicateFK