SQLite è uno dei database gestionali relazionali (RDBMS) più popolari. È leggero, ovvero non occupa molto spazio sul tuo sistema. Una delle sue caratteristiche migliori è che non richiede server, quindi non ha bisogno di installare o gestire un server separato per essere utilizzato.

Invece, memorizza tutto in un semplice file sul tuo computer. Anche questo richiede zero configurazione, quindi non c’è alcun processo di installazione complicato, rendendolo perfetto per principianti e progetti piccoli.

SQLite è una scelta ottima per applicazioni piccole e medie perché è facile da usare, veloce e può sostenere la maggior parte delle mansioni che può fare un database più grande, ma senza il problema di gestire software aggiuntivi. Che si stia costruendo un progetto personale o facendo un prototipo di una nuova app, SQLite è una opzione solida per avviare le cose velocemente.

In questo tutorial, imparerai come lavorare con SQLite usando Python. Ecco cosa viene trattato in questo tutorial:

Questo tutorial è perfetto per chiunque voglia iniziare con le basi delle basi senza affrontare configurazioni complesse.

Come impostare il tuo ambiente Python

Prima di lavorare con SQLite, assicurati che il tuo ambiente Python sia pronto. Ecco come impostare tutto.

Installazione di Python

Se non hai ancora Python installato sul tuo sistema, puoi scaricarlo dalla pagina ufficiale del sito di Python. Segui le istruzioni di installazione per il tuo sistema operativo (Windows, macOS o Linux).

Per controllare se Python è installato, apri il tuo terminale (o prompt di comando) e digita:

python --version

Questo dovrebbe mostrare la versione corrente di Python installata. Se non è installata, segui le istruzioni del sito di Python.

Installazione del modulo SQLite3

La buona notizia è che SQLite3 è incluso in Python! Non hai bisogno di installarlo separatamente perché è presente nella libreria standard di Python. Questo significa che puoi iniziare a usarlo immediatamente senza alcuna configurazione aggiuntiva.

È una buona idea creare un ambiente virtuale per ogni progetto per mantenere le dipendenze organizzate. Un ambiente virtuale è come un piano di lavoro pulito dove puoi installare pacchetti senza influenzare l’installazione globale di Python.

Per creare un ambiente virtuale, segui questi passaggi:

  1. Prima di tutto, apri il tuo terminale o il prompt di comando e naviga nella directory dove vuoi creare il tuo progetto.

  2. Esegui il comando seguente per creare un ambiente virtuale:

python -m venv env

Qui, env è il nome dell’ambiente virtuale. Puoi darle qualsiasi nome ti piaca.

  1. Attiva l’ambiente virtuale:
# Usa il comando per Windows
env\Scripts\activate

# Usa il comando per macOS/Linux:
env/bin/activate

Dopo aver attivato l’ambiente virtuale, noterai che il tuo prompt del terminale cambierà, mostrando il nome dell’ambiente virtuale. Questo significa che ora stai lavorando all’interno di esso.

Installazione di librerie necessarie

Per questo progetto avremo bisogno di alcune librerie aggiuntive. In particolare, useriamo:

  • pandas: Questa è una libreria facoltativa per la manipolazione e l’ visualizzazione di dati in formato tabellare, utile per casi di utilizzo avanzati.

  • faker: Questa libreria ci aiuterà a generare dati finti, come nomi e indirizzi casuali, che possiamo inserire nella nostra base dati per test.

Per installare pandas e faker, è sufficiente eseguire i seguenti comandi:

pip install pandas faker

Questo installa sia pandas che faker nella vostra environment virtuale. Con questo, il vostro environment è pronto, e siete pronti a iniziare la creazione e la gestione della vostra base dati SQLite in Python!

Come creare una base dati SQLite

Un database è un modo strutturato per memorizzare e gestire i dati in modo da essere facilmente accessibili, aggiornabili e organizzabili. È come un sistema di archiviazione digitale che consente di memorizzare in modo efficiente grandi quantità di dati, che siano per un’app semplice o un sistema più complesso. I database usano le tabelle per organizzare i dati, con righe e colonne che rappresentano i record individuali e le loro caratteristiche.

Come funzionano i database SQLite

A differenza di molti altri sistemi di database, SQLite è un database serverless. Ciò significa che non richiede la configurazione o la gestione di un server, rendendolo leggero e facile da usare. Tutti i dati sono memorizzati in un singolo file sul tuo computer, che puoi spostare, condividere o backupare facilmente. Nonostante la sua semplicità, SQLite è sufficientemente potente per gestire molte attività di database comuni ed è largamente utilizzato in app mobile, sistemi embedded e progetti di dimensioni piccole a medie.

Come creare una nuova base di dati SQLite

Creiamo una nuova base di dati SQLite e impariamo come interagire con essa usando la libreria sqlite3 di Python.

Connessione alla base di dati

Poiché sqlite3 è installato in modo predefinito, devi solo importarlo nel tuo script Python. Per creare una nuova base dati o per connetterti a una esistente, usi il metodo sqlite3.connect(). Questo metodo richiede il nome del file della base dati come argomento. Se il file non esiste, SQLite crearla automaticamente.

import sqlite3

# Connessione alla base di dati SQLite (o creazione della base dati se non esiste)
connection = sqlite3.connect('my_database.db')

In questo esempio, viene creato un file chiamato my_database.db nella stessa directory del tuo script. Se il file esiste già, SQLite aprirà semplicemente la connessione ad esso.

Creazione di un Cursore

Una volta creata una connessione, il passo successivo è creare un oggetto cursore. Il cursore è responsabile dell’esecuzione di comandi e query SQL sulla base dati.

# Creazione di un cursore
cursor = connection.cursor()

Chiudere la connessione

Dopo aver lavorato alla base dati, è importante chiudere la connessione per liberare risorse. È possibile chiudere la connessione con il seguente comando:

# Chiudi la connessione alla base dati
connection.close()

Tuttavia, dovresti chiudere la connessione solo dopo aver completato tutte le tue operazioni.

Quando esegui il tuo script Python, verrà creato un file chiamato my_database.db nella directory di lavoro corrente. Ora hai creato con successo la tua prima base dati SQLite!

Come utilizzare il gestore di contesto per aprire e chiudere connessioni

