En testant certains scripts de migration avec une copie des données de production (les scripts fonctionnent bien avec les données de développement), j'ai trouvé une situation curieuse. UNE CONTRAINTE a changé, donc j'émets des commandes DROP + ADD:
ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT A_DUP_CALLE_UK1;
ALTER TABLE A_DUP_CALLE
ADD CONSTRAINT A_DUP_CALLE_UK1 UNIQUE (
CONTROL_ID,
CALLE_AYTO_DUPL
)
ENABLE;
La commande DROP a bien fonctionné mais celle ADD a échoué. Maintenant, je suis dans un cercle vicieux. Je ne peux pas supprimer la contrainte car elle n'existe pas (la suppression initiale a fonctionné comme prévu):
ORA-02443: Impossible de supprimer la contrainte - contrainte inexistante
Et je ne peux pas le créer car le nom existe déjà:
ORA-00955: le nom est déjà utilisé par un objet existant
J'écris A_DUP_CALLE_UK1
dans la boîte de recherche du développeur SQL et ... la voici! Propriétaire, nom de table, tablescape ... tout concorde: ce n'est pas un objet différent avec le même nom, c'est est ma contrainte d'origine. Le tableau apparaît dans les détails de la contrainte mais la contrainte n'apparaît pas dans les détails du tableau.
Mes questions:
(Le serveur est 10g XE, je n'ai pas assez de réputation pour créer la balise.)
Je suppose que Marian a raison et cela est dû à un index et à une contrainte uniques ayant le même nom, par exemple:
create table t( k1 integer, k2 integer,
constraint u1 unique(k1,k2) using index(create unique index u1 on t(k1,k2)),
constraint u2 unique(k2,k1) using index u1);
select count(*) from user_indexes where index_name='U1';
COUNT(*)
----------------------
1
alter table t drop constraint u1;
select count(*) from user_indexes where index_name='U1';
COUNT(*)
----------------------
1
Normalement, lorsque vous ajoutez une contrainte unique, un index unique portant le même nom est créé, mais l'index et la contrainte ne sont pas la même chose. Jettes un coup d'oeil à all_indexes
pour voir s'il existe un index appelé A_DUP_CALLE_UK1
et essayez de découvrir s'il est utilisé par autre chose avant de le déposer!
Semble très étrange.
Tu peux courir:
SELECT *
FROM user_objects
WHERE object_name = 'A_DUP_CALLE_UK1'
pour vérifier de quel type d’objet se plaint Oracle. Ensuite, vous pouvez exécuter l'instruction DROP appropriée pour cela.
La seule autre chose à laquelle je peux penser est de supprimer complètement la table en utilisant DROP TABLE A_DUP_CALLE CASCADE CONSTRAINTS
pour se débarrasser de tout ce qui appartient à cette table, puis la recréer complètement.
Si le tableau contient des données de valeur, vous pouvez en faire une sauvegarde avant:
CREATE TABLE old_data
AS
SELECT *
FROM A_DUP_CALLE;
Une fois que vous avez recréé la table, vous pouvez faire
INSERT INTO A_DUP_CALLE (col1, col2, col3)
SELECT col1, col2, col3
FROM old_data
pour restaurer les données.
J'ai eu le même problème il y a quelques minutes à peine ... et j'ai trouvé une explication.
En créant une clé primaire, Oracle crée deux objets: une contrainte et un index qui contrôlent la partie "UNIQUE".
En supprimant la contrainte, l'index reste là, en utilisant le même nom de l'index, donc si vous exécutez juste
alter table t drop constraint u1;
Vous ne supprimerez que la contrainte. Pour supprimer l'index, vous devrez exécuter
drop index u1;
Cela devrait faire le travail. Alternativement, vous pouvez exécuter ces deux commandes en même temps avec la commande
alter table t drop constraint u1 including indexes;
La contrainte de clé primaire est fournie avec l'index. Vous supprimez la contrainte mais pas l'index. Vérifier:
select * from ALL_OBJECTS where OBJECT_NAME = 'PK_TBL_CONSTR';
et vous voyez OBJECT_TYPE
est INDEX
.
Faites les deux:
alter table TBL drop constraint PK_TBL_CONSTR;
drop index PK_TBL_CONSTR;
Faites ceci
ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT "A_DUP_CALLE_UK1";
Ça va marcher.
IMAGE: