poniedziałek, 14 października 2013

Wielotabelowy INSERT (Multitable Insert)

Wielotabelowy insert (Multitable insert)

Przypuśćmy że wynik poniższego zapytania:



select department_name, count(*), max(salary), min(salary),round(avg(salary))

from employees join departments using(department_id) group by department_name;



Chciałbym załadować do kilku tabel, rozbijając wynik na wiele elementów. Przykładowo do tabeli „liczba_pracowników” trafiłaby nazwa departamentu i liczba pracowników, do tabeli „srednie_zarobki” trafiłaby nazwa tabeli i średnie zarobki etc.
W pierwszej kolejności tworzę tabele do których następnie załaduję dane:

create table liczba_pracownikow(
nazwa_departamentu varchar2(50),
liczba integer
);

create table najwyzsze_zarobki(
nazwa_departamentu varchar2(50),
kwota number
);

create table najnizsze_zarobki(
nazwa_departamentu varchar2(50),
kwota number
);

create table srednie_zarobki(
nazwa_departamentu varchar2(50),
kwota number
);


Mógłbym teraz zastosować kilka osobnych insertów w taki sposób:

insert into liczba_pracownikow select department_name,count(*)
from employees join departments using(department_id) group by department_name;
insert into najwyzsze_zarobki select department_name,max(salary)
from employees join departments using(department_id) group by department_name;
insert into najnizsze_zarobki select department_name,min(salary)
from employees join departments using(department_id) group by department_name;
insert into srednie_zarobki select department_name,round(avg(salary))
from employees join departments using(department_id) group by department_name;

Jednak ma to zasadnicze wady:

  • Robiąc kilka insertów na podstawie zapytań, doprowadzam do wielokrotnych skanów tabeli źródłowej. To problematyczne i nieefektywne przy dużych tabelach.
  • Pomiędzy poszczególnymi insertami dane w tabeli źródłowej mogą ulec zmianie, więc efekty mogą być niespójne

    Zamiast wielu insertów, możemy zrobić jeden insert wielotabelowy:

    insert all
    into liczba_pracownikow(nazwa_departamentu,liczba) values(department_name,liczba)
    into najwyzsze_zarobki(nazwa_departamentu,kwota) values(department_name,maksi)
    into najnizsze_zarobki(nazwa_departamentu,kwota) values(department_name, mini)
    into srednie_zarobki(nazwa_departamentu,kwota) values(department_name,srednia)
    select department_name,
    count(*) liczba, max(salary) maksi, min(salary) mini,round(avg(salary)) srednia
    from employees join departments using(department_id) group by department_name;


    W tym przypadku, skan po tabeli źródłowej wykonywany jest raz, a odczytane dane są rozbijane po czterech tabelach na raz. Ponadto dane pozostają spójne. Przyjrzyjmy się planowi wykonania zapytania:





Brak komentarzy:

Prześlij komentarz