Python offre un metodo più efficiente e pulito per gestire le connessioni ai database usando l’istruzione with, anche conosciuta come gestore di contesto. L’istruzione with apre e chiude automaticamente la connessione, garantendo che la connessione sia chiusa correttamente anche se si verifica un errore durante le operazioni del database. Ciò elimina la necessità di chiamare manualmente connection.close().

Ecco come puoi usare l’istruzione with per gestire le connessioni al database:

import sqlite3

# Passaggio 1: Usa 'with' per connetterti alla base dati (o per crearne una) e chiuderla automaticamente quando sei pronto
with sqlite3.connect('my_database.db') as connection:

    # Passaggio 2: Crea un oggetto cursore per interagire con la base dati
    cursor = connection.cursor()

    print("Database created and connected successfully!")

# Non serve chiamare connection.close(); lo fa automaticamente!

Da ora in poi, utilizzeremo l’istruzione with nei nostri prossimi esempi di codice per gestire le connessioni al database in maniera efficiente. questo renderà il codice più conciso e più facile da mantenere.

Come creare le tabelle del database

Ora che abbiamo creato un database SQLite e si è connesso a esso, il passo successivo è quello di creare tabelle all’interno del database. Una tabella è dove salveremo i nostri dati, organizzati in righe (record) e colonne (attributi). Per questo esempio, creare una tabella chiamata Students per memorizzare le informazioni sugli studenti, che reutilizzeremo nelle sezioni successive.

Per creare una tabella, usiamo l’istruzione SQL CREATE TABLE. Questo comando definisce la struttura della tabella, inclusi i nomi delle colonne e i tipi di dati per ogni colonna.

Ecco un semplice comando SQL per creare una tabella Students con i seguenti campi:

  • id: Un identificatore unico per ogni studente (intero).

  • name: Il nome dell’ studente (testo).

  • age: L’età dell’ studente (intero).

  • email: L’indirizzo email dell’ studente (testo).

Il comando SQL per creare questa tabella sarebbe simile a questo:

CREATE TABLE Students (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER,
    email TEXT
);

Possiamo eseguire questo comando SQL CREATE TABLE in Python utilizzando la libreria sqlite3. Vediamo come fare.

import sqlite3

# Usa 'with' per connettersi al database SQLite e chiudere automaticamente la connessione quando terminato
with sqlite3.connect('my_database.db') as connection:

    # Crea un oggetto cursore
    cursor = connection.cursor()

    # Scrive il comando SQL per creare la tabella Students
    create_table_query = '''
    CREATE TABLE IF NOT EXISTS Students (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        age INTEGER,
        email TEXT
    );
    '''

    # Esegue il comando SQL
    cursor.execute(create_table_query)

    # Committa i cambiamenti
    connection.commit()

    # Stampa un messaggio di conferma
    print("Table 'Students' created successfully!")
  • IF NOT EXISTS: Questo assicura che la tabella sia creata solo se non esiste già, evitando errori se la tabella è stata creata prima.

  • connection.commit(): Questo salva (committa) i cambiamenti al database.

Quando si esegue il codice Python qui sopra, creerà la tabella Students nel file database my_database.db. Vedrete anche un messaggio nella console che conferma che la tabella è stata creata con successo.

Se stai utilizzando Visual Studio Code, puoi installare l’estensione SQLite Viewer per visualizzare i database SQLite.

Tipi di Dati in SQLite e il Loro Mapping a Python

SQLite supporta diversi tipi di dati, che dobbiamo comprendere quando definiamo le nostre tabelle. Ecco una rapida panoramica dei tipi di dati comuni in SQLite e come si mappano ai tipi di Python:

Tipo di Dato in SQLite Descrizione Equivalente in Python
INTEGER Numeri interi int
TEXT Stringhe di testo str
REAL Numeri in virgola mobile float
BLOB Dati binari (ad es., immagini, file) bytes
NULL Rappresenta nessun valore o dati mancanti None

Nella nostra tabella Students:

  • id è di tipo INTEGER, che si mappa all’int di Python.

  • name e email sono di tipo TEXT, che si mappa allo str di Python.

  • età è anche di tipo INTEGER, mappato a Python’s int.

Come Inserire Dati in una Tabella

Ora che abbiamo la nostra tabella Students creata, è il momento di iniziare ad inserire dati nel database. In questa sezione, vedremo come inserire sia record singoli che multipli usando Python e SQLite, e come evitare problemi comuni di sicurezza come l’iniezione SQL usando query parametrizzate.

Come Inserire un Singolo Record

Per inserire dati nel database, usiamo il comando SQL INSERT INTO. Cominceremo inserendo un singolo record nella nostra tabella Students.

Ecce here la sintassi SQL di base per inserire un singolo record:

INSERT INTO Students (name, age, email) 
VALUES ('John Doe', 20, '[email protected]');

Tuttavia, invece di scrivere direttamente SQL nel nostro script Python con valori hardcoded, useremo query parametrizzate per rendere il nostro codice più sicuro e flessibile. Le query parametrizzate aiutano a prevenire l’iniezione SQL, un attacco comune in cui utenti maligni possono manipolare la query SQL passando input dannosi.

Ecce come possiamo inserire un singolo record nella tabella Students usando una query parametrizzata:

import sqlite3

# Usa 'with' per aprire e chiudere la connessione automaticamente
with sqlite3.connect('my_database.db') as connection:
    cursor = connection.cursor()

    # Inserisci un record nella tabella Students
    insert_query = '''
    INSERT INTO Students (name, age, email) 
    VALUES (?, ?, ?);
    '''
    student_data = ('Jane Doe', 23, '[email protected]')

    cursor.execute(insert_query, student_data)

    # Committa i cambiamenti automaticamente
    connection.commit()

    # Non serve chiamare connection.close(); questo viene fatto automaticamente!
    print("Record inserted successfully!")

I segnaposto ? rappresentano i valori da inserire nella tabella. I valori reali vengono passati come una tupla (student_data) nel metodo cursor.execute().

Come Inserire Record multipli

Se vuoi inserire record multipli all’una, puoi usare il metodo executemany() in Python. Questo metodo richiede una lista di tuple, dove ogni tupla rappresenta un record.

Per rendere il nostro esempio più dinamico, puoi usare la libreria Faker per generare dati studenteschi casuali. Questo è utile per testare e simulare scenario reali.

from faker import Faker
import sqlite3

# Inizializza Faker
fake = Faker(['en_IN'])

