2013-07-17 43 views
10

Czy istnieje sposób użycia Oracle scalania do wstawiania i usuwania, ale nie aktualizacji?Oracle sql scalić, aby wstawić i usunąć, ale nie aktualizować

Mam tabelę reprezentującą zestaw wartości związanych z jednym wierszem w innej tabela. Mógłbym zmienić zestaw wartości, kasując je wszystkie i dodając nowy zestaw, lub selektywnie usuwając niektóre i dodając inne, ale jestem zainteresowany złożeniem pojedynczego wyciągu, jeśli to możliwe.

Oto działający przykład z aktualizacją. Aby to działało, musiałem dodać dummy, aby kolumna była dostępna do aktualizacji, która nie była w stanie on. Czy jest jakiś sposób, aby usunąć i wstawić bez atrapa kolumna do aktualizacji?

Żadna kolumna z warunku on nie może znajdować się na liście update set, nawet jeśli nie została faktycznie zaktualizowana.

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; 

Próbowałem to w Oracle 10g, a wraz z tym sqlfiddle, Oracle 11g.

Odpowiedz

15

Nie, nie można usunąć wierszy, które nie zostały zaktualizowane za pomocą polecenia scalania.
Oto dokumentacja: http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm

Określ DELETE where_clause oczyścić danych w tabeli podczas zaludnienie lub jego aktualizacji. Jedynymi wierszami, których dotyczy ta klauzula są te wiersze w tabeli docelowej, które są aktualizowane przez operację scalania Operacja scalania Operacja. Warunek DELETE WHERE ocenia zaktualizowaną wartość, a nie oryginalną wartość, która została oszacowana przez warunek UPDATE SET ... WHERE . Jeśli wiersz tabeli docelowej spełnia warunek DELETE , ale nie jest uwzględniony w łączeniu zdefiniowanym przez klauzulę ON, , to nie jest usuwany. Wszelkie wyzwalacze usuwania zdefiniowane na docelowej tabeli będą aktywowane dla każdego usunięcia wiersza.

Oznacza to, że wiersze należy zaktualizować. Hovewer, nie trzeba aktualizować wszystkie wiersze, po aktualizacji korzystać z tego samego WHERE jak używasz po DELETE

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

Byłem dość pewny, że nie było lepszego sposobu niż posiadanie kolumny manekinowej, ale nie zamierzam dodawać kolumny manekinowej tylko po to. No cóż. – drawnonward

1

Znalazłem można ustawić kolumnę do siebie:

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') 

Zaprzecza to potrzebie kolumny dummy.

+0

Czy as_value jest w stanie ON? Nie działało to dla mnie w 11g, jeśli kolumna jest w stanie ON Otrzymuję komunikat "Kolumny wymienione w klauzuli ON nie można zaktualizować", nawet jeśli aktualizacja ustawia wartość dla siebie. – Marquez

+0

To prawda. Na podstawie dokumentacji Oracle nie można zaktualizować kolumny, która jest częścią klauzuli ON. Jeśli myślisz o tym, ma to sens. Ale w aktualizacji można użyć innej kolumny innej niż próbna; bez wypróbowania tego nie wiem, czy klauzula delete nadal wywoływałaby ten sam błąd? Na przykład. SET b_value = b_value gdzie a_value nie jest w ("as", "afk") DELETE gdzie a_value nie jest w ("as", "afk"). – datico