Nie można usunąć nieistniejącego ograniczenia i nie można go również utworzyć

16

Podczas testowania niektórych skryptów migracji z kopią danych produkcyjnych (skrypty działają poprawnie z danymi programistycznymi) znalazłem ciekawą sytuację. CONSTRAINT zmieniło się, dlatego wydajemy polecenia 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;

Polecenie DROP działało dobrze, ale polecenie DODAJ nie powiodło się. Teraz jestem w błędnym kole. Nie mogę usunąć ograniczenia, ponieważ nie istnieje (początkowe upuszczenie działało zgodnie z oczekiwaniami):

ORA-02443: Nie można usunąć ograniczenia - nieistniejące ograniczenie

Nie mogę go utworzyć, ponieważ nazwa już istnieje:

ORA-00955: nazwa jest już używana przez istniejący obiekt

Piszę A_DUP_CALLE_UK1w polu wyszukiwania dewelopera SQL i ... gotowe! Właściciel, nazwa tabeli, Tablescape ... wszystko mecze: nie jest inny obiekt o tej samej nazwie, to jest mój oryginalny ograniczenie. Tabela pojawia się w szczegółach ograniczenia, ale ograniczenie nie pojawia się w szczegółach tabeli.

Moje pytania:

  • Jakie jest tego wytłumaczenie?
  • Jak mogę się upewnić, że tak się nie stanie, gdy dokonam prawdziwej aktualizacji na serwerze na żywo?

(Serwer to 10 g XE, nie mam wystarczającej reputacji, aby utworzyć tag).

Álvaro González
źródło
Może został stworzony jako inny typ obiektu, a nie wyjątkowe ograniczenie? Może unikalny indeks ..
Marian
Czy można utworzyć początkowe tworzenie z cudzysłowami wokół nazwy tabeli? W ten sposób w nazwie rozróżniana jest wielkość liter. Jeśli tak, możesz upuścić z cytatami i tym samym przypadkiem.
Adam Butler,

Odpowiedzi:

13

Domyślam się, że Marian ma rację, a jest to spowodowane unikalnym indeksem i ograniczeniem o tej samej nazwie, np .:

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  

Zwykle po dodaniu unikalnego ograniczenia tworzony jest unikalny indeks o tej samej nazwie - ale indeks i ograniczenie nie są tym samym. Sprawdź, all_indexesczy istnieje wywoływany indeks A_DUP_CALLE_UK1i spróbuj dowiedzieć się, czy jest on używany przez coś innego, zanim go upuścisz!

Jack mówi, że spróbuj topanswers.xyz
źródło
To był problem. Plik zrzutu wygenerowany przez exppolecenie zawiera CREATE UNIQUE INDEX "A_DUP_CALLE_UK1" ...instrukcję, której nie ma w oryginalnym zestawie skryptów.
Álvaro González
6

Wydaje się bardzo dziwne.

Możesz uruchomić:

 SELECT *
 FROM user_objects
 WHERE object_name = 'A_DUP_CALLE_UK1'

aby sprawdzić, czy na jaki obiekt narzeka Oracle. Następnie możesz uruchomić w tym celu odpowiednią instrukcję DROP.

Jedyną rzeczą, o której mogę myśleć, jest całkowite upuszczenie stołu, DROP TABLE A_DUP_CALLE CASCADE CONSTRAINTSaby pozbyć się wszystkiego, co należy do tego stołu, a następnie odtworzenie go całkowicie.

Jeśli tabela zawiera wartościowe dane, możesz wykonać ich kopię zapasową przed:

CREATE TABLE old_data
AS
SELECT *
FROM A_DUP_CALLE;

Po odtworzeniu tabeli możesz to zrobić

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

przywrócić dane.

koń bez imienia
źródło
4

Kilka minut temu miałem ten sam problem ... i znalazłem wyjaśnienie.

Tworząc klucz podstawowy, Oracle tworzy dwa obiekty: ograniczenie i indeks, który kontroluje część „UNIQUE”.

Po usunięciu ograniczenia indeks pozostaje tam, używając tej samej nazwy indeksu, więc jeśli wykonasz tylko

alter table t drop constraint u1;

Zrzucisz tylko ograniczenie. Aby usunąć indeks, musisz wykonać

drop index u1;

To powinno wystarczyć. Alternatywnie możesz wykonać obie te komendy jednocześnie z komendą

alter table t drop constraint u1 including indexes;
Cristian Meneses A.
źródło
który db? w tym nie działa w wyroczni
Derick
1

Ograniczenia klucza podstawowego pochodzą z indeksem. Upuszczasz ograniczenie, ale nie indeksujesz. Czek:

select * from ALL_OBJECTS where OBJECT_NAME = 'PK_TBL_CONSTR';

i widzisz, że OBJECT_TYPEjest INDEX.

Więc wykonaj oba:

alter table TBL drop constraint PK_TBL_CONSTR;
drop index PK_TBL_CONSTR;
gavenkoa
źródło
1

Zrób to

ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT "A_DUP_CALLE_UK1";

To będzie działać.

WIZERUNEK: wprowadź opis zdjęcia tutaj

Sachin
źródło
Nie, to nie zadziała. Twoje oświadczenie jest dokładnie tym samym stwierdzeniem, co pierwsze oświadczenie w pytaniu:ALTER TABLE A_DUP_CALLE DROP CONSTRAINT A_DUP_CALLE_UK1;
a_horse_w_no_name
TO faktycznie działało. Miałem ten sam problem od dzisiejszego południa i szukałem rozwiązania. Czasami OGRANICZENIA mogły zostać utworzone z rozróżnianiem wielkości liter, w takim przypadku po upuszczeniu trzeba będzie umieścić nazwę ograniczenia w podwójnych cudzysłowach .
Sachin
I zadziałało dla mnie. Nie nazwałam ograniczeń wyraźnie, dlatego system nadał mu swoją własną wygenerowaną nazwę, Relationship142a inne NOT NULLOgraniczenie zostało nazwane SYS_C0015910. Tak więc SYS_C0015910został pomyślnie usunięty za pomocą prostego zapytania ALTER, ale Relationship142potrzebował PODWÓJNYCH CYTATÓW
Sachin
1
Rzecz ty stworzony ograniczeń używając cudzysłowia, np: alter table ... add constraint "Relationship143" ... "Relationship143"jest rzeczywiście inna nazwa niż RELATIONSHIP143. Ale "RELATIONSHIP143"i RELATIONSHIP143identyczne
a_horse_with_no_name
2
Oracle (baza danych) nigdy nie stworzy nazwy takiej jak "Relationship143"sama. Prawdopodobnie było to jedno z twoich narzędzi. W każdym razie: w obecnej formie Twoja odpowiedź jest po prostu błędna w kontekście pierwotnego pytania.
a_horse_w_na_name