# Usa 'with' per aprire e chiudere la connessione automaticamente
with sqlite3.connect('my_database.db') as connection:
    cursor = connection.cursor()

    # Inserisci un record nella tabella Students
    insert_query = '''
    INSERT INTO Students (name, age, email) 
    VALUES (?, ?, ?);
    '''
    students_data = [(fake.name(), fake.random_int(
        min=18, max=25), fake.email()) for _ in range(5)]

    # Esegui la query per record multipli
    cursor.executemany(insert_query, students_data)

    # Committa i cambiamenti
    connection.commit()

    # Stampa il messaggio di conferma
    print("Fake student records inserted successfully!")

In questo codice:

  • Faker() genera nomi, età ed email casuali per gli studenti. Passare la localizzazione ([‘en_IN’]) è opzionale.

  • cursor.executemany(): Questo metodo ci permette di inserire più record contemporaneamente, rendendo il codice più efficiente.

  • students_data: Una lista di tuple ognuna delle quali rappresenta i dati di uno studente.

Come Gestire Problemi Comuni: SQL Injection

L’SQL injection è una vulnerabilità di sicurezza tramite cui gli attaccanti possono inserire o manipolare query SQL fornendo input dannosi. Per esempio, un attaccante potrebbe cercare di iniettare codice come '; DROP TABLE Students; -- per eliminare la tabella.

Utilizzando le query parametrizzate (come dimostrato sopra), si evita questo problema. I segnaposto ? nelle query parametrizzate assicurano che i valori di input vengano trattati come dati e non come parte del comando SQL. Questo rende impossibile l’esecuzione di codice dannoso.

Come Effettuare Query ai Dati

Ora che abbiamo inserito alcuni dati nella nostra tabella Students, impareremo come recuperare i dati dalla tabella. Esploreremo diversi metodi per recuperare i dati in Python, inclusi fetchone(), fetchall(), e fetchmany().

Per query dati da una tabella, usiamo l’istruzione SELECT. Ecco un semplice comando SQL per selezionare tutte le colonne dalla tabella Students:

SELECT * FROM Students;

Questo comando recupera tutti i record e le colonne dalla tabella Students. Possiamo eseguire questo SELECT query in Python e recuperare i risultati.

Come recuperare tutti i record

Ecco come possiamo recuperare tutti i record dalla tabella Students:

import sqlite3

# Usare 'with' per connettersi al database SQLite
with sqlite3.connect('my_database.db') as connection:

    # Creare un oggetto cursore
    cursor = connection.cursor()

    # Scrivere il comando SQL per selezionare tutti i record dalla tabella Students
    select_query = "SELECT * FROM Students;"

    # Eseguire il comando SQL
    cursor.execute(select_query)

    # Recuperare tutti i record
    all_students = cursor.fetchall()

    # Mostrare i risultati nel terminale
    print("All Students:")
    for student in all_students:
        print(student)

In questo esempio, il metodo fetchall() recupera tutte le righe restituite dalla query come una lista di tuple.

All Students:
(1, 'Jane Doe', 23, '[email protected]')
(2, 'Bahadurjit Sabharwal', 18, '[email protected]')
(3, 'Zayyan Arya', 20, '[email protected]')
(4, 'Hemani Shukla', 18, '[email protected]')
(5, 'Warda Kara', 20, '[email protected]')
(6, 'Mitali Nazareth', 19, '[email protected]')

Come recuperare un singolo record

Se volete recuperare solo un record, puoi usare il metodo fetchone():

import sqlite3

# Utilizza 'with' per connetterti al database SQLite
with sqlite3.connect('my_database.db') as connection:

    # Crea un oggetto cursore
    cursor = connection.cursor()

    # Scrivi il comando SQL per selezionare tutti i record dalla tabella Students
    select_query = "SELECT * FROM Students;"

    # Esegui il comando SQL
    cursor.execute(select_query)

    # Preleva un record
    student = cursor.fetchone()

    # Visualizza il risultato
    print("First Student:")
    print(student)

Output:

First Student:
(1, 'Jane Doe', 23, '[email protected]')

Come prelevare più record

Per prelevare un numero specifico di record, puoi usare fetchmany(size):

import sqlite3

# Utilizza 'with' per connetterti al database SQLite
with sqlite3.connect('my_database.db') as connection:

    # Crea un oggetto cursore
    cursor = connection.cursor()

    # Scrivi il comando SQL per selezionare tutti i record dalla tabella Students
    select_query = "SELECT * FROM Students;"

    # Esegui il comando SQL
    cursor.execute(select_query)

    # Preleva tre record
    three_students = cursor.fetchmany(3)

    # Visualizza i risultati
    print("Three Students:")
    for student in three_students:
        print(student)

Output:

Three Students:
(1, 'Jane Doe', 23, '[email protected]')
(2, 'Bahadurjit Sabharwal', 18, '[email protected]')
(3, 'Zayyan Arya', 20, '[email protected]')

Come usare pandas per una migliore presentazione dei dati

Per una migliore presentazione dei dati, possiamo usare la libreria pandas per creare un DataFrame dai nostri risultati di query. Questo facilita la manipolazione e la visualizzazione dei dati.

Ecco come prelevare tutti i record e visualizzarli come un DataFrame pandas:

import sqlite3
import pandas as pd

# Usa 'with' per connetterti al database SQLite
with sqlite3.connect('my_database.db') as connection:
    # Scrivi il comando SQL per selezionare tutti i record dalla tabella Students
    select_query = "SELECT * FROM Students;"

    # Usa pandas per leggere il comando SQL direttamente in un DataFrame
    df = pd.read_sql_query(select_query, connection)

# Mostra il DataFrame
print("All Students as DataFrame:")
print(df)

Output:

All Students as DataFrame:
   id                  name  age                        email
0   1              Jane Doe   23             [email protected]
1   2  Bahadurjit Sabharwal   18  [email protected]
2   3           Zayyan Arya   20  [email protected]
3   4         Hemani Shukla   18    [email protected]
4   5            Warda Kara   20           [email protected]
5   6       Mitali Nazareth   19          [email protected]

La funzione pd.read_sql_query() esegue il comando SQL e restituisce direttamente i risultati come DataFrame di pandas.

Come aggiornare e eliminare i dati

In questa sezione, impareremo come aggiornare record esistenti e eliminare record dalla nostra tabella Students usando i comandi SQL in Python. Questo è essenziale per gestire e mantenere i dati in maniera efficiente.

Aggiornamento di record esistenti

