Do wykonywania operacji na bazie danych wykorzystamy skrypt napisany w języku Python oraz moduł sqlite3 przeznaczony do obsługi baz SQLite3.
Podstawy pracy z bazą danych z wykorzystaniem skryptów języka Python zostały omówione w e‑materiale Instrukcje wyszukiwania w języku SQL, etap IIIPkQh27XjUInstrukcje wyszukiwania w języku SQL, etap III.
Ponieważ pracujemy na bazie SQLite3, instrukcje SQL zamieszczone w tym e‑materiale możemy również wykonywać w:
Poznajmy zawartość bazy. W wybranym edytorze tworzymy pusty plik i wpisujemy do niego następujący kod:
Linia 1. import sqlite3.
Linia 3. def wykonaj podkreślnik zapytanie otwórz nawias okrągły zapytanie zamknij nawias okrągły dwukropek.
Linia 4. if zapytanie kropka count otwórz nawias okrągły apostrof średnik apostrof zamknij nawias okrągły zamknij nawias ostrokątny 1 dwukropek.
Linia 5. kursor kropka executescript otwórz nawias okrągły zapytanie zamknij nawias okrągły.
Linia 6. print otwórz nawias okrągły cudzysłów Liczba zmodyfikowanych rekordów dwukropek cudzysłów przecinek pol kropka total podkreślnik changes zamknij nawias okrągły.
Linia 7. else dwukropek.
Linia 8. kursor kropka execute otwórz nawias okrągły zapytanie zamknij nawias okrągły.
Linia 10. if kursor kropka rowcount zamknij nawias ostrokątny 0 dwukropek.
Linia 11. print otwórz nawias okrągły cudzysłów Liczba zmodyfikowanych rekordów dwukropek cudzysłów przecinek kursor kropka rowcount zamknij nawias okrągły.
Linia 12. else dwukropek.
Linia 13. dane znak równości kursor kropka fetchall otwórz nawias okrągły zamknij nawias okrągły.
Linia 14. for rekord in dane dwukropek.
Linia 15. print otwórz nawias okrągły asterysk rekord zamknij nawias okrągły.
Linia 16. print otwórz nawias okrągły cudzysłów Liczba zwróconych rekordów dwukropek cudzysłów przecinek len otwórz nawias okrągły dane zamknij nawias okrągły zamknij nawias okrągły.
Linia 18. baza znak równości apostrof uczniowie2 kropka db apostrof.
Linia 19. pol znak równości sqlite3 kropka connect otwórz nawias okrągły baza zamknij nawias okrągły kratka połączenie z bazą.
Linia 20. kursor znak równości pol kropka cursor otwórz nawias okrągły zamknij nawias okrągły kratka utworzenie obiektu kursora.
Linia 22. kwerenda znak równości cudzysłów SELECT name przecinek sql FROM sqlite podkreślnik master WHERE type znak równości apostrof table apostrof cudzysłów.
Linia 24. wykonaj podkreślnik zapytanie otwórz nawias okrągły kwerenda zamknij nawias okrągły.
Linia 25. pol kropka commit otwórz nawias okrągły zamknij nawias okrągły.
Linia 26. pol kropka close otwórz nawias okrągły zamknij nawias okrągły.
import sqlite3
def wykonaj_zapytanie(zapytanie):
if zapytanie.count(';') > 1:
kursor.executescript(zapytanie)
print("Liczba zmodyfikowanych rekordów:", pol.total_changes)
else:
kursor.execute(zapytanie)
if kursor.rowcount > 0:
print("Liczba zmodyfikowanych rekordów:", kursor.rowcount)
else:
dane = kursor.fetchall()
for rekord in dane:
print(*rekord)
print("Liczba zwróconych rekordów:", len(dane))
baza = 'uczniowie2.db'
pol = sqlite3.connect(baza) # połączenie z bazą
kursor = pol.cursor() # utworzenie obiektu kursora
kwerenda = "SELECT name, sql FROM sqlite_master WHERE type='table'"
wykonaj_zapytanie(kwerenda)
pol.commit()
pol.close()
Plik zapisujemy pod nazwą kw_uczniowie2.py w tym samym katalogu, w którym zapisaliśmy wcześniej bazę danych. Działanie większości instrukcji umieszczonych w skrypcie omówiliśmy na początku e‑materiału Instrukcje wyszukiwania w języku SQL, etap IIIPkQh27XjUInstrukcje wyszukiwania w języku SQL, etap III.
Wprowadziliśmy jednak kilka zmian. W funkcji wykonaj_zapytanie() instrukcja warunkowa if zapytanie.count(';') > 1: sprawdza, czy zmienna zapytanie zawiera więcej niż jeden znak średnika, który powinien kończyć każdą instrukcję SQL. Jeżeli tak będzie, użyta zostanie metoda executescript(), aby wykonać wiele instrukcji SQL po kolei, oraz właściwość total_changes połączenia, aby wypisać liczbę zmienionych rekordów.
Druga dodana instrukcja warunkowa if kursor.rowcount > 0: sprawdza właściwość rowcount obiektu kursorakursorkursora. Informuje ona, ile rekordów zostało zmienionych podczas transakcjitransakcjatransakcji. Transakcje rozpoczynane są dla każdego polecenia modyfikującego dane (INSERT, UPDATE, DELETE, REPLACE), które wykonywane jest przez metodę execute() lub executemany(). Jeżeli wartość rowcount będzie większa od zera, wypiszemy liczbę zmienionych rekordów. W przypadku zapytania SELECT właściwość ta równa będzie -1, wtedy wykonywany będzie dotychczasowy kod.
Na końcu skryptu dodaliśmy wywołanie dwóch metod obiektu reprezentującego połączenie z bazą. Pierwsza – commit() – potrzebna jest, aby zatwierdzić przeprowadzane w ramach transakcji zmiany. Druga metoda – close() – zamyka połączenie z bazą.
Polecenie 1
Uruchom skrypt kw_uczniowie2.py. Przeanalizuj wynik wykonania skryptu i opisz schemat bazy danychschemat bazyschemat bazy danych.
Końcowy komunikat widoczny po wykonaniu skryptu: Liczba zwróconych rekordów: 4 – oznacza, że kwerenda zwróciła cztery rekordy zawierające definicje w języku SQL czterech tabel zawartych w bazie.
Linia 1. uczniowie CREATE TABLE uczniowie otwórz nawias okrągły.
Linia 2. id podkreślnik ucz INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 3. nazwisko varchar otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL przecinek.
Linia 4. imie varchar otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL przecinek.
Linia 5. ulica varchar otwórz nawias okrągły 50 zamknij nawias okrągły NOT NULL przecinek.
Linia 6. nr podkreślnik domu varchar otwórz nawias okrągły 25 zamknij nawias okrągły NOT NULL przecinek.
Linia 7. klasa varchar otwórz nawias okrągły 2 zamknij nawias okrągły NOT NULL.
Linia 8. zamknij nawias okrągły.
uczniowie CREATE TABLE uczniowie (
id_ucz INTEGER PRIMARY KEY AUTOINCREMENT,
nazwisko varchar(30) NOT NULL,
imie varchar(30) NOT NULL,
ulica varchar(50) NOT NULL,
nr_domu varchar(25) NOT NULL,
klasa varchar(2) NOT NULL
)
W wewnętrznej tabeli SQLite sqlite_sequence, która tworzona jest podczas pierwszego wystąpienia pola typu AUTOINCREMENT, zapisywane są informacje dotyczące pól kluczy głównych automatycznie inkrementowanych.
Linia 1. przedmioty CREATE TABLE przedmioty otwórz nawias okrągły.
Linia 2. id podkreślnik prz INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 3. nazwa varchar otwórz nawias okrągły 20 zamknij nawias okrągły NOT NULL przecinek.
Linia 4. naucz podkreślnik nazw varchar otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL DEFAULT apostrof apostrof przecinek.
Linia 5. naucz podkreślnik imie varchar otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL DEFAULT apostrof apostrof.
Linia 6. zamknij nawias okrągły.
przedmioty CREATE TABLE przedmioty (
id_prz INTEGER PRIMARY KEY AUTOINCREMENT,
nazwa varchar(20) NOT NULL,
naucz_nazw varchar(30) NOT NULL DEFAULT '',
naucz_imie varchar(30) NOT NULL DEFAULT ''
)
nazwa, naucz_nazwa, naucz_imie – VARCHAR, dane tekstowe.
Linia 1. oceny CREATE TABLE oceny otwórz nawias okrągły.
Linia 2. id podkreślnik ucz INTEGER NOT NULL przecinek.
Linia 3. ocena DECIMAL otwórz nawias okrągły 2 przecinek 1 zamknij nawias okrągły NOT NULL przecinek.
Linia 4. data DATE NOT NULL przecinek.
Linia 5. id podkreślnik prz INTEGER NOT NULL przecinek.
Linia 6. FOREIGN KEY otwórz nawias okrągły id podkreślnik ucz zamknij nawias okrągły REFERENCES uczniowie otwórz nawias okrągły id podkreślnik ucz zamknij nawias okrągły przecinek.
Linia 7. FOREIGN KEY otwórz nawias okrągły id podkreślnik prz zamknij nawias okrągły REFERENCES przedmioty otwórz nawias okrągły id podkreślnik prz zamknij nawias okrągły zamknij nawias okrągły.
oceny CREATE TABLE oceny (
id_ucz INTEGER NOT NULL,
ocena DECIMAL (2, 1) NOT NULL,
data DATE NOT NULL,
id_prz INTEGER NOT NULL,
FOREIGN KEY (id_ucz) REFERENCES uczniowie (id_ucz),
FOREIGN KEY (id_prz) REFERENCES przedmioty (id_prz))
W tabeli oceny występują pola:
id_ucz, id_prz – INTEGER, klucze obce, identyfikatory ucznia i przedmiotu,
ocena – DECIMAL, pole zawierające ocenę,
data – DATE, pole przechowujące datę wystawienia oceny w formacie ISO8601 „YYYY‑MM‑DD”.
Tabele uczniowie i przedmioty łączy relacja wiele‑do‑wielu definiowana przez relacje jeden‑do‑wielu każdej z tych tabel z tabelą oceny, w której zgromadzono informacje o ocenach każdego ucznia z różnych przedmiotów.
RZ7c1IlEUtAXo
Zrzut ekranu z programu LibreOffice Base. Przedstawia relacje między trzema tabelami. Tabela uczniowie zawiera pola id_ucz, nazwisko, imie, ulica, dom, id_klasy. Tabela oceny zawiera pola: id, id_ucz, icena, data, id_przedm. Tabela przedmioty zawiera id_przedm, nazwa_przedm, nazwisko_naucz, imie_naucz. Pola id_ucz tabel uczniowie oraz oceny połączono linią. Nad linią przy tabeli uczniowie jest cyfra 1, a przy tabeli oceny litera n. Pola id_przed tabel oceny oraz przedmioty połączono linią. Nad linią przy tabeli oceny jest litera n, a przy tabeli oceny cyfra 1.
Widok tabel, pól i relacji w bazie uczniowie2.
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.
Zanim zaczniemy wprowadzać zmiany wykonujemy po kolei proste zapytania wybierające dane z tabeli uczniowie:
Linia 1. SELECT asterysk FROM uczniowie ORDER BY nazwisko LIMIT 5 średnik.
SELECT * FROM uczniowie ORDER BY nazwisko LIMIT 5;
oraz:
Linia 1. SELECT asterysk FROM uczniowie ORDER BY ulica LIMIT 5 średnik.
SELECT * FROM uczniowie ORDER BY ulica LIMIT 5;
Ważne!
Zapytania SQL możemy umieszczać w skrypcie w zmiennej kwerenda, nadpisując poprzednią zawartość. Możemy też powielać instrukcję tworzącą zmienną kwerenda, wtedy wykonywane będzie ostatnie zapytanie, np.:
Linia 1. kwerenda znak równości cudzysłów SELECT name przecinek sql FROM sqlite podkreślnik master WHERE type znak równości apostrof table apostrof średnik cudzysłów.
Linia 2. kwerenda znak równości cudzysłów SELECT asterysk FROM uczniowie ORDER BY nazwisko LIMIT 5 średnik cudzysłów.
kwerenda = "SELECT name, sql FROM sqlite_master WHERE type='table';"
kwerenda = "SELECT * FROM uczniowie ORDER BY nazwisko LIMIT 5;"
Dla czytelności dłuższe zapytanie SQL można umieszczać w kilku wierszach przy użyciu potrójnych cudzysłowów, np.:
Linia 1. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 2. SELECT asterysk.
Linia 3. FROM uczniowie.
Linia 4. ORDER BY nazwisko.
Linia 5. LIMIT 5 średnik.
Linia 6. cudzysłów cudzysłów cudzysłów.
kwerenda = """
SELECT *
FROM uczniowie
ORDER BY nazwisko
LIMIT 5;
"""
Rekordy zwrócone przez pierwszą kwerendę:
Linia 1. 237 Aksamit Urszula Kosmiczna 51 2d.
Linia 2. 117 Augustyniak Jan Starzynskiego 50 1e.
Linia 3. 1 Baczynska Danuta Kiedrzynska 42 1a.
Linia 4. 149 Badenska Magdalena PCK 88 2a.
Linia 5. 180 Bak Krzysztof Bacewicza 59 2b.
Linia 6. Liczba zwróconych rekordów dwukropek 5.
237 Aksamit Urszula Kosmiczna 51 2d
117 Augustyniak Jan Starzynskiego 50 1e
1 Baczynska Danuta Kiedrzynska 42 1a
149 Badenska Magdalena PCK 88 2a
180 Bak Krzysztof Bacewicza 59 2b
Liczba zwróconych rekordów: 5
Rekordy zwrócone przez drugą kwerendę:
Linia 1. 35 Dawidson Grazyna Armii Krajowej 17 1b.
Linia 2. 56 Wasowicz Joanna Armii Krajowej 71 1b.
Linia 3. 75 Misiak Urszula Armii Krajowej 27 1c.
Linia 4. 118 Baranowska Ewelina Armii Krajowej 12 1e.
Linia 5. 119 Bator Ewelina Armii Krajowej 99 1e.
Linia 6. Liczba zwróconych rekordów dwukropek 5.
35 Dawidson Grazyna Armii Krajowej 17 1b
56 Wasowicz Joanna Armii Krajowej 71 1b
75 Misiak Urszula Armii Krajowej 27 1c
118 Baranowska Ewelina Armii Krajowej 12 1e
119 Bator Ewelina Armii Krajowej 99 1e
Liczba zwróconych rekordów: 5
Zmienianie danych
Wyniki kwerend pokazują, że w nazwiskach i nazwach ulic brak polskich liter. Pokażemy, w jaki sposób można usuwać tego typu problemy.
Zaczniemy od wykonania kopii tabeli uczniowie. W tym celu wykonujemy poniższe zapytanie:
Linia 1. CREATE TABLE uczniowie podkreślnik bak AS SELECT asterysk FROM uczniowie średnik.
CREATE TABLE uczniowie_bak AS SELECT * FROM uczniowie;
Instrukcja utworzy tabelę uczniowie_bak z wykorzystaniem danych pobranych z tabeli uczniowie, jednak po zakończeniu działania skryptu nic nie zobaczymy. Jeżeli chcemy sprawdzić, czy tabela z kopią danych została utworzona, możemy wykonać prostszą wersję pierwszej kwerendy, która wyświetli tylko nazwy tabel:
Linia 1. SELECT name FROM sqlite podkreślnik master średnik.
SELECT name FROM sqlite_master;
Przykład 1
Nazwiska uczniów i nazwy ulic w tabeli uczniowie nie mają polskich znaków.
Zasadnicze znaczenie w instrukcjach aktualizacyjnych i usuwających dane ma klauzula warunkowa, która decyduje o tym, które rekordy podlegają zmianom. Dobrą praktyką jest sprawdzanie precyzji wyrażeń warunkowych w kwerendzie wybierającej, np.:
Linia 1. SELECT asterysk FROM uczniowie WHERE ulica znak równości apostrof Starzynskiego apostrof średnik.
SELECT * FROM uczniowie WHERE ulica='Starzynskiego';
Dzięki wykonaniu kwerendy zobaczymy, ile rekordów zamierzamy zmienić. W tym przypadku będzie ich 17.
Do zmiany wartości pól w tabeli używamy klauzuli UPDATE. Z jej pomocą możemy aktualizować pojedyncze pola, np.:
Linia 1. UPDATE uczniowie SET ulica znak równości apostrof Starzyńskiego apostrof.
Linia 2. WHERE ulica znak równości apostrof Starzynskiego apostrof średnik.
UPDATE uczniowie SET ulica='Starzyńskiego'
WHERE ulica='Starzynskiego';
Powyższe zapytanie zmieni nazwę ulicy we wszystkich rekordach wybranych przez wyrażenie warunkowe w klauzuli WHERE. Po wykonaniu skryptu zobaczymy komunikat: Liczba zmodyfikowanych rekordów: 17.
Po zmianie danych zawsze można wykonać kwerendę wybierającą, aby sprawdzić zmodyfikowane rekordy. W klauzuli warunkowej podajemy wtedy wartości, które chcieliśmy w bazie zapisać.
Kwerenda sprawdzająca:
Linia 1. SELECT ulica FROM uczniowie WHERE ulica znak równości apostrof Starzyńskiego apostrof średnik.
SELECT ulica FROM uczniowie WHERE ulica='Starzyńskiego';
W wybranych rekordach możemy również zmieniać wartości w wielu polach na raz. Na początku sprawdźmy, ile rekordów zmienimy:
Linia 1. SELECT asterysk FROM uczniowie WHERE nazwisko znak równości apostrof Baczynska apostrof średnik.
SELECT * FROM uczniowie WHERE nazwisko='Baczynska';
Wynik zapytania pokaże, że jest tylko jedna osoba o podanym w warunku nazwisku. Możemy więc wykorzystać ten warunek w zapytaniu, które zmieni zawartość pól nazwisko i ulica:
Linia 1. UPDATE uczniowie.
Linia 2. SET nazwisko znak równości apostrof Baczyńska apostrof przecinek ulica znak równości apostrof Kiedrzyńska apostrof.
Linia 3. WHERE nazwisko znak równości apostrof Baczynska apostrof średnik.
UPDATE uczniowie
SET nazwisko='Baczyńska', ulica='Kiedrzyńska'
WHERE nazwisko='Baczynska';
Kwerenda sprawdzająca:
Linia 1. SELECT nazwisko przecinek ulica FROM uczniowie WHERE nazwisko znak równości apostrof Baczyńska apostrof średnik.
SELECT nazwisko, ulica FROM uczniowie WHERE nazwisko='Baczyńska';
Powyżej pokazaliśmy, jak wprowadzać polskie znaki w pojedynczych rekordach. W sekcji „Prezentacja multimedialna” zajmiemy się poprawianiem danych w wielu rekordach przy użyciu skryptu języka Python, formatu CSV i arkusza kalkulacyjnego.
Przykład 2
Uczennica Irena Bednarczyk zmieniła adres zamieszkania z „Mickiewicza 3” na „Słowackiego 23”. Zaktualizuj tę informację w bazie.
Ponieważ mamy więcej danych pozwalających jednoznacznie wybrać rekord z bazy przeznaczony do zmiany, użyjemy kwerendy wybierającej, aby uzyskać identyfikator uczennicy:
Linia 1. SELECT id podkreślnik ucz FROM uczniowie WHERE imie znak równości apostrof Irena apostrof AND nazwisko znak równości apostrof Bednarczyk apostrof AND ulica znak równości apostrof Mickiewicza apostrof średnik.
SELECT id_ucz FROM uczniowie WHERE imie='Irena' AND nazwisko='Bednarczyk' AND ulica='Mickiewicza';
Przygotowaną kwerendę użyjemy w klauzuli WHERE jako podzapytanie zwracające identyfikator rekordu, który chcemy zmienić:
Linia 1. UPDATE uczniowie.
Linia 2. SET ulica znak równości apostrof Słowackiego apostrof przecinek nr podkreślnik domu znak równości 23.
Linia 3. WHERE id podkreślnik ucz znak równości otwórz nawias okrągły.
Linia 4. SELECT id podkreślnik ucz FROM uczniowie.
Linia 5. WHERE imie znak równości apostrof Irena apostrof AND nazwisko znak równości apostrof Bednarczyk apostrof AND ulica znak równości apostrof Mickiewicza apostrof.
Linia 6. zamknij nawias okrągły średnik.
UPDATE uczniowie
SET ulica='Słowackiego', nr_domu=23
WHERE id_ucz=(
SELECT id_ucz FROM uczniowie
WHERE imie='Irena' AND nazwisko='Bednarczyk' AND ulica='Mickiewicza'
);
Po wykonaniu zapytania powinniśmy zobaczyć komunikat: Liczba zmodyfikowanych rekordów: 1.
Kwerenda sprawdzająca:
Linia 1. SELECT asterysk FROM uczniowie WHERE imie znak równości apostrof Irena apostrof AND nazwisko znak równości apostrof Bednarczyk apostrof AND ulica znak równości apostrof Słowackiego apostrof średnik.
SELECT * FROM uczniowie WHERE imie='Irena' AND nazwisko='Bednarczyk' AND ulica='Słowackiego';
Przykład 3
Częstą sytuacją jest przenoszenie się ucznia z klasy do klasy. Uczennica Monika Radzikowska przeszła z klasy „1a” do „1c” i powinniśmy zaktualizować odpowiedni wpis w bazie.
Na początku sprawdzamy, ile jest osób o podanym imieniu i nazwisku w odpowiedniej klasie.
Linia 1. SELECT COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły FROM uczniowie.
Linia 2. WHERE nazwisko znak równości apostrof Radzikowska apostrof AND imie znak równości apostrof Monika apostrof AND klasa znak równości apostrof 1a apostrof średnik.
SELECT COUNT(*) FROM uczniowie
WHERE nazwisko='Radzikowska' AND imie='Monika' AND klasa='1a';
Wynik zapytania to:
Linia 1. 1.
Linia 2. Liczba zwróconych rekordów dwukropek 1.
1
Liczba zwróconych rekordów: 1
Wartość 1 to wynik wykonanej kwerendy, komunikat „Liczba zwróconych rekordów: 1” mówi, że wynik został zwrócony w jednym rekordzie.
W przypadku, kiedy w bazie mamy uczniów o takich samych nazwiskach i/lub imionach (dodatkowo mogą być w tej samej klasie), nie możemy używać warunków opartych tylko na dopasowaniu nazwisk i imion. Żeby jednoznacznie wskazać ucznia, trzeba w klauzuli warunkowej odwołać się do innych danych, które mogą jednoznacznie identyfikować osobę, takich jak np. numer PESEL. W naszej bazie nie mamy takiego pola, musielibyśmy więc wykorzystać adres ucznia, czyli pola ulica i nr_domu.
Ponieważ w bazie jest tylko jedna uczennica o podanym imieniu i nazwisku, w kwerendzie zmieniającej klasę wykorzystamy więc taką samą klauzulę warunkową. Do zmiany zawartości pola użyjemy dla przykładu funkcji REPLACE():
Linia 1. UPDATE uczniowie SET klasa znak równości REPLACE otwórz nawias okrągły klasa przecinek apostrof a apostrof przecinek apostrof c apostrof zamknij nawias okrągły.
Linia 2. WHERE nazwisko znak równości apostrof Radzikowska apostrof AND imie znak równości apostrof Monika apostrof AND klasa znak równości apostrof 1a apostrof średnik.
UPDATE uczniowie SET klasa = REPLACE(klasa, 'a', 'c')
WHERE nazwisko='Radzikowska' AND imie='Monika' AND klasa='1a';
Składnia funkcji jest następująca: REPLACE(napis, stary_napis, nowy_napis). Funkcja pozwala zastąpić każde wystąpienie starego_napisu w napisienowym_napisem. Jako argument napis najczęściej podajemy pole tabeli zawierające dane tekstowe.
Po wykonaniu zapytania zobaczymy komunikat Liczba zmodyfikowanych rekordów: 1, który oznacza, że w bazie zmodyfikowany został jeden rekord.
Kwerenda sprawdzająca:
Linia 1. SELECT imie przecinek nazwisko przecinek klasa FROM uczniowie.
Linia 2. WHERE nazwisko znak równości apostrof Radzikowska apostrof AND imie znak równości apostrof Monika apostrof AND klasa znak równości apostrof 1c apostrof średnik.
SELECT imie, nazwisko, klasa FROM uczniowie
WHERE nazwisko='Radzikowska' AND imie='Monika' AND klasa='1c';
Przykład 4
Chcemy, żeby nazwy klas w tabeli uczniowie zapisane były wielkimi literami. Musimy zmienić zawartość wszystkich rekordów.
Kolejną funkcją, która pozwala manipulować zapisanymi w bazie danymi, jest funkcja UPPER(). Jej zadaniem jest zamiana ciągu znaków na wielkie litery. Wykonajmy przykładowe zapytanie, które zwróci nazwy klas wypisane wielkimi literami:
Linia 1. SELECT UPPER otwórz nawias okrągły klasa zamknij nawias okrągły FROM uczniowie średnik.
SELECT UPPER(klasa) FROM uczniowie;
Omawianej funkcji możemy użyć w zapytaniu, które zmieni nazwy klas na wielkie litery we wszystkich rekordach:
Linia 1. UPDATE uczniowie SET klasa znak równości UPPER otwórz nawias okrągły klasa zamknij nawias okrągły średnik.
UPDATE uczniowie SET klasa = UPPER(klasa);
Po wykonaniu zapytania zobaczymy komunikat: Liczba zmodyfikowanych rekordów: 414
Kwerenda sprawdzająca:
Linia 1. SELECT DISTINCT klasa FROM uczniowie średnik.
SELECT DISTINCT klasa FROM uczniowie;
Inne przydatne funkcje służące do manipulowania danymi tekstowymi, które można wykorzystać w zapytaniach zmieniających dane, to:
SUBSTR(napis, początek, liczba_znaków) – zwraca podaną liczbę znaków, zaczynając od znaku znajdującego się na pozycji początek w napisie, pierwszy znak ma pozycję równą 1.
Przykłady użycia:
SELECT LOWER(SUBSTR(nazwisko, 1, 3)) FROM uczniowie; – zapytanie zwróci pierwsze trzy znaki z każdego nazwiska zapisane małymi literami,
SELECT SUBSTR(nazwisko, 3) FROM uczniowie; – zapytanie zwróci wszystkie znaki z każdego nazwiska, zaczynając od trzeciego znaku,
SELECT SUBSTR(nazwisko, -3) FROM uczniowie; – zapytanie zwróci ostatnie trzy litery z każdego nazwiska,
SELECT SUBSTR(nazwisko, -1, -3) FROM uczniowie; – zapytanie zwróci trzy znaki z każdego nazwiska poprzedzające pierwszy znak od końca.
Usuwanie danych
Przykład 5
W bazie znalazły się niepotrzebne oceny, chcemy je usunąć.
Ćwiczenie 1
Przygotuj i wykonaj zapytanie, które stworzy kopię tabeli oceny pod nazwą oceny_bak.
Linia 1. CREATE TABLE oceny podkreślnik bak AS SELECT asterysk FROM oceny średnik.
CREATE TABLE oceny_bak AS SELECT * FROM oceny;
Po wykonaniu zapytania zobaczymy komunikat Liczba zwróconych rekordów: 0, ponieważ klauzula CREATE nie zmienia i nie wybiera żadnych rekordów tylko tworzy tabelę. Można się o tym przekonać, wykonując zapytanie:
Linia 1. SELECT name przecinek sql FROM sqlite podkreślnik master średnik.
SELECT name, sql FROM sqlite_master;
Z tabeli oceny wybierzemy wszystkie rekordy i posortujemy je malejąco według pola data:
Linia 1. SELECT asterysk FROM oceny ORDER BY data średnik.
SELECT * FROM oceny ORDER BY data;
Po przejrzeniu ostatnich zwróconych rekordów zauważymy, że niektóre oceny zostały wystawione niekoniecznie w czasie trwania roku szkolnego. Spróbujmy ustalić to dokładniej:
Linia 1. SELECT asterysk FROM oceny WHERE strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły zamknij nawias ostrokątny apostrof 06 apostrof AND strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły otwórz nawias ostrokątny apostrof 09 apostrof średnik.
SELECT * FROM oceny WHERE strftime('%m', data) > '06' AND strftime('%m', data) < '09';
Kwerenda wykorzystuje funkcję strftime(), która zwraca datę lub jej składnik w podanym jako pierwszy argument formacie. W tym przypadku ciąg %m oznacza miesiąc zapisany jako wartość tekstowa za pomocą dwóch cyfr. Jeżeli chcielibyśmy traktować miesiące jako wartości liczbowe, należałoby użyć następującego zapytania:
Linia 1. SELECT CAST otwórz nawias okrągły strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły AS INTEGER zamknij nawias okrągły AS miesiac przecinek asterysk.
Linia 2. FROM oceny.
Linia 3. WHERE miesiac zamknij nawias ostrokątny 6 AND miesiac otwórz nawias ostrokątny 9 średnik.
SELECT CAST(strftime('%m', data) AS INTEGER) AS miesiac, *
FROM oceny
WHERE miesiac > 6 AND miesiac < 9;
Instrukcja CAST(wyrażenie AS typ) przekształca wyrażenie na podany typ, w tym wypadku liczbę całkowitą (INTEGER).
Po wykonaniu któregoś z zapytań dowiemy się, że ocen wystawionych w lipcu i sierpniu jest 63.
Przyjmijmy, że oceny wystawiono błędnie i należy je usunąć. Wykorzystamy instrukcję DELETE, która usuwa wszystkie rekordy pasujące do wyrażenia warunkowego. My już takie wyrażenie mamy, możemy więc wykonać polecenie:
Linia 1. DELETE FROM oceny WHERE strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły zamknij nawias ostrokątny apostrof 06 apostrof AND strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły otwórz nawias ostrokątny apostrof 09 apostrof średnik.
DELETE FROM oceny WHERE strftime('%m', data) > '06' AND strftime('%m', data) < '09';
Po wykonaniu zapytania zobaczymy komunikat: Liczba zmodyfikowanych rekordów: 63.
Po usunięciu danych możemy sprawdzić, czy operacja się udała, wykonując kwerendę wybierającą z taką samą klauzulą warunkową, jaką zawierała kwerenda usuwająca. Oczekiwanym wynikiem jest komunikat: Liczba zwróconych rekordów: 0
Kwerenda sprawdzająca:
Linia 1. SELECT asterysk FROM oceny WHERE strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły zamknij nawias ostrokątny apostrof 06 apostrof AND strftime otwórz nawias okrągły apostrof procent m apostrof przecinek data zamknij nawias okrągły otwórz nawias ostrokątny apostrof 09 apostrof średnik.
SELECT * FROM oceny WHERE strftime('%m', data) > '06' AND strftime('%m', data) < '09';
Przykład 6
Chcemy usunąć z bazy danych informacje o uczniach o nazwisku „Cygan”.
Usuwanie ocen z tabeli oceny nie pociąga za sobą konieczności zmiany danych w pozostałych tabelach. Inaczej rzecz wygląda w przypadku usuwania z bazy danych ucznia lub uczniów. Ponieważ w tabeli oceny mogą występować powiązane dane, w celu zachowania spójności, powinniśmy również zadbać o ich usunięcie.
W dobrze zaprojektowanej bazie danych za usuwanie powiązanych danych odpowiadają ograniczenia nakładane podczas definiowania kluczy obcych. Co się zatem stanie, jeżeli usuniemy ucznia?
Sprawdźmy, ilu uczniów dotyczy operacja:
Linia 1. SELECT id podkreślnik ucz przecinek imie przecinek nazwisko FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof średnik.
SELECT id_ucz, imie, nazwisko FROM uczniowie WHERE nazwisko = 'Cygan';
i czy uczniowie mają jakieś oceny:
Linia 1. SELECT COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły FROM oceny WHERE id podkreślnik ucz IN otwórz nawias okrągły 4 przecinek 5 zamknij nawias okrągły średnik.
SELECT COUNT(*) FROM oceny WHERE id_ucz IN (4, 5);
Pierwsza kwerenda zwróci podane niżej dane dwóch uczniów, a druga wartość 65, która oznacza liczbę ocen powiązanych z uczniami w tabeli oceny.
Linia 1. 4 Aneta Cygan.
Linia 2. 5 Henryka Cygan.
Linia 3. Liczba zwróconych rekordów dwukropek 2.
4 Aneta Cygan
5 Henryka Cygan
Liczba zwróconych rekordów: 2
Ważne!
W bazach SQLite3 ograniczenia kluczy obcych definiowane w klauzulach FOREIGN KEY domyślnie są wyłączone. Oznacza to, że dane usuwane są bez sprawdzania, czy w tabelach zależnych znajdują się jakieś powiązane informacje.
Zobaczmy, co się stanie, kiedy przed kwerendą usuwającą dane uczniów wykonamy zapytanie PRAGMA foreign_keys = ON;, które włącza sprawdzanie ograniczeń kluczy obcych dla aktualnego połączenia z bazą.
Oba zapytania umieszczamy w zmiennej kwerenda, aby zostały wykonane po kolei przez metodę executescript():
Linia 1. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 2. PRAGMA foreign podkreślnik keys znak równości ON średnik.
Linia 3. DELETE FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof średnik.
Linia 4. cudzysłów cudzysłów cudzysłów.
kwerenda = """
PRAGMA foreign_keys = ON;
DELETE FROM uczniowie WHERE nazwisko = 'Cygan';
"""
Po wykonaniu skryptu zobaczymy komunikat kończący się w następujący sposób:
Oznacza on, że podczas próby wykonania zapytania usuwającego wystąpił błąd spójności sqlite3.IntegrityError, który związany jest z naruszeniem ograniczeń klucza obcego. System bazodanowy nie pozwala usunąć danych z tabeli uczniowie, ponieważ – jak wiemy – w tabeli oceny zostałyby „osierocone” rekordy.
Usuwanie danych powiązanych
Są dwie możliwości rozwiązania takiego problemu. Można:
najpierw usunąć dane z tabeli powiązanej (oceny), później z tabeli głównej (uczniowie),
lub zdefiniować ograniczenie ON DELETE CASCADE (ewentualnie ON DELETE SET NULL) na kluczu obcym id_ucz w tabeli powiązanej (oceny).
Sprawdźmy pierwszą możliwość. Wykonamy zapytanie:
Linia 1. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 2. DELETE FROM oceny WHERE id podkreślnik ucz IN otwórz nawias okrągły SELECT id podkreślnik ucz FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof zamknij nawias okrągły średnik.
Linia 3. DELETE FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof średnik.
Linia 4. cudzysłów cudzysłów cudzysłów.
kwerenda = """
DELETE FROM oceny WHERE id_ucz IN (SELECT id_ucz FROM uczniowie WHERE nazwisko = 'Cygan');
DELETE FROM uczniowie WHERE nazwisko = 'Cygan';
"""
W kwerendzie korzystamy z podzapytania SELECT do stworzenia listy identyfikatorów uczniów, którą wyrażenie warunkowe wykorzystuje do wyznaczenia rekordów tabeli oceny przeznaczonych do usunięcia. Po wykonaniu kwerendy zobaczymy komunikat: Liczba zmodyfikowanych rekordów: 67.
Warto zauważyć, że nawet gdybyśmy włączyli sprawdzanie ograniczeń klucza obcego, powyższe kwerendy usunęłyby dane.
Kwerenda sprawdzająca:
Linia 1. SELECT asterysk FROM oceny WHERE id podkreślnik ucz IN otwórz nawias okrągły SELECT id podkreślnik ucz FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof zamknij nawias okrągły średnik.
SELECT * FROM oceny WHERE id_ucz IN (SELECT id_ucz FROM uczniowie WHERE nazwisko = 'Cygan');
Ciekawostka
Innym niż wykorzystana w skrypcie właściwość rowcount sposobem na uzyskanie informacji o liczbie zmodyfikowanych rekordów jest wykonanie w ramach tego samego połączenia z bazą zapytania:
Zanim sprawdzimy drugie rozwiązanie przywrócimy usunięte rekordy za pomocą zapytań wykorzystujących utworzone kopie tabel:
Linia 1. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 2. PRAGMA foreign podkreślnik keys znak równości 0 średnik.
Linia 3. INSERT INTO uczniowie SELECT asterysk FROM uczniowie podkreślnik bak WHERE nazwisko znak równości apostrof Cygan apostrof średnik.
Linia 4. INSERT INTO oceny SELECT asterysk FROM oceny podkreślnik bak WHERE id podkreślnik ucz IN otwórz nawias okrągły 4 przecinek 5 zamknij nawias okrągły średnik.
Linia 5. cudzysłów cudzysłów cudzysłów.
kwerenda = """
PRAGMA foreign_keys = 0;
INSERT INTO uczniowie SELECT * FROM uczniowie_bak WHERE nazwisko = 'Cygan';
INSERT INTO oceny SELECT * FROM oceny_bak WHERE id_ucz IN (4, 5);
"""
Drugie rozwiązanie wymaga zmodyfikowania struktury tabeli oceny, co ze względu na niepełną obsługę polecenia ALTER TABLE w SQLite, służącego do modyfikowania struktury tabel, będzie wymagało wykonania kilku dodatkowych operacji.
Linia 1. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 2. CREATE TABLE oceny podkreślnik temp podkreślnik table AS SELECT asterysk FROM oceny średnik.
Linia 3. DROP TABLE oceny średnik.
Linia 4. CREATE TABLE oceny otwórz nawias okrągły.
Linia 5. id podkreślnik ucz INTEGER NOT NULL przecinek.
Linia 6. ocena DECIMAL otwórz nawias okrągły 2 przecinek 1 zamknij nawias okrągły NOT NULL przecinek.
Linia 7. data DATE NOT NULL przecinek.
Linia 8. id podkreślnik prz INTEGER NOT NULL przecinek.
Linia 9. FOREIGN KEY otwórz nawias okrągły id podkreślnik ucz zamknij nawias okrągły REFERENCES uczniowie otwórz nawias okrągły id podkreślnik ucz zamknij nawias okrągły ON DELETE CASCADE przecinek.
Linia 10. FOREIGN KEY otwórz nawias okrągły id podkreślnik prz zamknij nawias okrągły REFERENCES przedmioty otwórz nawias okrągły id podkreślnik prz zamknij nawias okrągły ON DELETE CASCADE.
Linia 11. zamknij nawias okrągły średnik.
Linia 12. INSERT INTO oceny SELECT asterysk FROM oceny podkreślnik temp podkreślnik table średnik.
Linia 13. DROP TABLE oceny podkreślnik temp podkreślnik table średnik.
Linia 14. cudzysłów cudzysłów cudzysłów.
kwerenda = """
CREATE TABLE oceny_temp_table AS SELECT * FROM oceny;
DROP TABLE oceny;
CREATE TABLE oceny (
id_ucz INTEGER NOT NULL,
ocena DECIMAL (2, 1) NOT NULL,
data DATE NOT NULL,
id_prz INTEGER NOT NULL,
FOREIGN KEY (id_ucz) REFERENCES uczniowie (id_ucz) ON DELETE CASCADE,
FOREIGN KEY (id_prz) REFERENCES przedmioty (id_prz) ON DELETE CASCADE
);
INSERT INTO oceny SELECT * FROM oceny_temp_table;
DROP TABLE oceny_temp_table;
"""
Przeanalizujmy po kolei polecenia:
pierwsze polecenie CREATE tworzy tymczasową kopię tabeli oceny pod nazwą oceny_temp_table,
polecenie DROP TABLE oceny; usuwa tabelę oceny,
drugie polecenie CREATE ponownie tworzy tabelę oceny, za pomocą ograniczenia ON DELETE CASCADE wskazujemy, że w przypadku usunięcia kluczy głównych id_ucz lub id_prz powiązane rekordy w tabeli oceny mają być automatycznie usuwane,
polecenie INSERT przywraca dane do tabeli oceny z utworzonej tabeli tymczasowej,
ostatnie polecenie DROP usuwa tymczasową kopię.
Po wykonaniu zapytań zobaczymy komunikat: Liczba zmodyfikowanych rekordów: 16902.
Teraz możemy jeszcze raz wykonać polecenie usuwające dane uczniów przy włączonych regułach kluczy obcych:
Linia 1. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 2. PRAGMA foreign podkreślnik keys znak równości ON średnik.
Linia 3. DELETE FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof średnik.
Linia 4. cudzysłów cudzysłów cudzysłów.
kwerenda = """
PRAGMA foreign_keys = ON;
DELETE FROM uczniowie WHERE nazwisko = 'Cygan';
"""
Po wykonaniu skryptu zobaczymy komunikat Liczba zmodyfikowanych rekordów: 67, który oznacza, że dane z tabeli powiązanej zostały usunięte automatycznie.
Kwerenda sprawdzająca:
Linia 1. SELECT asterysk FROM oceny WHERE id podkreślnik ucz IN otwórz nawias okrągły SELECT id podkreślnik ucz FROM uczniowie WHERE nazwisko znak równości apostrof Cygan apostrof zamknij nawias okrągły średnik.
SELECT * FROM oceny WHERE id_ucz IN (SELECT id_ucz FROM uczniowie WHERE nazwisko = 'Cygan');
Już wiesz
W bazach SQLite3 należy wprost włączać ograniczenia kluczy obcych (jeżeli mają być respektowane) za pomocą zapytania: PRAGMA foreign_keys = ON;.
Podczas projektowania bazy danych należy przeanalizować, w jaki sposób będą usuwane z niej dane i nałożyć na pola kluczy obcych odpowiednie ograniczenia ON DELETE.
Słowniczek
kursor
kursor
(ang. cursor) obiekt pozwalający komunikować się z bazą danych (czyli wykonywać zapytania SQL), a także umożliwiający pobieranie kolejnych zwróconych przez zapytania rekordów
schemat bazy
schemat bazy
schematyczny opis tabel (zwanych encjami), ich atrybutów (pól, kolumn) oraz typów danych, a także związków między tabelami, czyli relacji
transakcja
transakcja
uporządkowany zbiór operacji na bazie danych traktowany jako całość, wszystkie operacje muszą zostać poprawnie wykonane albo żadna z nich nie dochodzi do skutku i stan bazy nie ulega zmianie