SQLite - C/C++ per Principianti

Ciao a tutti, aspiranti programmatori! Oggi ci imbarcheremo in un viaggio emozionante nel mondo di SQLite utilizzando C/C++. Non preoccupatevi se non avete mai scritto una riga di codice prima - inizieremo dai concetti di base e lavoreremo gradualmente. Alla fine di questo tutorial, rimarrete sorpresi di cosa potrete accomplire!

SQLite - C/C++

Cos'è SQLite?

Prima di immergerci nel codice, capiremo cos'è SQLite. Immagina di avere un taccuino digitale dove puoi conservare tutte le sorti di informazioni in modo organizzato. Questo è essenzialmente ciò che è SQLite - un database leggero e basato su file che non richiede un processo server separato. È come avere un mini-database direttamente in tasca!

API dell'Interfaccia C/C++

Per interagire con SQLite utilizzando C/C++, dobbiamo utilizzare qualcosa chiamato API (Application Programming Interfaces). Pensa a queste come strumenti speciali che permettono al nostro programma C/C++ di comunicare con SQLite. Ecco le principali API che useremo:

Funzione API Descrizione
sqlite3_open() Apre una connessione a un database SQLite
sqlite3_exec() Esegue istruzioni SQL
sqlite3_close() Chiude la connessione al database
sqlite3_errmsg() Restituisce messaggi di errore

Non preoccupatevi se queste sembrano spaventose ora. Esploreremo ognuna con tanti esempi!

Connessione al Database

Iniziamo connettendoci a un database. Questo è come aprire il nostro taccuino digitale per iniziare a scrivere.

#include <stdio.h>
#include <sqlite3.h>

int main() {
sqlite3 *db;
int rc = sqlite3_open("test.db", &db);

if (rc) {
fprintf(stderr, "Impossibile aprire il database: %s\n", sqlite3_errmsg(db));
return(0);
} else {
fprintf(stderr, "Database aperto con successo\n");
}

sqlite3_close(db);
return 0;
}

Spieghiamo questo codice:

  1. Includiamo gli header necessari: stdio.h per l'input/output e sqlite3.h per le funzioni SQLite.
  2. In main(), dichiariamo un puntatore a sqlite3, che rappresenta la nostra connessione al database.
  3. Utilizziamo sqlite3_open() per aprire (o creare) un database chiamato "test.db".
  4. Controlliamo se la connessione è stata riuscita. In caso contrario, stampiamo un messaggio di errore.
  5. Infine, chiudiamo la connessione al database con sqlite3_close().

Creazione di una Tabella

Ora che abbiamo il nostro taccuino aperto, creiamo una pagina per conservare alcune informazioni. In termini di database, chiamiamo questo una tabella.

int main() {
sqlite3 *db;
char *zErrMsg = 0;
int rc;

rc = sqlite3_open("test.db", &db);

if (rc) {
fprintf(stderr, "Impossibile aprire il database: %s\n", sqlite3_errmsg(db));
return(0);
}

char *sql = "CREATE TABLE STUDENTS("
"ID INT PRIMARY KEY     NOT NULL,"
"NAME           TEXT    NOT NULL,"
"AGE            INT     NOT NULL,"
"GRADE          CHAR(1) );";

rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Errore SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Tabella creata con successo\n");
}

sqlite3_close(db);
return 0;
}

In questo esempio:

  1. Apriamo il database come prima.
  2. Definiamo un'istruzione SQL per creare una tabella chiamata STUDENTS con le colonne ID, NAME, AGE e GRADE.
  3. Utilizziamo sqlite3_exec() per eseguire questa istruzione SQL.
  4. Controlliamo se l'esecuzione è stata riuscita e stampiamo un messaggio appropriato.

Operazione INSERT

Ottimo! Abbiamo la nostra tabella. Ora aggiungiamosome dati.

char *sql = "INSERT INTO STUDENTS (ID,NAME,AGE,GRADE) "
"VALUES (1, 'Alice', 20, 'A' ); "
"INSERT INTO STUDENTS (ID,NAME,AGE,GRADE) "
"VALUES (2, 'Bob', 21, 'B' ); ";

rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Errore SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Record inseriti con successo\n");
}

Qui, stiamo inserendo due record nella nostra tabella STUDENTS. L'istruzione SQL utilizza la sintassi INSERT INTO per aggiungere nuove righe.

Operazione SELECT

Ora, recuperiamo i dati che abbiamo appena inserito. Questo è dove la magia vera dei database si rivela!

static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
for(int i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}

// In main()
char *sql = "SELECT * from STUDENTS";
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Errore SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Operazione eseguita con successo\n");
}

Questo esempio introduce una funzione di callback. Quando selezioniamo dati, SQLite chiama questa funzione per ogni riga del risultato. È come avere un assistente che legge ogni voce nel nostro taccuino!

Operazione UPDATE

Cosa succede se commettiamo un errore e dobbiamo cambiare alcuni dati? È qui che entra in gioco UPDATE.

char *sql = "UPDATE STUDENTS set GRADE = 'A' where ID=2";
rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Errore SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Record aggiornati con successo\n");
}

Questa istruzione SQL cambia il voto di Bob a A. Ottimo lavoro, Bob!

Operazione DELETE

A volte, dobbiamo rimuovere dati. Vediamo come eliminare un record.

char *sql = "DELETE from STUDENTS where ID=2";
rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);

if (rc != SQLITE_OK) {
fprintf(stderr, "Errore SQL: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Record eliminato con successo\n");
}

Questo rimuove il record di Bob dalla nostra tabella. Mi dispiace, Bob!

Ecco fatto! Abbiamo coperto i concetti di base di lavoro con SQLite in C/C++. Ricorda, programmare è come imparare una nuova lingua - richiede pratica. Non scoraggiarti se le cose non diventano chiare subito. Continua a sperimentare, e presto sarai in grado di scrivere applicazioni di database come un professionista!

Credits: Image by storyset