Per modificare i record esistenti in un database, usiamo il comando SQL UPDATE. Questo comando ci permette di cambiare i valori di specifiche colonne in uno o più righe in base a una condizione specificata.

Ad esempio, se vogliamo aggiornare l’età di un studente, il comando SQL avrà questo aspetto:

UPDATE Students 
SET age = 21 
WHERE name = 'Jane Doe';

Ora, scriviamo del codice Python per aggiornare l’età di un determinato studente nella nostra tabella Students.

import sqlite3

# Utilizza 'with' per connetterti al database SQLite
with sqlite3.connect('my_database.db') as connection:
    cursor = connection.cursor()

    # Comando SQL per aggiornare l'età di uno studente
    update_query = '''
    UPDATE Students 
    SET age = ? 
    WHERE name = ?;
    '''

    # Dati per l'aggiornamento
    new_age = 21
    student_name = 'Jane Doe'

    # Esegui il comando SQL con i dati
    cursor.execute(update_query, (new_age, student_name))

    # Effettua il commit per salvare l'aggiornamento
    connection.commit()

    # Stampa un messaggio di conferma
    print(f"Updated age for {student_name} to {new_age}.")

In questo esempio, abbiamo usato query parametrizzate per prevenire l’SQL injection.

Come eliminare record dalla tabella

Per rimuovere record da un database, usiamo il comando SQL DELETE. Questo comando ci permette di eliminare una o più righe in base a una condizione specificata.

Per esempio, se vogliamo eliminare uno studente chiamato ‘Jane Doe’, il comando SQL sarebbe così:

DELETE FROM Students 
WHERE name = 'Jane Doe';

Scriviamo ora del codice Python per eliminare uno specifico studente dalla nostra tabella Students usando lo statement with.

import sqlite3

# Utilizza 'with' per connetterti al database SQLite
with sqlite3.connect('my_database.db') as connection:
    cursor = connection.cursor()

    # Comando SQL per eliminare uno studente
    delete_query = '''
    DELETE FROM Students 
    WHERE name = ?;
    '''

    # Nome dello studente da eliminare
    student_name = 'Jane Doe'

    # Esegui il comando SQL con i dati
    cursor.execute(delete_query, (student_name,))

    # Effettua il commit per salvare l'eliminazione
    connection.commit()

    # Stampa un messaggio di conferma
    print(f"Deleted student record for {student_name}.")

Considerazioni importanti

  • Condizioni: Utilizzare sempre la clausola WHERE quando si aggiornano o eliminano record per evitare la modifica o la rimozione di tutte le righe nella tabella. Senza una clausola WHERE, il comando influisce su ogni riga nella tabella.

  • Backup: È una buona prassi eseguire il backup del database prima di eseguire aggiornamenti o eliminazioni, specialmente negli ambienti di produzione.

Come Utilizzare le Transazioni

Una transazione è una sequenza di una o più operazioni SQL che vengono trattate come un’unica unità di lavoro. Nel contesto di un database, una transazione consente di eseguire più operazioni che o tutte riescono o nessuna. Ciò garantisce che il database rimanga in uno stato consistente, anche in presenza di errori o problemi inaspettati.

Ad esempio, se si stanno trasferendo soldi tra due conti bancari, si desidera che il prelievo da un conto e il deposito sull’altro riescano o falliscano insieme. Se un’operazione fallisce, l’altra non dovrebbe essere eseguita per mantenere la coerenza.

Perché Utilizzare le Transazioni?

  1. Integrazione: Le transazioni aiutano a mantenere l’integrità del database garantendo che tutte le regole e i limiti siano rispettati.

  2. Isolamento: Ogni transazione opera indipendentemente dalle altre, impedendo interferenze non intenzionali.

  3. Durabilità: Una volta che una transazione è commessa, i cambiamenti sono permanenti, anche in caso di fallimento del sistema.

Quando utilizzare le transazioni?

Dovresti utilizzare le transazioni quando:

  • Eseguire molte operazioni collegate che devono avere successo o fallire insieme.

  • Modificare dati chiave critici che richiedono integrità e coerenza.

  • Lavorare con operazioni che possono fallire, come transazioni finanziarie o migrazioni dati.

Come gestire le transazioni in Python

In SQLite, le transazioni sono gestite usando i comandi BEGIN, COMMIT e ROLLBACK. Tuttavia, quando si utilizza il modulo sqlite3 in Python, si gestisce di solito le transazioni tramite l’oggetto connessione.

Avvio di una Transazione

Una transazione comincia implicitamente quando si esecute qualsiasi istruzione SQL. Per avviare una transazione esplicitamente, si può usare il comando BEGIN:

cursor.execute("BEGIN;")

Tuttavia, di solito non è necessario avviare una transazione manualmente, poiché SQLite comincia una transazione automaticamente quando si esecute una istruzione SQL.

Come Commitare una Transazione

Per salvare tutti i cambiamenti apportati durante una transazione, si usa il metodo commit(). Ciò rende tutte le modifiche definitive nel database.

connection.commit()

Noi abbiamo già usato il metodo commit() negli esempi forniti sopra.

Ripetere una Transazione

Se qualcosa va storto e si desidera annullare i cambiamenti apportati durante una transazione, si può usare il metodo rollback(). Ciò annulerà tutti i cambiamenti apportati dal momento in cui la transazione è iniziata.

connection.rollback()

Esempio di utilizzo di transazioni in Python

Per illustrare l’uso di transazioni in un scenario reale, creeremo una nuova tabella chiamata Customers per gestire i conti clienti. In questo esempio, supponiamo che ogni cliente abbia una balance. Aggiungeremo due clienti a questa tabella e eseguiremo un’operazione di trasferimento di fondi tra loro.

Prima di tutto, creiamo la tabella Customers e inseriamo due clienti:

import sqlite3

# Crea la tabella Customers e aggiunge due clienti
with sqlite3.connect('my_database.db') as connection:
    cursor = connection.cursor()

    # Crea tabella Customers
    create_customers_table = '''
    CREATE TABLE IF NOT EXISTS Customers (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL UNIQUE,
        balance REAL NOT NULL
    );
    '''
    cursor.execute(create_customers_table)

    # Inserisce due clienti
    cursor.execute(
        "INSERT INTO Customers (name, balance) VALUES (?, ?);", ('Ashutosh', 100.0))
    cursor.execute(
        "INSERT INTO Customers (name, balance) VALUES (?, ?);", ('Krishna', 50.0))

    connection.commit()

