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.