2010-02-25 6 views
2

Cela va sonner comme une requête folle. Les bases de données dont je fais état n'ont pas de clés étrangères et chaque clé primaire est une colonne identity_column. Cela rend difficile l'utilisation d'outils tels que TOAD car l'Intellisense fonctionne en lisant les relations PK et FK. Quelqu'un at-il un script pour supprimer les clés primaires de chaque table dans la base de données afin que je puisse les remplacer par PK "correct" et ajouter FK pour aider à signaler?Suppression de toutes les clés primaires

Pour éviter l'avalanche de "Ne le fais pas !!!" réponses, laissez-moi préciser que je ne vais pas le faire à ma base de données de production, mais copie sur un autre serveur.

Tout conseil serait apprécié.

------- EDIT Ceci est mis à jour avec des informations correctes. ----------------

Merci les gars, mais j'ai réalisé que j'ai fait une erreur. Presque chaque table a une "identity_column" avec la propriété de l'identité. Cette identité est un index clusterisé. Cependant, il n'est pas désigné comme une clé primaire.

Premièrement, quelle est la différence entre une clé primaire et un index clusterisé? Deuxièmement, comment puis-je créer un script sur tous les index clusterisés? Est-ce que cela fonctionnerait?

SELECT 
    'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name 
FROM sys.indexes WHERE type_desc = 'CLUSTERED' 

Merci de patienter

+0

Pourquoi voudriez-vous supprimer des index clusterisés? Cela causerait une réécriture totale de chaque rangée! – TFD

+0

Mon problème est le suivant. Ma base de données n'a pas de clés primaires, seulement des index clusterisés. J'écris un script pour prendre une copie de rapport de la base de données et y mettre des relations PK et FK appropriées pour faciliter la création de rapports par TOAD et SSRS. Étant donné que cela se produirait pendant les temps d'arrêt, et je vais l'effectuer sur un petit sous-ensemble des tableaux, je ne pense pas que la pénalité liée à la performance soit importante. – DavidStein

Répondre

4

Que diriez-vous quelque chose comme this?

[Untested]

-- Helper Procedure 
CREATE PROC#DropConstraints 
    @tableSchema nvarchar(max), 
    @tableName nvarchar(max), 
    @constraintType nvarchar(20) 
AS 
BEGIN 
    DECLARE @cName nvarchar(max); 

    DECLARE constraint_cursor CURSOR FOR 
    SELECT CONSTRAINT_NAME 
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
    WHERE 
     CONSTRAINT_TYPE = @constraintType 
     AND TABLE_NAME = @tableName 
     AND TABLE_SCHEMA = @tableSchema 

    OPEN constraint_cursor 

    FETCH NEXT FROM constraint_cursor INTO @cName 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    EXEC ('ALTER TABLE ' + @tableSchema + '.' + @tableName + ' DROP CONSTRAINT ' + @cName); 
    FETCH NEXT FROM constraint_cursor INTO @cName 
    END 

    CLOSE constraint_cursor 
    DEALLOCATE constraint_cursor 
END 
GO 

BEGIN TRANSACTION 

    -- Setup Cursor for looping 
    DECLARE table_cursor SCROLL CURSOR FOR 
    SELECT TABLE_SCHEMA, TABLE_NAME 
    FROM INFORMATION_SCHEMA.TABLES 

    OPEN table_cursor 

-- Drop Primary Keys 
    FETCH FIRST FROM table_cursor INTO @tableSchema, @tableName 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    EXEC#DropConstraints @tableSchema, @tableName, 'PRIMARY KEY'; 

    FETCH NEXT FROM table_cursor INTO @tableSchema, @tableName 
    END 

    -- Cleanup 
    CLOSE table_cursor 
    DEALLOCATE table_cursor 

COMMIT TRANSACTION 
GO 

DROP PROCEDURE #DropConstraints; 
GO 
3

Une autre option serait un processus en deux étapes:

  1. d'abord, sélectionnez les informations nécessaires à partir des vues du catalogue système, et les utiliser pour construire le T Les instructions SQL dont vous aurez besoin pour supprimer les indices et les contraintes:

    SELECT 
        'ALTER TABLE ' + OBJECT_NAME(OBJECT_ID) + ' DROP CONSTRAINT ' + name 
    FROM sys.indexes WHERE is_primary_key = 1 
    
  2. utiliser ce résultat définir, copier & coller dans une nouvelle fenêtre de requête et exécutez-le - il baissera toutes les contraintes de clé primaire de toutes vos tables dans la base de données que vous exécutez ce dans

De cette façon, vous » re éviter le curseur, et vous obtenez une liste d'instructions à exécuter, que vous pouvez toujours utiliser "tel quel", modifier, ou même jeter complètement, si vous n'en avez pas besoin.

