сбросить дубликаты внешних ключей - PullRequest
8 голосов
/ 24 марта 2012

У меня есть около 100 таблиц, где все они имеют дублированные ограничения внешнего ключа.

Есть ли способ, которым я мог бы избавиться от этого?Есть ли запрос, который может дать мне все дубликаты ключей?

Ответы [ 3 ]

12 голосов
/ 24 марта 2012

Я использую этот сценарий 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
2 голосов
/ 24 марта 2012

Для 100 таблиц это не вариант, но если у вас всего несколько таблиц, создайте диаграмму в SQL Server Management Studio, добавьте туда свои таблицы и визуально удалите дубликаты.

1 голос
/ 21 февраля 2018

При этом удаляются самые последние созданные дубликаты

;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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...