我有大约100个表,其中所有表都有重复的外键约束。
有没有办法可以摆脱它?是否有查询可以为我提供所有重复的密钥?
答案 0 :(得分:12)
我在这里使用这个T-SQL脚本来检测可能重复的FK约束 - 它还在最后一个输出列中生成必要的ALTER TABLE...DROP CONSTRAINT
语句。
您无法可靠地自动检测并选择要删除的多个FK约束中的哪一个 - 因此您基本上可以检测它们,然后手动选择要丢弃的那些(使用我的查询生成的drop语句)。
;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
答案 1 :(得分:2)
对于100个表,它不是一个选项,但是如果您只有几个表,请在SQL Server Management Studio中创建一个图表,在那里添加表并直观地删除这些表。
答案 2 :(得分:1)
这将删除最近创建的重复项
;WITH fkeys AS (
SELECT f.object_id ,
f.name ,
f.parent_object_id,
ROW_NUMBER() OVER(PARTITION BY t.column_names ORDER BY f.create_date,f.[object_id]) AS RowNum
FROM sys.foreign_keys f
CROSS APPLY ( SELECT fc.parent_object_id,parent_column_id,fc.referenced_object_id ,fc.referenced_column_id
FROM sys.foreign_key_columns fc
WHERE fc.constraint_object_id = f.object_id
ORDER BY constraint_column_id
FOR XML PATH('')
) t ( column_names )
)
SELECT 'ALTER TABLE '+QUOTENAME(OBJECT_SCHEMA_NAME(f.parent_object_id)) + '.'+QUOTENAME(OBJECT_NAME(f.parent_object_id)) +' DROP CONSTRAINT '+QUOTENAME(f.name)+';' AS DropStatement
FROM fkeys f
WHERE f.RowNum >= 2