2012-03-23 43 views
8

Tôi có khoảng 100 bảng trong đó tất cả các khóa đó đều có các ràng buộc khoá ngoại bản trùng lặp trên chúng.thả các khóa nước ngoài trùng lặp

Có cách nào để tôi có thể loại bỏ nó không? Có một truy vấn có thể cho tôi tất cả các khóa trùng lặp trong đó không?

Trả lời

10

Tôi đang sử dụng tập lệnh T-SQL này ở đây để phát hiện các ràng buộc FK có thể trùng lặp - và nó cũng tạo ra các câu lệnh ALTER TABLE...DROP CONSTRAINT cần thiết ở cột cuối cùng của các cột đầu ra.

Bạn không thể tự động phát hiện và chọn nhiều hạn chế FK để thả - vì vậy bạn về cơ bản còn lại để phát hiện chúng và sau đó chọn thủ công để thả xuống (sử dụng câu lệnh thả do truy vấn của tôi tạo).

;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

Tuyệt vời cảm ơn !! – peter

+0

có cách nào để chúng tôi có thể lấy tên lược đồ không? vì có rất ít không thuộc về lược đồ dbo. – peter

+1

@Peter: ** SURE! ** đã cập nhật phản hồi của tôi để bao gồm lược đồ gốc (bạn cũng có thể nhận giản đồ tham chiếu nếu cần - nhưng bạn không cần nó cho câu lệnh DROP) –

2

Đối với 100 bảng không phải là một tùy chọn, nhưng nếu bạn chỉ có một vài bảng, hãy tạo sơ đồ trong SQL Server Management Studio, thêm bảng của bạn và xóa trực quan.

0

này loại bỏ các bản sao gần đây nhất là tạo

;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 
Các vấn đề liên quan