+0

Cela fonctionne, mais j'ai réalisé que j'ai fait une erreur. Je vais expliquer ci-dessus. – DavidStein

+0

Cela fonctionnerait-il? SELECT 'ALTER TABLE' + OBJECT_NAME (OBJECT_ID) + 'DROP CONSTRAINT' + nom DE sys.indexes OU type_desc = 'CLUSTERED' – DavidStein

+0

oui, mais cela vous donne les indices ** ** - les clusters ne sont pas nécessairement identique à la ** clé primaire ** sur la table. Mais si c'est ce que vous recherchez, en supprimant tous les index clusterisés, alors oui, cela va créer la liste des instructions ALTER TABLE –

1

Pour répondre à votre question sur le differnce betweeen un PK et un index ordonné en clusters:

Les clés primaires sont les valeurs clés qui garantissent l'enregistrement peut être identifié de manière unique. Ils n'ont rien à voir avec les index clusterisés (qui dictent l'ordre dans lequel les enregistrements sont physiquement stockés), sauf que la valeur par défaut pour la création d'une clé primaire est d'en faire un index clusterisé. Vous n'avez cependant pas à en faire un index clusterisé.Sachez que si vous n'avez pas eu de clés primaires et de clés étrangères dans le passé, vos données peuvent être complètement arrosées et vous ne devez pas créer les clés étrangères tant que vous ne les avez pas nettoyées.

1

Pour supprimer tous les index clusterisés, vous devez différencier les situations dans lesquelles une contrainte (Primaire ou Unique) est l'index cluster ou si un index sans contrainte est l'index clusterisé. Vous ne pouvez pas supprimer d'index de contrainte à l'aide de DROP INDEX et vous ne pouvez pas supprimer d'index à l'aide de DROP CONSTRAINT. Donc, vous devez faire quelque chose comme:

Select 'ALTER TABLE ' + QUOTENAME(OBJECT_NAME([object_id])) + ' DROP CONSTRAINT ' + QUOTENAME([name]) 
From sys.indexes 
Where is_primary_key = 1 Or is_unique_constraint = 1 
And type_desc = 'CLUSTERED' 
Union All 
Select 'DROP INDEX ' + QUOTENAME([name]) + ' ON ' + QUOTENAME(OBJECT_NAME([object_id])) 
from sys.indexes 
Where is_primary_key = 0 And is_unique_constraint = 0 
And type_desc = 'CLUSTERED' 

Franchement, même cela ne fonctionnera probablement pas parce que toutes les clés étrangères à toutes les clés primaires devront être déposés avant de pouvoir déposer la clé primaire. Pour le faire correctement, vous voudrez écrire toutes les clés étrangères, les supprimer toutes, puis supprimer toutes les contraintes en cluster et ensuite recréer toutes les clés étrangères.

Je dois demander si c'est vraiment ce que vous voulez faire. En supprimant tous les index clusterisés, vous forcez une reconstruction de tous les index dans toutes les tables affectées.

0

Les exemples de code fournis avant moi fonctionnent, à la fois la version de clé primaire uniquement et celle qui prend également en charge d'autres types d'index clusterisés. Cependant, aucun ne prend soin du fait que les objets peuvent ne pas exister dans le schéma par défaut, ni ne contrôle que les index et les contraintes ne sont pas un objet système dont SQL Server a besoin.

c'est la version simple, seule la suppression des clés primaires:

select 'ALTER TABLE ' + quotename(object_schema_name(object_id)) + '.' 
     + quotename(object_name(object_id)) + ' DROP CONSTRAINT ' + name 
from sys.indexes 
where is_primary_key = 1 

ici est la deuxième version, qui a également le script la suppression des clés non primaires index cluster:

select 'ALTER TABLE ' + quotename(object_schema_name(object_id)) + '.' 
     + quotename(object_name([object_id])) + ' DROP CONSTRAINT ' 
     + quotename([name]) 
from sys.indexes 
where is_primary_key = 1 
     or is_unique_constraint = 1 
     and type_desc = 'CLUSTERED' 
union all 
select 'DROP INDEX ' + quotename(i.[name]) + ' ON ' 
     + quotename(object_schema_name(i.[object_id])) + '.' 
     + +quotename(object_name(i.[object_id])) 
from sys.indexes as i 
     inner join sys.objects as o on o.object_id = i.object_id 
where is_primary_key = 0 
     and is_unique_constraint = 0 
     and i.type_desc = 'CLUSTERED' 
     and o.[type] not in ('S') 
     and o.is_ms_shipped = 0 
Questions connexes