Last modified: September 18, 2024
This article is written in: 🇵🇱
Bazy danych z SQLite
Na rynku dostępnych jest wiele różnorodnych systemów zarządzania bazami danych (DBMS). Każdy z nich posiada specyficzne wady i zalety. Jednym z popularnych, lekkich DBMS jest SQLite. Kluczowe cechy SQLite to:
- SQLite działa na większości dostępnych systemów operacyjnych.
- SQLite nie wymaga instalacji dodatkowego oprogramowania ani konfiguracji serwera.
- Cała baza danych jest zawarta w jednym pliku, co ułatwia przenoszenie i kopie zapasowe.
- W wielu przypadkach, cała baza danych jest ładowana do pamięci RAM, co przyspiesza operacje na niej.
Jeżeli poszukujesz zestawów danych do wykorzystania w projektach czy do nauki, polecam następujące źródła:
Połączenie (Connection)
W kontekście baz danych, połączenie odnosi się do sesji między aplikacją a bazą danych. Gdy mówimy o "połączeniu z bazą danych", mamy na myśli nawiązanie komunikacji pomiędzy aplikacją (w naszym przypadku programem w Pythonie) a serwerem bazy danych (w tym przypadku plikiem bazy SQLite).
connection
w naszym przykładzie jest instancją klasy, która reprezentuje to połączenie. Za pomocą tego obiektu możemy:
- Wykonywać operacje na bazie danych, takie jak tworzenie tabeli czy dodawanie rekordów.
- Zarządzać transakcjami (czyli grupami operacji, które mają być traktowane jako jedna całość; możemy je "zatwierdzać" (
commit
) lub "cofać" (rollback
)). - Zamykać połączenie z bazą danych.
Kursor
W kontekście baz danych, kursor to specjalny obiekt, który umożliwia przechodzenie przez wyniki zapytania oraz odzyskiwanie kolejnych wierszy danych. W skrócie, kursor to narzędzie, które pozwala "przeszukiwać" wyniki zapytań krok po kroku.
W module sqlite3
w Pythonie, kursor jest używany do:
- Wykonywania zapytań do bazy danych.
- Pobierania wyników zapytań (np. za pomocą metod
fetchone()
do pobierania jednego wiersza,fetchall()
do pobierania wszystkich wierszy czyfetchmany(size)
do pobierania określonej liczby wierszy). - Obsługi błędów i wyjątków powiązanych z operacjami na bazie danych.
Otwarcie połączenia z bazą danych
Połączenie z bazą danych lub jej utworzenie (jeśli nie istnieje) realizuje się za pomocą funkcji connect()
.
import sqlite3
connection = sqlite3.connect("baza_danych.db")
Tworzenie tabel
Aby zdefiniować strukturę bazy, można utworzyć odpowiednie tabele za pomocą języka SQL. Tworzenie tabeli polega na zdefiniowaniu jej nazwy oraz kolumn, które będą się w niej znajdować, wraz z odpowiednimi typami danych i opcjonalnymi ograniczeniami.
Tworzenie tabeli users
import sqlite3
# Połączenie z bazą danych (lub utworzenie nowej)
connection = sqlite3.connect('example.db')
# Definicja polecenia SQL do utworzenia tabeli
sql_create_table = """
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
password TEXT NOT NULL
)
"""
# Wykonanie polecenia SQL
connection.execute(sql_create_table)
connection.commit()
Powyższy kod tworzy tabelę users
z trzema kolumnami:
id
: Klucz główny tabeli, wartość unikalna dla każdego rekordu, automatycznie zwiększana.username
: Nazwa użytkownika, pole tekstowe, wartość nie może być pusta.password
: Hasło użytkownika, pole tekstowe, wartość nie może być pusta.
Tworzenie tabeli orders
# Definicja polecenia SQL do utworzenia tabeli
sql_create_orders_table = """
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
amount REAL,
order_date TEXT,
FOREIGN KEY (user_id) REFERENCES users (id)
)
"""
# Wykonanie polecenia SQL
connection.execute(sql_create_orders_table)
connection.commit()
Powyższy kod tworzy tabelę orders
z czterema kolumnami:
id
: Klucz główny tabeli, wartość unikalna dla każdego rekordu, automatycznie zwiększana.user_id
: Id użytkownika, klucz obcy odnoszący się doid
w tabeliusers
.amount
: Kwota zamówienia, pole numeryczne.order_date
: Data zamówienia, pole tekstowe.
Dodawanie rekordów do tabeli users
# Dane do wprowadzenia
data_users = [
("user1", "pass1"),
("user2", "pass2")
]
# Wprowadzanie danych
for user in data_users:
connection.execute("INSERT INTO users (username, password) VALUES (?, ?)", user)
# Zatwierdzenie zmian
connection.commit()
# Sprawdzenie wyników
cursor = connection.execute("SELECT * FROM users")
print(cursor.fetchall())
Powyższy kod dodaje dwa rekordy do tabeli users
. Wartości dla username
i password
są pobierane z listy data_users
, a następnie wstawiane do tabeli za pomocą zapytania INSERT INTO
.
Wynik:
[(1, 'user1', 'pass1'), (2, 'user2', 'pass2')]
Dodawanie rekordów do tabeli orders
# Dane do wprowadzenia
data_orders = [
(1, 250.5, '2023-01-01'),
(1, 300.75, '2023-01-02'),
(2, 450.0, '2023-01-03')
]
# Wprowadzanie danych
for order in data_orders:
connection.execute("INSERT INTO orders (user_id, amount, order_date) VALUES (?, ?, ?)", order)
# Zatwierdzenie zmian
connection.commit()
# Sprawdzenie wyników
cursor = connection.execute("SELECT * FROM orders")
print(cursor.fetchall())
Powyższy kod dodaje trzy rekordy do tabeli orders
. Wartości dla user_id
, amount
i order_date
są pobierane z listy data_orders
, a następnie wstawiane do tabeli za pomocą zapytania INSERT INTO
.
Wynik:
[(1, 1, 250.5, '2023-01-01'), (2, 1, 300.75, '2023-01-02'), (3, 2, 450.0, '2023-01-03')]
Pobieranie wszystkich rekordów z tabeli users
# Wykonanie zapytania SELECT
cursor = connection.execute("SELECT * FROM users")
users = cursor.fetchall()
# Wyświetlenie wyników
for user in users:
print(user)
SELECT * FROM users
: Pobiera wszystkie kolumny i wiersze z tabeliusers
.cursor.fetchall()
: Pobiera wszystkie wyniki zapytania i zwraca je jako listę krotek.for user in users
: Iteruje przez listę użytkowników i drukuje każdą krotkę.
Wynik:
(1, 'user1', 'pass1')
(2, 'user2', 'pass2')
Pobieranie wybranych kolumn i filtrowanie danych
# Wykonanie zapytania SELECT z filtrowaniem
cursor = connection.execute("SELECT username FROM users WHERE id = ?", (1,))
user = cursor.fetchone()
# Wyświetlenie wyniku
if user:
print(user)
SELECT username FROM users WHERE id = ?
: Pobiera kolumnęusername
z tabeliusers
, gdzieid
jest równe 1.cursor.fetchone()
: Pobiera pierwszy wynik zapytania.if user
: Sprawdza, czy wynik nie jest pusty i drukuje nazwę użytkownika.
Wynik:
('user1',)
Łączenie tabel (JOIN)
Przykład: Inner Join
# Wykonanie zapytania INNER JOIN
sql = """
SELECT users.username, orders.amount, orders.order_date
FROM users
INNER JOIN orders ON users.id = orders.user_id
"""
cursor = connection.execute(sql)
results = cursor.fetchall()
# Wyświetlenie wyników
for row in results:
print(row)
INNER JOIN
: Łączy wiersze z dwóch tabel, gdzie istnieje dopasowanie w obu tabelach.ON users.id = orders.user_id
: Warunek łączenia, gdzieid
z tabeliusers
musi być równeuser_id
z tabeliorders
.
Wynik:
('user1', 250.5, '2023-01-01')
('user1', 300.75, '2023-01-02')
('user2', 450.0, '2023-01-03')
Przykład: Left Join
# Wykonanie zapytania LEFT JOIN
sql = """
SELECT users.username, orders.amount, orders.order_date
FROM users
LEFT JOIN orders ON users.id = orders.user_id
"""
cursor = connection.execute(sql)
results = cursor.fetchall()
# Wyświetlenie wyników
for row in results:
print(row)
LEFT JOIN
: Łączy wszystkie wiersze z tabeli users
i dopasowane wiersze z tabeli orders
. Jeśli nie ma dopasowania, wynikiem są wartości NULL w kolumnach tabeli orders
.
Wynik:
('user1', 250.5, '2023-01-01')
('user1', 300.75, '2023-01-02')
('user2', 450.0, '2023-01-03')
Grupowanie danych (GROUP BY)
Przykład: Grupowanie według użytkownika i sumowanie zamówień
# Wykonanie zapytania GROUP BY
sql = """
SELECT users.username, SUM(orders.amount) as total_amount
FROM users
INNER JOIN orders ON users.id = orders.user_id
GROUP BY users.username
"""
cursor = connection.execute(sql)
results = cursor.fetchall()
# Wyświetlenie wyników
for row in results:
print(row)
GROUP BY users.username
: Grupuje wyniki według nazwy użytkownika.SUM(orders.amount) as total_amount
: Oblicza sumę zamówień dla każdego użytkownika.
Wynik:
('user1', 551.25)
('user2', 450.0)
Sortowanie danych (ORDER BY)
Przykład: Sortowanie wyników według daty zamówienia
# Wykonanie zapytania ORDER BY
sql = """
SELECT users.username, orders.amount, orders.order_date
FROM users
INNER JOIN orders ON users.id = orders.user_id
ORDER BY orders.order_date DESC
"""
cursor = connection.execute(sql)
results = cursor.fetchall()
# Wyświetlenie wyników
for row in results:
print(row)
ORDER BY orders.order_date DESC
: Sortuje wyniki według daty zamówienia w kolejności malejącej.
Wynik:
('user2', 450.0, '2023-01-03')
('user1', 300.75, '2023-01-02')
('user1', 250.5, '2023-01-01')
Zamykanie połączenia
Po wszystkich operacjach na bazie danych, konieczne jest zamknięcie połączenia.
connection.close()