Ora, eseguiamo l’operazione di trasferimento di fondi tra Ashutosh e Krishna:

import sqlite3


def transfer_funds(from_customer, to_customer, amount):
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        try:
            # Inizia una transazione
            cursor.execute("BEGIN;")

            # Sottrae quantità dal mittente
            cursor.execute(
                "UPDATE Customers SET balance = balance - ? WHERE name = ?;", (amount, from_customer))
            # Aggiunge quantità al destinatario
            cursor.execute(
                "UPDATE Customers SET balance = balance + ? WHERE name = ?;", (amount, to_customer))

            # Committa i cambiamenti
            connection.commit()
            print(
                f"Transferred {amount} from {from_customer} to {to_customer}.")

        except Exception as e:
            # Se si verifica un errore, annulla la transazione
            connection.rollback()
            print(f"Transaction failed: {e}")


# Esempio d'uso
transfer_funds('Ashutosh', 'Krishna', 80.0)

In questo esempio, prima abbiamo creato una tabella Customers e aggiunto due clienti, Ashutosh con un saldo di ₹100 e Krishna con un saldo di ₹50. Poi abbiamo eseguito un trasferimento di ₹80 da Ashutosh a Krishna. Utilizzando le transazioni, garantiamo che sia l’sconto da parte di Ashutosh e il credito a Krishna siano eseguiti come un’unica operazione atomica, mantenendo l’integrità dei dati in caso di errori. Se il trasferimento fallisce (ad esempio, a causa di saldi insufficenti), la transazione sarà annullata, lasciando entrambi gli account invariati.

Come ottimizzare le prestazioni delle query di SQLite tramite l’indicizzazione

L’indicizzazione è una potente tecnica utilizzata in database per migliorare le prestazioni delle query. Un indice è essenzialmente una struttura dati che memorizza le posizioni delle righe in base ai valori specifici delle colonne, proprio come un indice in fondo ad un libro ci consente di trovare rapidamente un argomento.

Senza un indice, SQLite deve scansionare l’intera tabella riga per riga per trovare i dati rilevanti, il che diventa inefficiente man mano che il set di dati si amplifica. Utilizzando un indice, SQLite può saltare direttamente alle righe necessarie, velocizzando显著emente l’esecuzione delle query.

Come popolare il database con dati finti

Per testare efficacemente l’impatto dell’indicizzazione, abbiamo bisogno di un set di dati significativo. Invece di aggiungere record manualmente, possiamo utilizzare la libreria faker per generare rapidamente dati finti. In questa sezione, generiremo 10.000 record finti e li inseriremo nella nostra tabella Students. Questo simulerà una situazione reale in cui i database diventano grandi e la prestazione delle query diventa importante.

Utilizzeremo il metodo executemany() per inserire i record come segue:

import sqlite3
from faker import Faker

# Inizializza la libreria Faker
fake = Faker(['en_IN'])


def insert_fake_students(num_records):
    """Generate and insert fake student data into the Students table."""
    fake_data = [(fake.name(), fake.random_int(min=18, max=25),
                  fake.email()) for _ in range(num_records)]

    # Usa 'with' per gestire la connessione al database
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Inserisci dati finti nella tabella Students
        cursor.executemany('''
        INSERT INTO Students (name, age, email) 
        VALUES (?, ?, ?);
        ''', fake_data)

        connection.commit()

    print(f"{num_records} fake student records inserted successfully.")


# Inserisci 10.000 record finti nella tabella Students
insert_fake_students(10000)

Eseguendo questo script, verranno aggiunte 10.000 record finti studente alla tabella Students. Nella sezione successiva, queryremo il database e confrontiamo il rendimento delle query con e senza indici.

Come fare query senza indici

In questa sezione, queryremo la tabella Students senza alcun indice per osservare come SQLite si comporta quando non sono presenti alcuna ottimizzazione. Servirà come base per confrontare il rendimento quando aggiungiamo indici in seguito.

Senza indici, SQLite esegue una scansione completa della tabella, il che significa che deve controllare ogni riga della tabella per trovare risultati corrispondenti. Per dataset piccoli, questo è gestibile, ma con il crescere del numero di record, il tempo impiegato per la ricerca aumenta drasticamente. Vediamo questo in azione eseguendo una semplice query SELECT per cercare un studente specifico per nome e misurare quanto impieghi.

Prima di tutto, queryremo la tabella Students cercando un studente con un nome specifico. Loggeremo il tempo impiegato per l’esecuzione della query usando il modulo time di Python per misurare il rendimento.

import sqlite3
import time


def query_without_index(search_name):
    """Query the Students table by name without an index and measure the time taken."""

    # Connettersi alla base di dati usando 'with'
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Misurare l'orario di inizio
        start_time = time.perf_counter_ns()

        # Eseguire una query SELECT per trovare un studente per nome
        cursor.execute('''
        SELECT * FROM Students WHERE name = ?;
        ''', (search_name,))

        # Recuperare tutti i risultati (in pratica dovrebbero essere solo uno o poche)
        results = cursor.fetchall()

        # Misurare l'orario di fine
        end_time = time.perf_counter_ns()

        # Calcolare il tempo totale impiegato
        elapsed_time = (end_time - start_time) / 1000

        # Mostrare i risultati e il tempo impiegato
        print(f"Query completed in {elapsed_time:.5f} microseconds.")
        print("Results:", results)


# Esempio: Cerca un studente per nome
query_without_index('Ojasvi Dhawan')

Ecco l’output:

Query completed in 1578.10000 microseconds.
Results: [(104, 'Ojasvi Dhawan', 21, '[email protected]')]

Eseguendo il script precedente, potrai vedere quanto tempo ci vuole per cercare nella tabella Students senza alcun indice. Per esempio, se la tabella ha 10.000 record, la query potrebbe richiedere 1000-2000 microsecondi a seconda della dimensione della tabella e del tuo hardware. Questo potrebbe non sembrare troppo lento per un piccolo set di dati, ma la prestazione decrecerà man mano che si aggiungono più record.

Usiamo time.perf_counter_ns() per misurare il tempo impiegato per l’esecuzione della query in nanosecondi. Questo metodo è altamente preciso per il benchmarking di brevi intervalli di tempo. Convertiamo il tempo in microsecondi (us) per una lettura più semplice.

