2013-07-17 11 views
10

Gibt es eine Möglichkeit, Oracle Merge zum Einfügen und Löschen verwenden, aber nicht aktualisieren?Oracle-SQL-Merge zum Einfügen und Löschen, aber nicht aktualisieren

Ich habe eine Tabelle, die eine Reihe von Werten für eine einzelne Zeile in einer anderen Tabelle darstellt. Ich könnte die Menge der Werte ändern, indem ich sie alle lösche und die neue Menge hinzufüge, oder indem ich einige selektiv lösche und andere hinzufüge, aber ich bin daran interessiert, wenn möglich eine einzige Aussage zu machen.

Hier ist ein Arbeitsbeispiel mit Update. Damit dies funktioniert, musste ich dummy hinzufügen, so dass eine Spalte zum Aktualisieren verfügbar war, die nicht im on Zustand war. Gibt es eine Möglichkeit, nur zu löschen und einzufügen, ohne eine Dummy-Spalte zu aktualisieren?

Keine Spalte aus der on-Bedingung möglicherweise in der update set-Liste, auch wenn es nicht tatsächlich aktualisiert wird.

create table every_value (the_value varchar2(32)); 
create table paired_value (the_id number, a_value varchar2(32) , dummy number default 0); 
-- the_id is a foreign_key to a row in another table 

insert into every_value (the_value) values ('aaa'); 
insert into every_value (the_value) values ('abc'); 
insert into every_value (the_value) values ('ace'); 
insert into every_value (the_value) values ('adg'); 
insert into every_value (the_value) values ('aei'); 
insert into every_value (the_value) values ('afk'); 

-- pair ace and afk with id 3 
merge into paired_value p using every_value e 
on (p.the_id = 3 and p.a_value = e.the_value) 
when matched then update set dummy=dummy+1 
delete where a_value not in ('ace','afk') 
when not matched then insert (the_id,a_value) 
values (3,e.the_value) 
where e.the_value in ('ace','afk'); 

-- pair ace and aei with id 3 
-- should remove afk, add aei, do nothing with ace 
merge into paired_value p using every_value e 
on (p.the_id = 3 and p.a_value = e.the_value) 
when matched then update set dummy = dummy+1 
delete where a_value not in ('ace','aei') 
when not matched then insert (the_id,a_value) 
values (3,e.the_value) 
where e.the_value in ('ace','aei'); 

-- pair aaa and adg with id 4 
merge into paired_value p using every_value e 
on (p.the_id = 4 and p.a_value = e.the_value) 
when matched then update set dummy = dummy+1 
delete where a_value not in ('aaa','adg') 
when not matched then insert (the_id,a_value) 
values (4,e.the_value) 
where e.the_value in ('aaa','adg'); 

select * from paired_value; 

Ich habe dies 10g in Oracle versucht, und mit diesem sqlfiddle, Oracle 11g.

Antwort

15

Nein, Sie können keine Zeilen löschen, die nicht durch den Befehl zum Zusammenführen aktualisiert wurden.
Hier ist die Dokumentation: http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

die DELETE Geben where_clause Daten in einer Tabelle zu bereinigen, während Bestücken oder Aktualisierung. Die einzigen von dieser Klausel betroffenen Zeilen sind diejenigen Zeilen in der Zieltabelle, die durch die Zusammenführung Operation aktualisiert werden. Die DELETE WHERE-Bedingung wertet den aktualisierten Wert aus, nicht der ursprüngliche Wert, der von der Bedingung UPDATE SET ... WHERE ausgewertet wurde. Wenn eine Zeile der Zieltabelle die Bedingung DELETE erfüllt, aber nicht in der Verknüpfung enthalten ist, die durch die ON-Klausel definiert ist, wird sie nicht gelöscht. Alle Löschtrigger, die in der Zieltabelle definiert sind, werden für jede Zeilenlöschung aktiviert.

Das bedeutet, dass die Zeilen aktualisiert werden müssen. Hovewer, brauchen Sie nicht alle Zeilen zu aktualisieren, nachdem UPDATE die gleiche WHERE-Klausel verwenden, wie Sie nach verwenden

DELETE
when matched then update set dummy=dummy 
    where a_value not in ('ace','afk') 
delete 
    where a_value not in ('ace','afk') 
+0

Ich war ziemlich sicher, es gab keinen besseren Weg als eine Dummy-Spalte, aber ich werde nicht nur eine Dummy-Spalte hinzufügen. Naja. – drawnonward

1

Ich habe herausgefunden Sie die Spalte selbst festlegen können:

MERGE ... 
WHEN MATCHED THEN 
    UPDATE SET a_value = a_value WHERE a_value not in ('ace','afk') 
    DELETE WHERE a_value not in ('ace','afk') 

Dies macht die Dummy-Spalte überflüssig.

+0

Ist as_value in Ihrem ON-Zustand? Dies funktionierte bei 11g nicht, wenn die Spalte in der ON-Bedingung ist. Ich erhalte den Fehler "Spalten, auf die in der ON-Klausel verwiesen wird, kann nicht aktualisiert werden", selbst wenn das Update den Wert auf sich selbst setzt. – Marquez

+0

Das ist richtig. Nach Orakeldokumentation können Sie eine Spalte, die Teil der ON-Klausel ist, nicht aktualisieren. Wenn Sie darüber nachdenken, macht es Sinn. Sie könnten jedoch eine andere Nicht-Dummy-Spalte im Update verwenden; ohne es auszuprobieren, weiß ich nicht, ob die delete-Klausel immer noch den gleichen Fehler auslöst? Z.B. SET b_value = b_value wobei a_value nicht in ('ace', 'afk') DELETE wo a_value nicht in ('ace', 'afk'). – datico

Verwandte Themen