Ich erhalte die Meldung "ORA-01779: Eine Spalte, die einer nicht schlüsselerhaltenen Tabelle zugeordnet ist, kann nicht geändert werden", wenn ich versuche, einen Join zu aktualisieren. Ich habe mich auf der Website umgesehen und viele Ratschläge gefunden, was Schlüsselerhaltung bedeutet und warum dies notwendig ist ... aber so nah ich das beurteilen kann, halte ich mich an diesen Rat und erhalte immer noch den Fehler.
Ich habe zwei Tabellen:
PG_LABLOCATION has, among other things, the columns:
"LABLOCID" NUMBER,
"DNSNAME" VARCHAR2(200 BYTE)
LABLOCID is the primary key, DNSNAME has a unique constraint
PG_MACHINE has, among other things, the columns:
"MACHINEID" NUMBER,
"LABLOCID" NUMBER,
"IN_USE" NUMBER(1,0) DEFAULT 0,
"UPDATE_TIME" TIMESTAMP (6) DEFAULT '01-JAN-1970'
MACHINEID is a primary key
LABLOCID is a foreign key into LABLOCID in PG_LABLOCATION (its primary key)
Das Update, das ich ausführe, ist:
update
(select mac.in_use, mac.update_time
from pg_machine mac
inner join pg_lablocation loc
on mac.lablocid = loc.lablocid
where loc.dnsname = 'value'
and '02-JAN-2013' > mac.update_time
)
set in_use = 1 - MOD( 101, 2 ), update_time = '02-JAN-2013';
Ich aktualisiere nur Werte in einer Tabelle (PG_MACHINE) und die Verknüpfungsspalte in der anderen Tabelle ist der Primärschlüssel, wodurch der Schlüssel beim Lesen erhalten bleibt. Ich bin besorgt, dass die where-Klausel das Problem verursacht, aber ich habe versucht, den Filter auf mac.update_time zu entfernen, und habe den gleichen Fehler erhalten, und loc.dnsname hat eine eindeutige Einschränkung.
Was noch seltsamer ist, ist, dass wir, wie viele Leute, eine Entwickler- und eine Produktumgebung haben. Wir haben eine vollständige Schema- und Datenmigration von prod zu dev durchgeführt. Ich habe sie beide durchgesehen und sie haben identische Indizes und Einschränkungen. Die Abfrage funktioniert in dev, generiert jedoch den obigen Fehler in prod.
Also zwei Fragen:
1) Können Sie sehen, was mit meiner Anfrage nicht stimmt? 2) Können Sie vorschlagen, was zwischen meiner Entwickler- und Produktumgebung unterschiedlich sein könnte (z. B. Servereinstellungen), was diesen Fehler in der einen, aber nicht in der anderen verursachen könnte?
Antworten:
Sie können einen Join in Oracle aktualisieren, wenn die folgenden Bedingungen erfüllt sind :
(Es gelten zusätzliche Einschränkungen für die Aktualisierung von Ansichten. )
In Ihrem Beispiel aktualisieren Sie
PG_MACHINE
nur die Tabelle . Oracle muss sicherstellen, dass für eine einzelne Zeile dieser Tabelle nur eine Zeile der anderen gefunden werden kann. Dies scheint der Fall zu sein, da Sie eine PK aktiviert habenPG_LABLOCATION.LABLOCID
. Daher sollten Sie in der Lage sein, den Join zu aktualisieren. Siehe zum Beispiel diese SQLFiddle mit einem ähnlichen Setup .In Ihrem Fall sollten Sie entweder:
MERGE
if , wennPG_LABLOCATION.LABLOCID
es für die entsprechende Abfrage eindeutig ist.MERGE
ist weniger streng als das Aktualisieren mit Joins und gibt nur dann einen Fehler zurück, wenn die Ergebnismenge tatsächlich ein Duplikat enthält (während diesUPDATE
fehlschlägt, wenn die Möglichkeit eines Duplikats besteht).Überprüfen Sie Ihre Abfrage, da Sie in der
SELECT
Klausel keine Werte aus der übergeordneten Tabelle benötigen , können Sie sie als Semi-Join umschreiben (dies garantiert, dass kein Duplikat generiert wird):Dies könnte wie folgt umgeschrieben werden:
In diesem Fall würde ich mich für die dritte Option entscheiden: Im Allgemeinen können Sie die Eltern in einem Eltern-Kind-Join nicht aktualisieren .
quelle
PG_MACHINE.LABLOCID
!! Die Fehlermeldung kann von einer aufschiebbaren Einschränkung in einer Umgebung stammen, siehe diese andere SQLFiddle . Über die Datumskonvertierung können Sie diese Notation für wörtliche Datumsangaben verwenden =)