Nicht vorhandene Einschränkung kann nicht gelöscht und auch nicht erstellt werden

16

Beim Testen einiger Migrationsskripte mit einer Kopie der Produktionsdaten (Skripte funktionieren einwandfrei mit Entwicklungsdaten) stieß ich auf eine merkwürdige Situation. Ein CONSTRAINT hat sich geändert, daher gebe ich DROP + ADD-Befehle aus:

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;

Der DROP-Befehl hat gut funktioniert, aber der ADD-Befehl ist fehlgeschlagen. Jetzt bin ich in einem Teufelskreis. Ich kann die Einschränkung nicht löschen, da sie nicht vorhanden ist (anfängliches Löschen hat wie erwartet funktioniert):

ORA-02443 - Einschränkung kann nicht gelöscht werden - Nicht vorhandene Einschränkung

Und ich kann es nicht erstellen, weil der Name bereits existiert:

ORA-00955: Name wird bereits von einem vorhandenen Objekt verwendet

Ich tippe A_DUP_CALLE_UK1in dem SQL Developer Suchfeld und ... da ist es! Eigentümer, Tabellenname, Tabellenumfeld ... alles passt zusammen: Es ist kein anderes Objekt mit demselben Namen, es ist meine ursprüngliche Einschränkung. Die Tabelle wird in den Details der Einschränkung angezeigt, aber die Einschränkung wird nicht in den Details der Tabelle angezeigt.

Meine Fragen:

  • Was ist die Erklärung dafür?
  • Wie kann ich sicherstellen, dass dies nicht passiert, wenn ich ein echtes Upgrade in Live Server durchführe?

(Server ist 10g XE, ich habe nicht genug Reputation, um das Tag zu erstellen.)

Álvaro González
quelle
Vielleicht wurde es als eine andere Art von Objekt erstellt und keine eindeutige Einschränkung? Vielleicht eindeutiger Index ..
Marian
Könnte die erste Erstellung mit Anführungszeichen um den Tabellennamen ausgeführt worden sein? Dies würde den Namen zwischen Groß- und Kleinschreibung unterscheiden. Wenn ja, könnten Sie mit Anführungszeichen und dem gleichen Fall fallen.
Adam Butler

Antworten:

13

Vermutlich hat Marian Recht und dies wird durch einen eindeutigen Index und eine Einschränkung mit demselben Namen verursacht, z.

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  

Normalerweise wird beim Hinzufügen einer eindeutigen Einschränkung ein eindeutiger Index mit demselben Namen erstellt, aber der Index und die Einschränkung sind nicht dasselbe. Sehen Sie sich an all_indexes, ob ein Index aufgerufen wird, A_DUP_CALLE_UK1und versuchen Sie herauszufinden, ob er von etwas anderem verwendet wird, bevor Sie ihn löschen!

Jack Douglas
quelle
Das war das Problem. Die vom expBefehl generierte Dump-Datei enthält eine CREATE UNIQUE INDEX "A_DUP_CALLE_UK1" ...Anweisung, die im ursprünglichen Script-Set nicht vorhanden ist.
Álvaro González
6

Scheint sehr seltsam.

Du kannst rennen:

 SELECT *
 FROM user_objects
 WHERE object_name = 'A_DUP_CALLE_UK1'

um zu überprüfen, über welche Art von Objekt sich Oracle beschwert. Dann können Sie die entsprechende DROP-Anweisung dafür ausführen.

Das einzige andere, was ich mir vorstellen kann, ist, die Tabelle vollständig DROP TABLE A_DUP_CALLE CASCADE CONSTRAINTSzu löschen, um alles loszuwerden, was zu dieser Tabelle gehört, und sie dann vollständig neu zu erstellen.

Wenn die Tabelle wertvolle Daten enthält, können Sie diese vorher sichern:

CREATE TABLE old_data
AS
SELECT *
FROM A_DUP_CALLE;

Sobald Sie die Tabelle neu erstellt haben, können Sie dies tun

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

um die Daten wiederherzustellen.

ein Pferd ohne Name
quelle
4

Ich hatte vor ein paar Minuten das gleiche Problem ... und ich habe eine Erklärung gefunden.

Durch das Erstellen eines Primärschlüssels erstellt Oracle zwei Objekte: eine Einschränkung und einen Index, der den "EINZIGARTIGEN" Teil steuert.

Wenn Sie die Einschränkung löschen, bleibt der Index dort und verwendet denselben Namen wie der Index. Wenn Sie also nur ausführen, wird der Index beibehalten

alter table t drop constraint u1;

Sie lassen nur die Einschränkung fallen. Um den Index zu löschen, müssen Sie ausführen

drop index u1;

Dies sollte die Arbeit erledigen. Alternativ können Sie beide Befehle gleichzeitig mit dem Befehl ausführen

alter table t drop constraint u1 including indexes;
Cristian Meneses A
quelle
welche db? Einschließlich funktioniert nicht in Orakel
Derick
1

Primärschlüsselbeschränkung wird mit Index geliefert. Sie löschen die Einschränkung, aber nicht den Index. Prüfen:

select * from ALL_OBJECTS where OBJECT_NAME = 'PK_TBL_CONSTR';

und du siehst OBJECT_TYPEist INDEX.

Also mach beides:

alter table TBL drop constraint PK_TBL_CONSTR;
drop index PK_TBL_CONSTR;
gavenkoa
quelle
1

Mach das

ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT "A_DUP_CALLE_UK1";

Es wird klappen.

BILD: Bildbeschreibung hier eingeben

Sachin
quelle
Nein, es wird nicht funktionieren. Ihre Aussage ist genau die gleiche Aussage wie die erste Aussage in der Frage:ALTER TABLE A_DUP_CALLE DROP CONSTRAINT A_DUP_CALLE_UK1;
a_horse_with_no_name
Es hat tatsächlich funktioniert. Ich hatte seit heute Mittag das gleiche Problem und auf der Suche nach der Lösung bin ich auf dieses Problem gestoßen. Manchmal wurden CONSTRAINTS möglicherweise unter Berücksichtigung der Groß- und Kleinschreibung erstellt. In diesem Fall müssen Sie den Namen der Einschränkung in doppelte Anführungszeichen setzen, wenn Sie ihn löschen.
Sachin
Und es hat bei mir funktioniert. Ich hatte die Einschränkungen nicht explizit benannt, daher gab das System ihm seinen eigenen generierten Namen Relationship142und anderen NOT NULLEinschränkungen wurde der Name gegeben SYS_C0015910. So SYS_C0015910wurde erfolgreich mit einfachen ALTER-Abfrage gelöscht, aber DOUBLE QUOTESRelationship142
Sachin
1
Die Sie erstellt die Einschränkungen mit doppelten Anführungszeichen, zB: alter table ... add constraint "Relationship143" ... "Relationship143"ist in der Tat ein anderer Name als RELATIONSHIP143. Aber "RELATIONSHIP143"und RELATIONSHIP143sind identisch
a_horse_with_no_name 24.12.14
2
Oracle (die Datenbank) wird niemals einen eigenen Namen erstellen "Relationship143". Es war wahrscheinlich eines Ihrer Werkzeuge, die dies taten. Wie dem auch sei: Wie es aussieht, Ihre Antwort ist im Kontext der ursprünglichen Frage einfach falsch.
a_horse_with_no_name 24.12.14