Inizio Introduzione del Piano Query

Quando si lavora con database, capire come vengono eseguite le query può aiutare a identificare i colli di bottiglia della performance e ottimizzare il proprio codice. SQLite fornisce un utile strumento per questo, chiamato EXPLAIN QUERY PLAN, che consente di analizzare i passaggi che SQLite deve compiere per recuperare i dati.

In questa sezione, viene introdotta come utilizzare EXPLAIN QUERY PLAN per visualizzare e comprendere le operazioni interne di una query – in particolare, come SQLite esegue uno scansione completa della tabella quando non è presente alcun indice.

Usiamo EXPLAIN QUERY PLAN per vedere come SQLite recupera i dati dalla tabella Students senza alcun indice. Cercherà un studente per nome, e il piano di query rivelerà i passaggi che SQLite deve compiere per trovare le righe corrispondenti.

import sqlite3


def explain_query(search_name):
    """Explain the query execution plan for a SELECT query without an index."""

    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Usa EXPLAIN QUERY PLAN per analizzare come la query è eseguita
        cursor.execute('''
        EXPLAIN QUERY PLAN
        SELECT * FROM Students WHERE name = ?;
        ''', (search_name,))

        # Recupera e mostra il piano di query
        query_plan = cursor.fetchall()

        print("Query Plan:")
        for step in query_plan:
            print(step)


# Esempio: Analizzare il piano di query per la ricerca per nome
explain_query('Ojasvi Dhawan')

Quando si esegue questo codice, SQLite restituisce una panoramica di come intende eseguire la query. Ecco un esempio di ciò che la visualizzazione potrebbe assomigliare:

Query Plan:
(2, 0, 0, 'SCAN Students')

Questo indica che SQLite sta eseguendo una scansione completa della tabella Students (una scansione completa della tabella) per trovare le righe in cui la colonna name corrisponde al valore fornito (Ojasvi Dhawan). Poiché non esiste alcun indice sulla colonna name, SQLite deve esaminare ogni riga della tabella.

Come creare un indice

Creare un indice su una colonna consente a SQLite di trovare le righe più velocemente durante le operazioni di query. Invece di scannerizzare tutta la tabella, SQLite può usare l’indice per saltare direttamente alle righe relative, accelerando significativamente le query, specialmente quelle che coinvolgono grandi set di dati.

Per creare un indice, si usa il seguente comando SQL:

CREATE INDEX IF NOT EXISTS index-name ON table (column(s));

Nell’esempio seguente, creeremo un indice sulla colonna name della tabella Students. Ecco come lo puoi fare usando Python:

import sqlite3
import time


def create_index():
    """Create an index on the name column of the Students table."""
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Comando SQL per creare un indice sulla colonna name
        create_index_query = '''
        CREATE INDEX IF NOT EXISTS idx_name ON Students (name);
        '''

        # Misura l'orario di inizio
        start_time = time.perf_counter_ns()

        # Esegue il comando SQL per creare l'indice
        cursor.execute(create_index_query)

        # Misura l'orario di inizio
        end_time = time.perf_counter_ns()

        # Applica i cambiamenti
        connection.commit()

        print("Index on 'name' column created successfully!")

        # Calcola il tempo totale impiegato
        elapsed_time = (end_time - start_time) / 1000

        # Mostra i risultati e il tempo impiegato
        print(f"Query completed in {elapsed_time:.5f} microseconds.")


# Chiama la funzione per creare l'indice
create_index()

Output:

Index on 'name' column created successfully!
Query completed in 102768.60000 microseconds.

Anche se la creazione dell’indice richiede questo tempo (102768,6 microsecondi), è un’operazione una sola volta. Otterrai comunque un notevole incremento di velocità quando si eseguono molte query. Nelle sezioni seguenti, query la base di dati di nuovo per osservare le miglioramenti di prestazioni rese possibili da questo indice.

Come fare query con indici

In questa sezione, eseguiremo lo stesso query SELECT che abbiamo eseguito prima, ma questa volta faremo uso dell’indice che abbiamo creato sulla colonna name della tabella Students. Misureremo e registreremo il tempo di esecuzione per osservare le migliorie di prestazioni fornite dall’indice.

import sqlite3
import time


def query_with_index(student_name):
    """Query the Students table using an index on the name column."""
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Comando SQL per selezionare un studente per nome
        select_query = 'SELECT * FROM Students WHERE name = ?;'

        # Misura del tempo di esecuzione
        start_time = time.perf_counter_ns()  # Avvia il timer

        # Esegui il query con il nome dello studente fornito
        cursor.execute(select_query, (student_name,))
        result = cursor.fetchall()  # Recupera tutti i risultati

        end_time = time.perf_counter_ns()  # Ferma il timer

        # Calcola il tempo trascorso in microsecondi
        execution_time = (end_time - start_time) / 1000

        # Mostra i risultati e il tempo di esecuzione
        print(f"Query result: {result}")
        print(f"Execution time with index: {execution_time:.5f} microseconds")


# Esempio: Cerca un studente per nome
query_with_index('Ojasvi Dhawan')

Ecco cosa otteniamo nell’output:

Query result: [(104, 'Ojasvi Dhawan', 21, '[email protected]')]
Execution time with index: 390.70000 microseconds

Possiamo osservare una riduzione significativa del tempo di esecuzione rispetto all’esecuzione del query senza l’indice.

Analizziamo ora il piano di esecuzione del query per il query con l’indice sulla colonna name della tabella Students. Se eseguite lo stesso script di nuovo per spiegare il query, otterrete il seguente output:

Query Plan:
(3, 0, 0, 'SEARCH Students USING INDEX idx_name (name=?)')

Il piano ora mostra che il query utilizza l’indice idx_name, riducendo significativamente il numero di righe da scansione, il che porta ad una esecuzione del query più veloce.

Confronto dei risultati di performance

Ora, riassumiamo i risultati di performance ottenuti durante le interrogazioni con e senza indici.

Confronto dei tempi di esecuzione

Tipo di interrogazione Tempo di esecuzione (microsecondi)
Senza indice 1578.1
Con indice 390.7

Riepilogo del miglioramento delle performance

  • L’interrogazione con l’indice è circa 4,04 volte più veloce rispetto all’interrogazione senza l’indice.

  • Il tempo di esecuzione è migliorato di circa il 75,24% dopo l’aggiunta dell’indice.

Linee guida per l’utilizzo degli indici

