Impossible de supprimer une contrainte inexistante et de la créer non plus


16

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

Je tape A_DUP_CALLE_UK1dans la boîte de recherche du développeur SQL et ... le voilà ! Propriétaire, nom de la table, tablescape ... tout matches: il n'est pas un objet différent avec le même nom, il 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:

  • Quelle en est l'explication?
  • Comment puis-je m'assurer que cela ne se produira pas lorsque je ferai la mise à niveau réelle sur le serveur en direct?

(Le serveur est 10g XE, je n'ai pas assez de réputation pour créer le tag.)


Peut-être qu'il a été créé comme un autre type d'objet et non comme une contrainte unique? Index peut-être unique ..
Marian

La création initiale aurait-elle pu être exécutée avec des guillemets autour du nom de la table? Cela rendrait le nom sensible à la casse. Si c'est le cas, vous pouvez déposer des guillemets et le même cas.
Adam Butler

Réponses:


13

Je suppose que Marian a raison et cela est dû à un index et à une contrainte uniques portant 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. Jetez un œil all_indexespour voir s'il existe un index appelé A_DUP_CALLE_UK1et essayez de déterminer s'il est utilisé par autre chose avant de le déposer!


C'était le problème. Le fichier de vidage généré par la expcommande contient une CREATE UNIQUE INDEX "A_DUP_CALLE_UK1" ...instruction qui n'est pas présente dans le jeu de scripts d'origine.
Álvaro González

6

Semble très étrange.

Tu peux courir:

 SELECT *
 FROM user_objects
 WHERE object_name = 'A_DUP_CALLE_UK1'

pour vérifier si 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 CONSTRAINTSpour se débarrasser de tout ce qui appartient à cette table, puis de 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.


4

J'ai eu le même problème il y a quelques minutes ... 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;

quel db? y compris ne fonctionne pas dans Oracle
Derick

1

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_TYPEest INDEX.

Faites les deux:

alter table TBL drop constraint PK_TBL_CONSTR;
drop index PK_TBL_CONSTR;

1

Faites ceci

ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT "A_DUP_CALLE_UK1";

Ça va marcher.

IMAGE: entrez la description de l'image ici


Non, il ne travaillera pas. Votre déclaration est exactement la même déclaration que la première déclaration de la question:ALTER TABLE A_DUP_CALLE DROP CONSTRAINT A_DUP_CALLE_UK1;
a_horse_with_no_name

Cela a fonctionné en fait. J'avais le même problème depuis midi aujourd'hui, et à la recherche de la solution, je suis tombé sur cela. Parfois, CONSTRAINTS peut avoir été créé en respectant la casse, auquel cas, vous devrez mettre le nom de la contrainte entre guillemets lorsque vous le supprimerez.
Sachin

Et ça a marché pour moi. Je n'avais pas nommé les contraintes explicitement, donc le système lui a donné son propre nom généré Relationship142et une autre NOT NULLcontrainte a été nommée SYS_C0015910. Donc, a SYS_C0015910été supprimé avec succès avec une simple requête ALTER, mais Relationship142avait besoin de DOUBLE CITATIONS
Sachin

1
Vous avez créé les contraintes à l'aide de guillemets doubles, par exemple:alter table ... add constraint "Relationship143" ... "Relationship143" est en effet un nom différent de RELATIONSHIP143. Mais "RELATIONSHIP143"et RELATIONSHIP143sont identiques
a_horse_with_no_name

2
Oracle (la base de données) ne créera jamais un nom comme "Relationship143"lui-même. C'était probablement l'un de vos outils qui a fait cela. Quoi qu'il en soit: en l'état, votre réponse est tout simplement fausse dans le contexte de la question d'origine.
a_horse_with_no_name
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.