Projektowanie i programowanie aplikacji biznesowych wykład 1 1
Baza danych SQLite Autorem biblioteki SQLite jest Richard Hipp z firmy Hwaci - Applied Software Research. Pierwsza wersja tego oprogramowania powstała we wrześniu 2001 roku. SQLite jest biblioteką oprogramowania, która implementuję samodzielną i bezserwerową, nie wymagający konfiguracji mechanizm bazy danych SQL. Kod źródłowy dla SQLite znajduje się w domenie publicznej (public domain). Baza danych SQLite jest obecnie bardzo popularna i jest użytkowana w setkach milionów egzemplarzy na całym świecie. SQLite jest używany w systemie Solaris 10 i MAC OS, iphone i Skype. Biblioteka Qt4 ma wbudowane wsparcie dla SQLite, tak samo jak Python czy PHP. Wiele popularnych aplikacji ma wbudowaną bazę SQLite do obsługi wewnętrznej takie jak Firefox czy Amarok. SQLite ma w większości zaimplementowany standard SQL-92. Silnik SQLite nie tworzy samodzielnego procesu dla bazy. Zamiast tego jest statycznie lub dynamicznie dołączany do aplikacji. Biblioteka SQLite ma niewielkie rozmiary około 470 kb. Baza danych SQLite to pojedynczy plik na dysku, który można umieścić w dowolnym miejscu w hierarchii katalogów. Może być stosowany na różnych systemach operacyjnych, zarówno 32 jak 64 bitowych. Biblioteka SQLite została napisana w języku C. Implementuje ona pełny silnik bazodanowy. Jej główną zaletą, odróżniająca ją od podobnych rozwiązań, jest to, iż umożliwia wykorzystanie języka SQL do komunikacji z bazą. Przeznaczona została głównie dla programistów C/C++. Oferuje prosty interfejs obsługi dla tych właśnie języków. Nie ma jednak żadnych przeciwwskazań, aby programiści używający innych języków programowania (np. Delphi, Visual Basic czy PHP) nie mogli z niej skorzystać. Gwarantuje to fakt, że SQLite jest dostępna również w postaci biblioteki dll. 2
SQLite wstęp Biblioteka SQLite pozwala na używanie bazy danych bez konieczności uruchamiania oddzielnego procesu jat to ma miejsce na przykład w przypadku MySQL. Zwartość bazy danych jest przetrzymywana w jednym pliku binarnym. SQlite rozwiązuje odwieczny problem programistów przechowujących dane w plikach płaskich, a mianowicie blokowanie i dostęp współbieżny. Głównym plusem tej bazy wydajność szczególnie przy wykonywaniu zapytań typu INSERT i SELECT, a także wieloplatformowość. Niestety nie jest to rozwiązanie wolne od wad. Podczas procesu dopisywania nowych danych SQLite musi zablokować cały plik, aż do czasu zakończenia operacji. Zatem rozwiązanie to nie jest wydajne w sytuacjach gdy dane podlegają ciągłym zmianom. Drugim poważnym minusem jest brak pojęcia praw dostępu do bazy danych(znanym chociażby z MySQL a), przez co nie możemy stworzyć bezpiecznej tabeli do której dostęp mieliby tylko uprawnieni użytkownicy. W skrócie oznacza to, że musimy sami stworzyć system kontroli dostępu, poprzez nadawanie praw do zapisu i odczytu odpowiednim plikom. Rozwiązanie takie nie jest wygodne. Podsumowując SQLite nie nadaje się do zastosowań na witrynach gdzie dane podlegają ciągłym zmianom, a także tam gdzie jest wymagany system kontroli dostępu. Jednak na małych i średnich stronach rozwiązanie to może okazać się naprawdę wydajne. W końcu do stworzenia tabeli z kilkunastoma rekordami nie potrzeba całego kombajna jakim jest niewątpliwie MySQL. 3
SQLite Początek Relacyjna baza danych jest zbiorem danych zorganizowanych w tablicach. Pomiędzy tabelami mogą istnieć relacje. Tabele są formalnie opisane/ Tabele składają się z wierszy i kolumn. SQL (Structured Query Language) jest językiem zapytań do bazy danych przeznaczony do zarządzania danymi w relacyjnych systemach zarządzania bazami danych. Tabela jest zbiorem wartości, które są zorganizowane za pomocą modelu pionowych kolumn i poziomych wierszy. Kolumny są identyfikowane przez ich nazwy. Schemat systemu bazy danych i jego struktura są opisana w oficjalnym języku. Określa on tabele, pola, relacje, widoki, indeksy, procedury, funkcjie, kolejki, wyzwalacze i inne elementy. Wiersz bazy danych reprezentuje pojedynczy, pośrednio zorganizowany element danych w tabeli. Jest również nazywany krotką lub rekordem. Kolumna jest zestawem wartości danych konkretnego typu, po jednym dla każdego wiersza tabeli. Kolumny zapewniają strukturę, na którą składają się wiersze. Pole jest to pojedynczy element, który istnieje na przecięciu między wierszem i kolumną. Klucz główny jednoznacznie identyfikuje każdy rekord w tabeli. Klucz obcy służy do połączenia więzów między dwiema tabelami. Klucz obcy identyfikuje kolumnę lub zestaw kolumn w jednej (odnośników) tabeli, która odwołuje się do kolumny lub zestawu kolumn w innej (sygnatura) tabeli. Wyzwalany jest proceduralny kod, który jest wykonywany automatycznie w odpowiedzi na określone zdarzenia na konkretnej tabeli w bazie danych. Widok jest to specyficzne spojrzenie na dane w jednej lub kilku tabelach. To zapytanie może zorganizować dane w pewnym określonej kolejności, lub ukryć niektóre dane. 4
Widok składa się z przechowywanego zapytania dostępnego w wirtualnej tabeli składającej się z zestawu wyników kwerendy. W przeciwieństwie do zwykłych tabel widok nie jest częścią fizycznego schematu bazy danych. Jest dynamiczną, wirtualną tabela zawierającą obliczenia lub zestaw z danymi w bazie danych. Transakcja jest autonomiczną jednostką operującą na danych w jednej lub kilku baz danych. Wyniki wszystkich instrukcji SQL w transakcjach mogą być zapisane w bazie danych i mogą być ponownie wykonane. Zestaw wyników SQL jest zbiorem wierszy z bazy danych, zwróconych przez instrukcję SELECT. Zawiera także meta-informacje o zapytaniu, takie jak nazwy kolumn, a także rodzaj i rozmiary każdej kolumny. Indeks jest strukturą danych, która zwiększa szybkość operacji pobierania danych z tabeli bazy danych. Źródło opisu: http://uazz.pl/index.php/kurs-sqlite Narzędzie sqlite3 Biblioteka SQLite zawiera proste narzędzie wiersza poleceń o nazwie sqlite3 (lub sqlite3.exe dla systemów Windows), które pozwala użytkownikowi ręcznie wpisywać i wykonywać polecenia SQL na bazie danych SQLite. 5
SQLite w środowisku Dev C++ Pierwszym krokiem jest pobranie odpowiednich plików (sqlite3.c i sqlite3.h) ze strony www.sqlite.org (w typ przypadku pobrano plik sqlite-amalgamation-3080301.zip). 6
Pobrane pliki umieszczamy w odpowiednim miejscu na dysku (np. w katalogu Dev_Cpp) 7
Następnie ze strony www.sqlite.org pobieramy plik zawierający narzędzie sqlite3.exe (w typ przypadku pobrano plik sqlite-shell-win32-x86-3080301.zip). Plik sqlite3.exe umieszczamy w wybranej lokalizacji (w typ przypadku został umieszczony w katalogu Dev-Cpp - dla uproszczenia przykładu). 8
9
W efekcie powyższych operacji wszystkie pobrane pliki zostały zapisane w katalogu Dev-Cpp. 10
Zanim będziemy mogli wykorzystać bibliotekę sqlite.h najpierw musimy stworzyć odpowiednią infrastrukturę czyli utworzyć bibliotekę statyczną. W tym celu uruchamiamy aplikację Dev-C++ a w ramach nowego projektu wybieramy opcję Static Library (uwaga należy zaznaczyć opcję projekt C) oraz nazywamy nasz projekt (np. Proj_Biblio_SQLITE). 11
Zapisujemy projekt w katalogu Dec-Cpp 12
Kolejnym krokiem jest dołączenie do projektu odpowiednich plików. 13
14
Ostatnim krokiem jest kompilacja. 15
Produktem finalnym jest plik Proj_Biblio_SQLITE.a, który zawszę będzie dołączany do projektów wykorzystujących sqlite.h. 16
Narzędzie sqlite3.exe Pierwszym krokiem jest uruchomienie konsoli, w ramach której przechodzimy do katalogu zawierającego plik sqlite.exe. 17
Jako parametr podajemy nazwę pliku, w którym będą przechowywane wszystkie bazy danych (w poniższym przykładzie plik ten został nazwany plik_z_bazami). Jeżeli plik istnieje wówczas zostanie podpięty jeżeli nie istnieje wówczas zostanie utworzony. 18
Następnie dokonujemy stosownych operacji za pomocą instrukcji SQL. W poniższym przykładzie dokonano utworzenia bazy o nazwie auto o dwóch polach tekstowych marka i model oraz jednym polu liczbowym waga. 19
Kolejnym krokiem było wpisanie danych do utworzonej bazy 20
W analogiczny sposób została utworzona baza kierowca. 21
Wpisanie danych do bazy kierowca Zakończenie działania sqlite3 za pomocą instrukcji.exit 22
Utworzony plik_z_bazami - znajduje się w tym samym katalogu co sqlite3.exe. 23
Uruchamiamy program SQLiteStudio gdzie podłączamy utworzony przez nas plik_z_bazami 24
25
SQLiteSudio jest to program wykorzystywany do zarządzania bazami danych. Z jego poziomu możemy nie tylko wprowadzać dane ale również modyfikować bazy (usuwać lub dodawać pola, zakładać klucze, relacje itd.) 26
Przykład definiowania klucza głównego 27
28
29
Przykład definiowania indeksu 30
Dopisywanie rekordów do bazy 31
Definiowanie klucza obcego 32
W ramach SQLiteStudio możemy formułować zapytania SQL względem zarządzanych baz 33
34
Wynik zapytania 35
SQLite w praktyce Korzystanie z SQLite jest bardzo proste ponieważ sprowadza się do umiejętności władania językiem SQL oraz zastosowania trzech funkcji i jednej struktury. Funkcja sqlite_open pozwala otworzyć plik zawierający bazę danych. Jej składnia wygląda następująco: sqlite *sqlite_open(const char *dbname, int mode, char **errmsg); gdzie: - dbname nazwa pliku, - mode tryb w jakim będą dostępne dane pochodzące z bazy (tylko do odczytu lub tryb pełnego dostępu do danych ), - errmsg wskaźnik do komunikatu błędu. Funkcja sqlite_open zwraca wskaźnik do struktury o nazwie sqlite. Reprezentuje ona obiekt bazy danych i jest wykorzystywana podczas wszystkich operacji przeprowadzanych na bazie danych. Jeśli operacja otwarcia się nie powiedzie, wtedy funkcja zwróci wartość NULL. Funkcja sqlite_close zamyka plik z bazą danych. Jako parametr podajemy wskaźnik to struktury otrzymanej w wyniku wywołania funkcji sqlite_open. void sqlite_close(sqlite*); 36
Struktura funkcji sqlite_exec wygląda następująco: int sqlite_exec( sqlite* wbd, char *sql, int (*)FC(void*,int,char**,char**), void* wx, char **errmsg ); gdzie: - wbd - wskaźnik do bazy danych, - sql - wyrażenie języka SQL, które chcemy wykonać na bazie, - FC - wskaźnik do funkcji typu callback, która określa wynik naszego zapytania w SQL, - wx - wskaźnik, na który można zrzutować dowolną zmienną lub przygotowaną wcześniej strukturę, jaką chcemy przekazać do funkcji callback, - errmsq -wskaźnik do komunikatu o błędzie. Funckja typu callback (FC) ma następującą strukturę int FC(void *parg, int argc, char **argv, char **columnnames) gdzie: - parg - wskaźnik, na który można zrzutować dowolną zmienną lub strukturę użytą jako 4 parametr w funkcji sqlite_exec, - argc - liczbę kolumn w wynikowym rekordzie, - Argv - tablicę napisów zawierającą wartości poszczególnym pól, - columnnames - tablicę napisów zawierającą nazwy kolumn. Liczba wywołań funkcji FC dokonywana przez system zależy od ilości rekordów w wynikowej tabeli. 37
Struktura funkcji sqlite_get_table (pewnego rodzaju alternatywy wobec sqlite_exec). int sqlite_get_table(sqlite* db, char *sql, char ***result, int *nrow, int *ncolumn, char **errmsg); gdzie: - sqlite* db - wskaźnik do struktury sqlite otrzymanej podczas otwarcia bazy, - char *sql - wyrażenie SQL stanowiące treść zapytania do bazy danych, - char ***result - tablica wskaźników do tekstów reprezentujących wynik zapytania, - int *nrow - liczba wierszy zawartych w zmiennej result, - int *ncolumn - liczba kolumn zawartych w zmiennej result, - char **errmsg - tekst komunikatu o błędzie. 38
SQLite w DecC++ Poza standardowymi bibliotekami dołączamy bibliotekę sqlite3.h 39
A do projektu dodajemy wcześniej utworzoną bibliotekę statyczną Proj_Biblio_SQLITE.a 40
Fragment kodu realizujący określone zapytanie (SQL) w ramach obsługi zdarzenia naciśnięcia przycisku funkcje sqlite3.open, sqlite3.exec oraz sqlite3.close. 41
42
Wynik wpisanego zapytania (program przykład) 43
44