Gli indici possono migliorare significativamente le performance del tuo database SQLite, ma devono essere utilizzati con cautela. Ecco alcune linee guida da considerare quando si lavora con gli indici:

Quando e perché utilizzare gli indici

  1. Colonne di interrogazione frequenti: Utilizza gli indici sulle colonne frequentemente utilizzate nelle interrogazioni SELECT, specialmente quelle utilizzate nelle clausole WHERE, JOIN e ORDER BY. Ciò perché l’indicizzazione di queste colonne può ridurre drasticamente il tempo di esecuzione delle interrogazioni.

  2. Constraint di unicità: Quando le colonne devono contenere valori unici (come nomi utente o indirizzi email), la creazione di un indice può enforcerli efficientemente.

  3. Set di dati grandi: Per le tabelle con un gran numero di record, gli indici diventano sempre più benefici. consentono ricerche rapide, elemento essenziale per mantenere la performance mentre i tuoi dati crescono.

  4. Indici composti: Considerare la creazione di indici composti per query che filtrano o ordinano multipli colonne. Ad esempio, se spesso cerci studenti per entrambi nome e eta, un indice su entrambe le colonne può ottimizzare queste query.

Potenziali svantaggi degli indici

Anche se gli indici forniscono vantaggi significativi, ci sono alcuni potenziali svantaggi:

  1. Operazioni di inserimento/aggiornamento più lente: Quando si inseriscono o aggiornano record in una tabella con indici, SQLite deve anche aggiornare l’indice, il che può rallentare queste operazioni. Questo avviene perché ogni inserimento o aggiornamento richiede un overheard aggiuntivo per mantenere la struttura dell’indice.

  2. Requisiti di archiviazione incrementati: Gli indici richiedono spazio aggiuntivo su disco. Per tabele grandi, il costo di archiviazione può essere significativo. Considerare questo quando si progetta lo schema della base dati, specialmente per sistemi con risorse di archiviazione limitate.

  3. Gestione complessa degli indici: La presenza di troppi indici può complicare la gestione del database. Può portare a situazioni in cui ci sono indici ridondanti, che possono degradare il rendimento invece di migliorarlo. L’indagine regolare e l’ottimizzazione degli indici è una buona pratica.

Gli indici sono strumenti potenti per l’ottimizzazione delle query del database, ma richiedono una considerazione attentiva. Raggiungere un equilibrio tra un migliore rendimento in lettura e il potenziale overhead sulle operazioni di scrittura è la chiave. Ecco alcune strategie per ottenere questo equilibrio:

  • Monitorare il rendimento delle query: Usare EXPLAIN QUERY PLAN di SQLite per analizzare come le query si comportano con e senza indici. Questo può aiutare a identificare quali indici sono benefici e quali potrebbero essere innecessari.

  • Manutenzione regolare: Revisionare periodiciamente gli indici e valutare se sono ancora necessari. Rimuovere gli indici ridondanti o poco usati per streamlinere le operazioni del database.

  • Testare e valutare: Prima di implementare gli indici in un ambiente di produzione, condurre test approfonditi per comprendere l’impatto sia sulle operazioni di lettura che di scrittura.

Seguendo queste migliori pratiche, puoi sfruttare i benefici dell’indicizzazione mentre minimizzi i possibili svantaggi, migliorando così le prestazioni e l’efficienza della vostra base dati SQLite.

Come gestire errori e eccezioni

In questa sezione, viene discusso come gestire errori e eccezioni durante l’utilizzo di SQLite in Python. La gestione corretta degli errori è cruciale per mantenere l’integrità del database e garantire che il vostro applicativo si comporti in modo predicibile.

Errori comuni nelle operazioni SQLite

Interagendo con un database SQLite, potrebbero emergere diversi errori comuni:

  1. Violazioni di vincoli: Questo avviene quando cercate di inserire o aggiornare dati che violano un vincolo del database, come l’unicità della chiave primaria o i vincoli della chiave esterna. Ad esempio, cercare di inserire una chiave primaria duplicata richiederà un errore.

  2. Incompatibilità di Tipo di Dato: Il tentativo di inserire dati di tipo sbagliato (per esempio, inserire una stringa in un punto in cui è atteso un numero) può portare a un errore.

  3. Errori di Blocco Database: Se un database è in fase di scrittura da un’altra procedura o connessione, cercare di accedervi può portare ad un errore di “database bloccato”.

  4. Errori di Sintassi: Errori nell’uso della sintassi SQL comporteranno errori durante l’esecuzione dei comandi.

Come Usare Gestione Eccezioni in Python

Le meccanismi di gestione delle eccezioni integrati di Python (try e except) sono essenziali per la gestione degli errori nelle operazioni SQLite. Usando questi costrutti, è possibile catturare eccezioni e rispondere appropriatamente senza far crashare il programma.

Ecco un semplice esempio di come gestire gli errori durante l’inserimento di dati nel database:

import sqlite3


def add_customer_with_error_handling(name, balance):
    """Add a new customer with error handling."""
    try:
        with sqlite3.connect('my_database.db') as connection:
            cursor = connection.cursor()
            cursor.execute(
                "INSERT INTO Customers (name, balance) VALUES (?, ?);", (name, balance))
            connection.commit()
            print(f"Added customer: {name} with balance: {balance}")

    except sqlite3.IntegrityError as e:
        print(f"Error: Integrity constraint violated - {e}")

    except sqlite3.OperationalError as e:
        print(f"Error: Operational issue - {e}")

    except Exception as e:
        print(f"An unexpected error occurred: {e}")


# Esempio di utilizzo
add_customer_with_error_handling('Vishakha', 100.0)  # Valido
add_customer_with_error_handling('Vishakha', 150.0)  # Entrata duplicata

In questo esempio:

  • Catturiamo IntegrityError, che viene sollevato per violazioni come le violazioni delle condizioni di unicità.

  • Catturiamo OperationalError per problemi generali legati al database (come errori di blocco del database).

  • Ci è anche un blocco except generico per gestire qualsiasi eccezione imprevista.

Output:

Added customer: Vishakha with balance: 100.0
Error: Integrity constraint violated - UNIQUE constraint failed: Customers.name

