2012-03-23 54 views
8

我有大約100臺,其中所有的人都對他們的重複的外鍵約束。撤消重複的外鍵

有沒有,我可以擺脫它的方法嗎?有沒有可以給我所有重複密鑰的查詢?

回答

10

我在這裏使用這個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 
+0

優秀謝謝!! – peter 2012-03-23 21:58:44

+0

有沒有辦法讓我們獲得模式名稱?因爲很少有不屬於dbo模式的。 ! – peter 2012-03-23 22:02:14

+1

@Peter:** ** SURE更新我的迴應包括父模式(你可以得到引用的模式,也如果需要的話 - 但你並不需要,對於DROP語句) – 2012-03-23 22:06:22

2

對於100的表,那麼是不是一種選擇,但如果你只有幾桌,請在SQL Server Management Studio中的示意圖,其中添加表那裏,視覺上刪除受騙者。

0

這將刪除最近創建的副本

;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