Ho circa 100 tabelle in cui tutte hanno vincoli di chiave esterna duplicati su di esse.eliminazione di chiavi esterne duplicate
C'è un modo per liberarmene? C'è una query che potrebbe darmi tutte le chiavi duplicate in esso?
Ho circa 100 tabelle in cui tutte hanno vincoli di chiave esterna duplicati su di esse.eliminazione di chiavi esterne duplicate
C'è un modo per liberarmene? C'è una query che potrebbe darmi tutte le chiavi duplicate in esso?
Qui sto utilizzando questo script T-SQL per rilevare i vincoli FK potenzialmente duplicati e inoltre produce le necessarie istruzioni ALTER TABLE...DROP CONSTRAINT
nell'ultima colonna di output.
Non è possibile rilevare e scegliere in modo affidabile quale dei vincoli FK multipli da rilasciare, quindi in pratica non è possibile individuarli e quindi selezionare manualmente quelli da eliminare (utilizzando l'istruzione drop prodotta dalla query).
;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
Per un 100 tavoli non è un'opzione, ma se si dispone di pochi tavoli, creare un diagramma in SQL Server Management Studio, aggiungere le tabelle lì ed eliminare i doppioni visivamente.
Ciò elimina la più recente creato duplicati
;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
eccellente GRAZIE !! – peter
c'è un modo per ottenere anche il nome dello schema? poiché ce ne sono pochi che non appartengono a Dbo Scheme. ! – peter
@Peter: ** ** SICURO aggiornato la mia risposta per includere lo schema genitore (si potrebbe ottenere lo schema di riferimento, anche, se necessario - ma non è necessario che per l'istruzione DROP) –