Wykład 8 SQL praca z tabelami 5
Podzapytania to mechanizm pozwalający wykorzystywać wyniki jednego zapytania w innym zapytaniu. Nazywane często zapytaniami zagnieżdżonymi. Są stosowane z zapytaniami typu SELECT, INSERT, UPDATE i DELETE, gdzie są wprowadzane do klauzul WHERE lub FROM. Dwa typy podzapytań: - proste - skorelowane W przykładach można wykorzystać bazę złożoną z tabel klienci, towary i zamowienia o strukturach: klienci id imie nazwisko towary id nazwa grupa cena zamowienia id klient_id towar_id data wartosc
Podzapytanie w klauzuli FROM SELECT kolumny_zapytania FROM (SELECT kolumny_podzapytania FROM tablice WHERE warunki_podzapytania ) AS nazwa WHERE warunki_zapytania; zapytanie główne pod-zapytanie zapytanie główne c.d. gdzie argument nazwa jest nazwą tablicy wynikowej zwróconej przez podzapytanie. np. SELECT imie, nazwisko, wartosc, data FROM (SELECT imie, nazwisko, wartosc, data FROM klienci, zamowienia WHERE klienci.id = zamowienia.klient_id) AS klienci_zamowienia WHERE wartosc > 15 ORDER BY wartosc; Efektem jest tablica o kolumnach imie, nazwisko, wartosc i data, dla wierszy, w których wartosc zamówienia jest większa niż 15.
Podzapytanie proste w klauzuli WHERE. Podzapytanie proste to takie podzapytanie, które jest wykonywane raz, a jego wynik jest następnie wykorzystywany w zapytaniu głównym np. SELECT towar_id FROM zamówienia WHERE wartosc = (SELECT MIN(wartosc) FROM zamowienia); zapytanie główne pod-zapytanie gdzie najpierw wykonywane jest podzapytanie,a potem pytanie główne. Wynikiem jest tabela z kolumna towar_id i jednym wierszem o min wartości zamówienia. Podobnie: SELECT towar_id, nazwa FROM zamowienia, towary WHERE wartosc = (SELECT MIN(wartosc) FROM zamowienia) zapytanie głowne pod-zapytanie AND towary.id = zamowienia.towar_id; dodatkowo wyświetla kolumne z nazwą towaru o min wartości zamówienia.
Podzapytanie zwracające wiele wartości w klauzuli WHERE. Przykład: SELECT zamowienia.id, imie, nazwisko, nazwa, data, wartosc FROM zamówienia, towary, klienci WHERE wartosc IN (SELECT MAX(wartosc) FROM zamowienia GROUP BY towar_id) AND towary.id = zamowienia.towar_id AND klienci.id = zamowienia.klient_id ORDER BY wartosc; gdzie otrzymamy kolumny zamowienia.id, imie, nazwisko, nazwa, data, wartosc dla najwyższych zamówień dla kardego typu towaru (towar_id) posortowanych względem wartości zamówienia.
Podzapytania skorelowane. Podzapytania skorelowane są wykonywane dla każdej wartości analizowanej przez zapytanie główne. Dają odpowiedź na bardziej skomplikowane pytania. Przykład: SELECT id, nazwa, cena, grupa FROM towary WHERE cena > (SELECT AVG(cena) FROM towary AS towary2 WHERE towary.grupa=towary2.grupa ) ORDER BY cena; dla każdego towaru analizowanego w zapytaniu głównym w zapytaniu skorelowanym zostanie wyliczona średnia cena grupy towarów, do której towar należy (tablica towary została w pod-zapytaniu przemianowana na towary2).
Podzapytania w instrukcjach aktualizujacych dane. Podzapytania mogą być wykorzystywane w przypadku instrukcji aktualizujących dane, takich jak INSERT, UPDATE czy DELETE. Przykład wypełniania nowej tablicy utworzonej poleceniem: CREATE TABLE zam_tymczas ( imie VARCHAR(20), nazwisko VARCHAR(30), wartosc DECIMAL(7,2) ); wartościami z wcześniejszych tabel klienci i zamowienia według schematu INSERT INTO tablica (kolumny) ( SELECT kolumny_podzapytania FROM tablice_podzapytania WHERE warunki_podzapytania );
Podzapytania w instrukcjach aktualizujacych dane (INSERT INTO). Przykład: INSERT INTO zam_tymczas (imie, nazwisko, wartosc) (SELECT imie, nazwisko, wartosc FROM klienci, zamowienia WHERE klienci.id = zamowienia.klient_id ); wstawi do tabeli wartość zamówienia dla każdego klienta i zamówienia Przykład: INSERT INTO zam_tymczas (imie, nazwisko, wartosc) ( SELECT imie, nazwisko, SUM(wartosc) AS wartosc FROM klienci, zamowienia WHERE klienci.id = zamowienia.klient_id GROUP BY klient_id, imie, nazwisko ); wstawi min. wartość sumaryczna zamówień dla każdego klienta.
Podzapytania w instrukcjach aktualizujacych dane (DELETE). Można przykładowo usunąć z tabeli zam_tymczas takie zamówienia których wartość jest mniejsza niż średnia wartość zamówień w tabeli zamowienia DELETE FROM zam_tymczas WHERE wartosc < ( SELECT AVG(wartosc) FROM zamowienia );
Transakcje Transakcja to zbiór operacji na bazie danych, które stanowią logiczną całość i albo mogą być wykonywane wszystkie, albo żadna z nich. Najczęściej spotykaną transakcją jest przelew. W przykładach można użyć tabeli konta przechowującej informację o stanie kont o strukturze: konta id id_osoby saldo gdzie id - klucz główny, id_osoby klucz obcy (id właściciela konta), saldo stan konta Utworzonej przez: CREATE TABLE konta ( id INTEGER PRIMARY_KEY, id_osoby INTEGER NOT NULL, saldo DECIMAL(7,2) NOT NULL );
Transakcje i wypełnionej przykładowymi danymi: INSERT INTO konta VALUES (1, 1, 120.00); INSERT INTO konta VALUES (2, 2, 30.00); Przelew o wysokości 40 zł można wykonać przez dwie operacje: UPDATE konta SET saldo = saldo 40 WHERE id = 1; UPDATE konta SET saldo = saldo + 40 WHERE id = 2; Przelew nie powinien dojść do skutku jeśli między jedną instrukcją UPDATE a drugą nastąpi jakakolwiek awaria. Transakcja składa się z trzech etapów: - rozpoczęcie transakcji (START TRANSACTION) - wykonanie instrukcji składających się na transakcję - zatwierdzenie transakcji (COMMIT)
Transakcje Przykład: START TRANSACTION; UPDATE konta SET saldo = saldo 40 WHERE id = 1; UPDATE konta SET saldo = saldo + 40 WHERE id = 2; COMMIT; Wycofanie (odwołanie) transakcji następuję za pomocą polecenia ROLLBACK (zamiast COMMIT): START TRANSACTION; instrukcje wchodzące w skład transakcji ROLLBACK; Należy pamiętać, że transakcja zachodzi dopiero w momencie wykonania polecenia COMMIT.
Więzy integralności Mając w bazie dwie tabele (np. pracownicy i stanowiska) powiązane za pomocą klucza obcego (np. stanowisko_id) np. o strukturach: pracownicy id imie nazwisko placa stanowisko_id pesel stanowiska id nazwa łatwo popełnić pomyłkę powodującą brak identyfikatora występującego w powiązaniu (np. brak odpowiedniego id w tabeli stanowiska)- brak spójności danych w bazie. Możemy spowodować aby serwer sam sprawdzał spójność o ile odpowiednio zdefiniujemy więzy integralności. Więzy integralności wprowadzamy przez jawne zdefiniowanie klucza obcego przy tworzeniu tablicy przez konstrukcję: [CONSTRAINT nazwa] FOREIGN KEY (kolumna1, kolumna2,, kolumnan) REFERENCES nazwa_tabeli (kolumna1, kolumna2,, kolumnan) gdzie nazwa to nazwa ograniczenia, nazwa_tabeli to tabela z której pochodzi klucz obcy, zaś kolumny po REFERECES mówią z których kolumn pochodzi klucz obcy.
Więzy integralności Przykład: CREATE TABLE pracownicy ( id INTEGER PRIMARY KEY, imie VARCHAR(20) NOT NULL, nazwisko VARCHAR(30) NOT NULL, placa DECIMAL(7,2) NOT NULL, stanowisko_id INTEGER, pesel CHAR(11), CONSTRAINT stanowiska_fk FOREIGN KEY (stanowisko_id) REFERENCES stanowiska(id) );
Więzy integralności Więzy integralności można dodawać do i usuwać z istniejących tabel zgodnie z przepisem: ALTER TABLE nazwa_tabeli ADD/DROP [CONTRAINT nazwa] FOREIGN KEY (kolumna1, kolumna2,, kolumnan) REFERECES nazwa_tabeli (kolumna1, kolumna2,, kolumnan) Przykład: ALTER TABLE pracownicy ADD CONSTRAINT stanowiska_fk FOREIGN KEY (stanowisko_id) REFERENCES stanowiska(id); ALTER TABLE pracownicy DROP CONSTRAINT stanowiska_fk; lub ALTER TABLE pracownicy DROP FOREIGN KEY stanowiska_fk;