Impossibile eliminare il vincolo inesistente e neanche crearlo


16

Durante il test di alcuni script di migrazione con una copia dei dati di produzione (gli script funzionano bene con i dati di sviluppo) ho trovato una situazione curiosa. Un VINCITORE è cambiato, quindi sto inviando i comandi 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;

Il comando DROP ha funzionato bene ma quello ADD non è riuscito. Ora sono in un circolo vizioso. Non riesco a eliminare il vincolo perché non esiste (il rilascio iniziale ha funzionato come previsto):

ORA-02443: Impossibile eliminare il vincolo - vincolo inesistente

E non posso crearlo perché il nome esiste già:

ORA-00955: il nome è già utilizzato da un oggetto esistente

I tipo A_DUP_CALLE_UK1in SQL Developer di ricerca scatola e ... eccolo! Proprietario, nome tabella, tablescape ... tutto corrisponde: non è un oggetto diverso con lo stesso nome, è il mio vincolo originale. La tabella viene visualizzata nei dettagli del vincolo ma il vincolo non viene visualizzato nei dettagli della tabella.

Le mie domande:

  • Qual è la spiegazione per questo?
  • Come posso assicurarmi che non accada quando eseguo il vero aggiornamento nel server live?

(Il server è 10g XE, non ho abbastanza reputazione per creare il tag.)


Forse è stato creato come un altro tipo di oggetto e non un vincolo unico? Forse un indice unico ..
Marian,

La creazione iniziale potrebbe essere stata eseguita con virgolette attorno al nome della tabella? Ciò renderebbe il nome case sensitive. Se è così potresti cadere tra virgolette e lo stesso caso.
Adam Butler,

Risposte:


13

Suppongo che Marian abbia ragione e questo è causato da un indice e un vincolo univoci con lo stesso nome, ad esempio:

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  

Normalmente quando si aggiunge un vincolo univoco, viene creato un indice univoco con lo stesso nome, ma l'indice e il vincolo non sono la stessa cosa. Dai un'occhiata all_indexesper vedere se esiste un indice chiamato A_DUP_CALLE_UK1e prova a capire se viene utilizzato da qualcos'altro prima di rilasciarlo!


Questo era il problema. Il file di dump generato dal expcomando contiene CREATE UNIQUE INDEX "A_DUP_CALLE_UK1" ...un'istruzione che non è presente nel set di script originale.
Álvaro González,

6

Sembra molto strano.

Puoi eseguire:

 SELECT *
 FROM user_objects
 WHERE object_name = 'A_DUP_CALLE_UK1'

per verificare se si lamenta il tipo di oggetto di cui Oracle si lamenta. Quindi è possibile eseguire l'appropriata istruzione DROP per questo.

L'unica altra cosa a cui riesco a pensare è di eliminare completamente la tabella usando DROP TABLE A_DUP_CALLE CASCADE CONSTRAINTSper sbarazzarsi di tutto ciò che appartiene a quella tabella e quindi ricrearla completamente.

Se la tabella contiene dati di valore, è possibile effettuare un backup prima di:

CREATE TABLE old_data
AS
SELECT *
FROM A_DUP_CALLE;

Dopo aver ricreato il tavolo, puoi farlo

INSERT INTO A_DUP_CALLE (col1, col2, col3) 
SELECT col1, col2, col3
FROM old_data

per ripristinare i dati.


4

Ho avuto lo stesso problema solo pochi minuti fa ... e ho trovato una spiegazione.

Creando una chiave primaria, Oracle crea due oggetti: un vincolo e un indice che controlla la parte "UNIQUE".

Eliminando il vincolo, l'indice rimane lì, usando lo stesso nome dell'indice, quindi se si esegue solo

alter table t drop constraint u1;

Abbandonerai solo il vincolo. Per eliminare l'indice, devi eseguire

drop index u1;

Questo dovrebbe fare il lavoro. In alternativa, è possibile eseguire entrambi questi comandi contemporaneamente con il comando

alter table t drop constraint u1 including indexes;

quale db? compreso non funziona in Oracle
Derick

1

Il vincolo chiave primaria viene fornito con l'indice. Rilasci il vincolo ma non l'indice. Dai un'occhiata:

select * from ALL_OBJECTS where OBJECT_NAME = 'PK_TBL_CONSTR';

e vedi OBJECT_TYPEè INDEX.

Quindi fai entrambe le cose:

alter table TBL drop constraint PK_TBL_CONSTR;
drop index PK_TBL_CONSTR;

1

Fai questo

ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT "A_DUP_CALLE_UK1";

Funzionerà.

IMMAGINE: inserisci qui la descrizione dell'immagine


No, non funzionerà. La tua affermazione è esattamente la stessa affermazione della prima affermazione nella domanda:ALTER TABLE A_DUP_CALLE DROP CONSTRAINT A_DUP_CALLE_UK1;
a_horse_with_no_name

Ha funzionato davvero. Ho avuto lo stesso problema da oggi a mezzogiorno, e cercando la soluzione mi sono imbattuto in questo. A volte VINCOLI potrebbero essere stati creati tenendo conto della distinzione tra maiuscole e minuscole, nel qual caso è necessario inserire il nome del vincolo tra virgolette quando lo si rilascia.
Sachin,

E ha funzionato per me. Non avevo nominato esplicitamente i vincoli, quindi il sistema gli ha dato il proprio nome generato Relationship142e ad altri NOT NULLVincoli è stato dato il nome SYS_C0015910. Quindi è SYS_C0015910stato cancellato con successo con una semplice query ALTER, ma Relationship142serviva DOPPIO PREVENTIVO
Sachin

1
L'utente ha creato i vincoli usando le doppie virgolette, ad esempio: alter table ... add constraint "Relationship143" ... "Relationship143"è in effetti un nome diverso da RELATIONSHIP143. Ma "RELATIONSHIP143"e RELATIONSHIP143sono identici
a_horse_with_no_name

2
Oracle (il database) non creerà mai un nome simile "Relationship143"da solo. Probabilmente è stato uno dei tuoi strumenti a farlo. Comunque: così com'è, la tua risposta è semplicemente sbagliata nel contesto della domanda originale.
a_horse_with_no_name
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.