Sostieni AppuntiFacili con una piccola donazione su PayPal
Dona con PayPalIn molte applicazioni reali è necessario salvare dati in modo persistente: utenti, prodotti, log, configurazioni, ecc. Python offre diversi modi per gestire database, ma il più semplice per iniziare è SQLite.
SQLite è un database:
sqlite3È ideale per prototipi, progetti didattici, piccole applicazioni e programmi desktop.
INFO
Obiettivo della lezione: imparare a creare, collegare e interrogare un database SQLite tramite Python.
SQLite è un DBMS relazionale che memorizza tutto in un singolo file .db o .sqlite.
| Caratteristica | Dettagli |
|---|---|
| Tipo | Database relazionale |
| Installazione | Nessuna, integrato in Python |
| Memorizzazione | File locale .db |
| Lingua | SQL standard |
| Utilizzo | Applicazioni locali, mobile, IoT |
INFO
SQLite è usatissimo: Android, iOS, Chrome, Firefox e tantissime app lo usano internamente.
Il modulo base è:
import sqlite3
import sqlite3
conn = sqlite3.connect("miodb.db") # crea il file se non esiste
cursor = conn.cursor()
print("Connessione avvenuta con successo!")
conn.close()
TIP
Tienere sempre a mente di chiudere la connessione per liberare risorse.
Esempio: tabella utenti.
import sqlite3
conn = sqlite3.connect("miodb.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS utenti (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
)
""")
conn.commit()
conn.close()
dove:
CREATE TABLE IF NOT EXISTS: crea la tabella solo se non esiste.id autoincrementale.email contrassegnata come unica.import sqlite3
conn = sqlite3.connect("miodb.db")
cursor = conn.cursor()
cursor.execute("""
INSERT INTO utenti (nome, email)
VALUES (?, ?)
""", ("Mario Rossi", "mario@example.com"))
conn.commit()
conn.close()
Perché ? ?: Serve a prevenire SQL injection e rendere sicure le query parametrizzate.
conn = sqlite3.connect("miodb.db")
cursor = conn.cursor()
cursor.execute("SELECT * FROM utenti")
utenti = cursor.fetchall()
for utente in utenti:
print(utente)
conn.close()
cursor.execute("SELECT * FROM utenti WHERE email = ?", ("mario@example.com",))
utente = cursor.fetchone()
print(utente)
cursor.execute("""
UPDATE utenti SET nome = ?
WHERE email = ?
""", ("Mario R.", "mario@example.com"))
conn.commit()
cursor.execute("DELETE FROM utenti WHERE email = ?", ("mario@example.com",))
conn.commit()
Python permette di gestire automaticamente apertura/chiusura connessioni:
import sqlite3
with sqlite3.connect("miodb.db") as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM utenti")
print(cursor.fetchall())
TIP
Usare with è una best practice: più pulito, più sicuro, meno errori.
import sqlite3
try:
conn = sqlite3.connect("miodb.db")
cursor = conn.cursor()
cursor.execute("SELECT * FROM utenti")
dati = cursor.fetchall()
print(dati)
except sqlite3.Error as e:
print("Errore nel database:", e)
finally:
if conn:
conn.close()
Una buona struttura per lavorare con un database in Python è:
progetto/
│-- database/
│ │-- __init__.py
│ │-- connection.py
│ │-- user_repository.py
│-- models/
│ │-- user.py
│-- main.py
│-- miodb.db
File: database/connection.py
import sqlite3
class DatabaseConnection:
def __init__(self, db_path="miodb.db"):
self.db_path = db_path
def __enter__(self):
self.conn = sqlite3.connect(self.db_path)
self.cursor = self.conn.cursor()
return self.cursor
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is None:
self.conn.commit()
else:
print(f"Errore DB: {exc_value}")
self.conn.close()
per:
File: models/user.py
class User:
def __init__(self, id: int | None, nome: str, email: str):
self.id = id
self.nome = nome
self.email = email
File: database/user_repository.py
from models.user import User
from database.connection import DatabaseConnection
class UserRepository:
@staticmethod
def create_table():
with DatabaseConnection() as cursor:
cursor.execute("""
CREATE TABLE IF NOT EXISTS utenti (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
)
""")
@staticmethod
def add_user(user: User):
with DatabaseConnection() as cursor:
cursor.execute("""
INSERT INTO utenti (nome, email)
VALUES (?, ?)
""", (user.nome, user.email))
@staticmethod
def get_all_users():
with DatabaseConnection() as cursor:
cursor.execute("SELECT id, nome, email FROM utenti")
rows = cursor.fetchall()
return [User(id=r[0], nome=r[1], email=r[2]) for r in rows]
@staticmethod
def get_user_by_email(email: str):
with DatabaseConnection() as cursor:
cursor.execute("SELECT id, nome, email FROM utenti WHERE email = ?", (email,))
row = cursor.fetchone()
return User(id=row[0], nome=row[1], email=row[2]) if row else None
@staticmethod
def update_user_email(old_email, new_email):
with DatabaseConnection() as cursor:
cursor.execute("""
UPDATE utenti SET email = ?
WHERE email = ?
""", (new_email, old_email))
@staticmethod
def delete_user(email: str):
with DatabaseConnection() as cursor:
cursor.execute("DELETE FROM utenti WHERE email = ?", (email,))
File: main.py
from models.user import User
from database.user_repository import UserRepository
# Creazione tabella
UserRepository.create_table()
# Inserimento utenti
UserRepository.add_user(User(id=None, nome="Mario", email="mario@example.com"))
UserRepository.add_user(User(id=None, nome="Luigi", email="luigi@example.com"))
# Lettura
utenti = UserRepository.get_all_users()
for u in utenti:
print(u)
# Ricerca
utente = UserRepository.get_user_by_email("mario@example.com")
print("Trovato:", utente)
# Aggiornamento
UserRepository.update_user_email("mario@example.com", "mario_new@example.com")
# Eliminazione
UserRepository.delete_user("luigi@example.com")
1) Qual è il vantaggio principale di SQLite?
2) In Python, quale modulo si usa per SQLite?
3) Quale comando crea una tabella?
4) Perché si usano i placeholder '?' nelle query?
5) Qual è il metodo per eseguire una query?
6) Quale metodo recupera tutti i risultati?
7) Cosa fa 'conn.commit()'?
8) Quale pratica è consigliata?