Best Practices for Ensuring Database Integrity

  1. Usa le transazioni: Usa sempre le transazioni (come discusso nella sezione precedente) quando esegui operazioni multiple correlate. Questo aiuta a garantire che tutte le operazioni abbiano successo o nessuna di esse, mantenendo la coerenza.

  2. Convalida i dati di input: Prima di eseguire comandi SQL, convalida i dati di input per assicurarti che rispettino i criteri attesi (ad esempio, tipi corretti, all’interno di intervalli consentiti).

  3. Gestisci eccezioni specifiche: Gestisci sempre eccezioni specifiche per gestire in modo appropriato diversi tipi di errori. Ciò consente una gestione degli errori e un debug più chiari.

  4. Registra gli errori: Invece di stampare gli errori solo sulla console, considera di registrarli su un file o su un sistema di monitoraggio. Questo ti aiuterà a tracciare i problemi in produzione.

  5. Decadimento Elegante: Progetta la tua applicazione per gestire gli errori in maniera elegante. Se un’operazione fallisce, fornisci un feedback significativo all’utente invece di far crashare l’applicazione.
  6. Backup Regolare Dati: Esegui regolarmente il backup del tuo database per prevenire la perdita di dati in caso di malfunzionamenti critici o corruzioni.

  7. Utilizza dichiarazioni preparate: Le dichiarazioni preparate aiutano a prevenire gli attacchi di iniezione SQL e possono anche fornire prestazioni migliori per le query ripetute.

Come Esportare e Importare Dati [Sezione Bonus]

In questa sezione, impareremo come esportare dati da un database SQLite in formati comuni come CSV e JSON, nonché come importare dati in SQLite da questi formati utilizzando Python. Questo è utile per la condivisione dei dati, il backup e l’integrazione con altre applicazioni.

Esportazione Dati da SQLite a CSV

Esportare i dati in un file CSV (Comma-Separated Values) è semplice utilizzando le librerie incorporate di Python. I file CSV sono ampiamente utilizzati per lo storage e lo scambio di dati, rendendoli un formato comodo per l’esportazione dati.

Ecco come esportare dati da una tabella SQLite in un file CSV:

import sqlite3
import csv

def export_to_csv(file_name):
    """Export data from the Customers table to a CSV file."""
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Esegui una query per recuperare tutti i dati del cliente
        cursor.execute("SELECT * FROM Customers;")
        customers = cursor.fetchall()

        # Scrivi dati in CSV
        with open(file_name, 'w', newline='') as csv_file:
            csv_writer = csv.writer(csv_file)
            csv_writer.writerow(['ID', 'Name', 'Balance'])  # Scrittura dell'intestazione
            csv_writer.writerows(customers)  # Scrittura delle righe dati

        print(f"Data exported successfully to {file_name}.")

# Esempio di utilizzo
export_to_csv('customers.csv')

Come esportare dati in JSON

Anche voi può esportare dati in un file JSON (JavaScript Object Notation), che è un formato popolare per l’interscambio di dati, specialmente nelle applicazioni web.

Ecco un esempio di come esportare dati in JSON:

import json
import sqlite3


def export_to_json(file_name):
    """Export data from the Customers table to a JSON file."""
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Esegui una query per recuperare tutti i dati del cliente
        cursor.execute("SELECT * FROM Customers;")
        customers = cursor.fetchall()

        # Converti i dati in una lista di dizionari
        customers_list = [{'ID': customer[0], 'Name': customer[1],
                           'Balance': customer[2]} for customer in customers]

        # Scrivi dati in JSON
        with open(file_name, 'w') as json_file:
            json.dump(customers_list, json_file, indent=4)

        print(f"Data exported successfully to {file_name}.")


# Esempio di utilizzo
export_to_json('customers.json')

Come importare dati in SQLite da CSV

Potete anche importare dati da un file CSV in una base dati SQLite. Questo è utile per popolare la vostra base dati con dataset esistenti.

Ecco come importare dati da un file CSV:

import csv
import sqlite3


def import_from_csv(file_name):
    """Import data from a CSV file into the Customers table."""
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Apre il file CSV per la lettura
        with open(file_name, 'r') as csv_file:
            csv_reader = csv.reader(csv_file)
            next(csv_reader)  # Salta la riga dell'intestazione

            # Inserisci ogni riga nella tabella Clienti
            for row in csv_reader:
                cursor.execute(
                    "INSERT INTO Customers (name, balance) VALUES (?, ?);", (row[1], row[2]))

        connection.commit()
        print(f"Data imported successfully from {file_name}.")


# Esempio di utilizzo
import_from_csv('customer_data.csv')

Come Importare Dati in SQLite da JSON

Allo stesso modo, l’importazione dei dati da un file JSON è semplice. Puoi leggere il file JSON e inserire i dati nella tua tabella SQLite.

Ecco come fare:

import json
import sqlite3


def import_from_json(file_name):
    """Import data from a JSON file into the Customers table."""
    with sqlite3.connect('my_database.db') as connection:
        cursor = connection.cursor()

        # Apre il file JSON per la lettura
        with open(file_name, 'r') as json_file:
            customers_list = json.load(json_file)

            # Inserisci ciascun cliente nella tabella Clienti
            for customer in customers_list:
                cursor.execute("INSERT INTO Customers (name, balance) VALUES (?, ?);", (customer['Name'], customer['Balance']))

        connection.commit()
        print(f"Data imported successfully from {file_name}.")


# Esempio di utilizzo
import_from_json('customer_data.json')

Conclusione

E questo è tutto! Questa guida ti ha introdotto ai fondamenti del lavoro con SQLite in Python, coprendo tutto, dall’allestimento dell’ambiente fino all’interrogazione e manipolazione dei dati, nonché l’esportazione e l’importazione delle informazioni. Spero che tu l’abbia trovata utile e che abbia suscitato il tuo interesse nell’usare SQLite per i tuoi progetti.

Ora è il momento di mettere in pratica le tue nuove conoscenze! Ti incoraggio a creare il tuo progetto utilizzando SQLite e Python. Che si tratti di un’applicazione semplice per la gestione della tua libreria, di uno strumento per la gestione del budget, o qualcosa di unico, le possibilità sono infinite.

Una volta completato il tuo progetto, condividilo su Twitter e taggami! Sarò felice di vedere cosa hai creato e festeggiare i tuoi successi.

Tutto il codice di questo tutorial si può trovare su GitHub. Grazie per averlo seguito e buon coding!

Genera una TOC (Tavola delle Contents) per i tuoi articoli freeCodeCamp gratuitamente utilizzando lo strumento TOC Generator.