Artur G.

Artur G. Manager / Management
3.0 enthusiast

Temat: Mały problem z update'em tabelki

Witam,

Mam niby dość banalne zadanie, ale trochę się przy nim zaciąłem.
Mam 2 tabelki tabelkaA i tabelkaB. Obie o identycznej definicji (klucz główny każdej z nich to contract_part_id), natomiast różnych danych.

Załóżmy, że pierwsza z nich ma 100tys. rekordów, a druga 50 tys. rekordów. Jednocześnie wszystkie contract_part_id tabelki B są pozdbiorem contract_part_id tabelki A.

To co chcę zrobić, to update'ować sobie wartości niektórych kolumn w tabelceA wartościami z tabelkiB dla tych rekordów tabelkiA, które mają swoje odpowiedniki w tabelceB. Pozostałe rekordy tabelki A pozostają takie jak były.

Napisałem na szybko następującego SQL'a:

update tabelkaA a
set (a.FTP1_PURE_RATE, a.FTP2_RATE, a.FTP_LIQ_SPRD, a.FTP_I_S_SPRD, a.FTP_TRY_SPRD, a.FTP_B_M_SPRD) = (select b.FTP1_PURE_RATE, b.FTP2_RATE, b.FTP_LIQ_SPRD, b.FTP_I_S_SPRD, b.FTP_TRY_SPRD, b.FTP_B_M_SPRD from tabelkaB b where a.contract_part_id =b.contract_part_id);

No i niestety wpadka.
Wprawdzie dla tych rekordów których contract_part_id występowało zarówno w tabelce A jak i B zrobił update poprawnie, jednak jeśli były jakieś rekordy w tabelceA, dla których nie było odpowiedników w tabelce B, to zamiast zostawić je nietknięte update'ował je null'ami :-(

Czy ktoś ma pomysł jak zmodyfikować zapytanie aby updatował tylko te 50 tys. rekordów które powinien?
Zależy mi też by było to rozwiązanie optymalne, gdyż szybkość działania jest tu sprawą kluczową.

Z góry dzięki!

P.S. Zapomniałem dodać że chodzi o SQL'a w wersji Oracle'owej Artur G. edytował(a) ten post dnia 19.04.11 o godzinie 20:39
Łukasz Kurowski

Łukasz Kurowski Usque Ad Finem

Temat: Mały problem z update'em tabelki

Artur G.:
update tabelkaA a
set (a.FTP1_PURE_RATE, a.FTP2_RATE, a.FTP_LIQ_SPRD, a.FTP_I_S_SPRD, a.FTP_TRY_SPRD, a.FTP_B_M_SPRD) = (select b.FTP1_PURE_RATE, b.FTP2_RATE, b.FTP_LIQ_SPRD, b.FTP_I_S_SPRD, b.FTP_TRY_SPRD, b.FTP_B_M_SPRD from tabelkaB b where a.contract_part_id =b.contract_part_id);
WHERE... i tu odpowiedni exist z podzapytaniem skorelowanym.

lub coś w tym stylu

update
(
select a.FTP1_PURE_RATE FTP1_PURE_RATE_A, ..., b.FTP1_PURE_RATE FTP1_PURE_RATE_B, ...
from tabelkaA a left join tabelkaB b on a.contract_part_id =b.contract_part_id
)
set FTP1_PURE_RATE_A = nvl (FTP1_PURE_RATE_B, FTP1_PURE_RATE_A)

Co zadziała szybciej to już zależy jaka jest proporcja w ilości rekordów pomiędzy obiema tabelami. Wersja Twoja z odpowiednimi indeksami będzie szybsza jeśli w tabeli B będzie mniej niż kilka % rekordów tabeli A. W przeciwnym wypadku kombinuj z drugim rozwiązaniem, bo "full scan" będzie bardziej opłacalny... Aha, no i odpowiednie "hinty" nie zaszkodzą!

Jeszcze trochę lektury na koniec:
http://psoug.org/reference/update.htmlŁukasz Kurowski edytował(a) ten post dnia 19.04.11 o godzinie 21:00
Monika A.

Monika A. programista

Temat: Mały problem z update'em tabelki

Czy to musi być SQL, czy może być PL/SQL? Spróbowałabym jeszcze z FORALL...

edit: choć wcale nie jestem pewna czy wydajniejsze :)Monika M. edytował(a) ten post dnia 19.04.11 o godzinie 22:37
Tomasz Przewęzikowski

Tomasz Przewęzikowski Kierownik Działu IT,
PACTOR WINDYKACJA Sp
z o.o. S.K.A

Temat: Mały problem z update'em tabelki

Można zrobić coś takiego

update tabelkaA a left join (select b.contract_part_id ,b.FTP1_PURE_RATE, b.FTP2_RATE, b.FTP_LIQ_SPRD, b.FTP_I_S_SPRD, b.FTP_TRY_SPRD, b.FTP_B_M_SPRD from tabelkaB b)tab ON a.contract_part_id = tab.contract_part_id

set
a.FTP1_PURE_RATE=tab.FTP1_PURE_RATE,
a.FTP2_RATE=tab.FTP2_RATE,
a.FTP_LIQ_SPRD=tab.FTP_LIQ_SPRD,
a.FTP_I_S_SPRD=tab.FTP_I_S_SPRD,
a.FTP_TRY_SPRD=tab.FTP_TRY_SPRD,
a.FTP_B_M_SPRD=tab.FTP_B_M_SPRD

where a.contract_part_id = tab.contract_part_id

Powinno zadziałać.
Adam O.

Adam O. Bazy danych etc

Temat: Mały problem z update'em tabelki

Nie wiem jaki to RDBMS, więc może to mało odkrywcze i nie będzie działać, ale:

update a
set
a.FTP1_PURE_RATE = b.FTP1_PURE_RATE,
a.FTP2_RATE = b.FTP2_RATE,
a.FTP_LIQ_SPRD = b.FTP_LIQ_SPRD,
a.FTP_I_S_SPRD = b.FTP_I_S_SPRD,
a.FTP_TRY_SPRD = b.FTP_TRY_SPRD,
a.FTP_B_M_SPRD = b.FTP_B_M_SPRD

from tabelkaA a
inner join tabelkaB b on a.contract_part_id =b.contract_part_id

Nie jestem pewien czy będzie coś szybszego. Może gdybyś założył klucz obcy w tabelce B, to kto wie...
Łukasz Kurowski

Łukasz Kurowski Usque Ad Finem

Temat: Mały problem z update'em tabelki

Adam O.:
Nie wiem jaki to RDBMS

Kolega napisał:
P.S. Zapomniałem dodać że chodzi o SQL'a w wersji Oracle'owej

i nie będzie działać, ale:

No właśnie chyba nie będzie :).
Artur G.

Artur G. Manager / Management
3.0 enthusiast

Temat: Mały problem z update'em tabelki

"where exist ... " z pierwszej odpowiedzi Łukasza załatwił sprawę :)
Dzięki!

Następna dyskusja:

Problem z UPDATE i CONCAT()




Wyślij zaproszenie do