Nella lezione precedente, abbiamo creato le tabelle del database. Ora, ci concentreremo sull'inserimento dei dati, affinché il database contenga le informazioni necessarie al funzionamento del nostro sito web o dell'applicazione.
Con Node.js possiamo inserire i dati nelle tabelle MySQL utilizzando l'istruzione SQL INSERT INTO.
Per inserire un record (cioè una riga) in una tabella, utilizziamo l'istruzione INSERT INTO specificando il nome della tabella e i valori da inserire:
const mysql = require("mysql");
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: "la_tua_password",
database: "esempio"
});
con.connect(function (err) {
if (err) throw err;
const sql = "INSERT INTO utenti (nome, email) VALUES ('Mario', '[email protected]');";
con.query(sql, function (err, result) {
if (err) throw err;
console.log("ID del nuovo utente: " + result.insertId);
});
});Nell'esempio:
nome e email.id non viene specificata nella query perché è definita come AUTO_INCREMENT. Questa proprietà del database fa sì che l'ID venga assegnato e incrementato automaticamente per ogni nuovo record (riga) inserito, senza che sia necessario fornirne manualmente il valore. Ad esempio, se sono già state inserite 3 righe (con id uguali a 1, 2, 3), il quarto record avrà id = 4.VALUES per indicare i valori da inserire, nell'ordine corrispondente alle colonne specificate.result.insertId contiene l'ID del record appena inserito, utile per operazioni successive.Nella maggior parte dei casi, i dati da inserire provengono da variabili di cui non possiamo conoscere a priori il contenuto (ad esempio, da un form compilato dall'utente). Possiamo utilizzare i placeholder (?) per inserire valori in modo sicuro:
// Dati inseriti dall'utente
const nome = "Lucia";
const email = "[email protected]";
const sql = "INSERT INTO utenti (nome, email) VALUES (?, ?);";
con.query(sql, [nome, email], function (err, result) {
if (err) throw err;
console.log("Utente inserito con ID: " + result.insertId);
});Nell'esempio:
? come placeholder nella query SQL.[nome, email] come secondo parametro di con.query().? viene sostituito con "Lucia", mentre il secondo ? con "[email protected]".req.body, req.query o altre fonti esterne: un utente malintenzionato può inserire stringhe contenenti comandi SQL (come ' OR '1'='1) che modificano la query.Per inserire più record in una sola operazione, possiamo utilizzare un array bidimensionale con tutti i valori. Si tratta di una lista di dati che MySQL può inserire autonomamente in una sola istruzione. Per farlo, basta inserire la lista come parametro di con.query():
const sql = "INSERT INTO utenti (nome, email) VALUES ?;";
const valori = [
["Giovanni Verdi", "[email protected]"],
["Anna Neri", "[email protected]"],
["Paolo Gialli", "[email protected]"]
];
con.query(sql, [valori], function (err, result) {
if (err) throw err;
console.log("Numero di record inseriti: " + result.affectedRows);
});Nell'esempio, utilizziamo un singolo ? dopo VALUES. Creiamo un array bidimensionale valori dove ogni elemento è un sotto-array contenente i dati di un utente.
Basta passare [valori] come secondo parametro (bisogna utilizzare le parentesi quadre aggiuntive per farlo correttamente).
Nell'esempio, result.affectedRows indica quanti record sono stati inseriti. Nell'esempio, sono 3.
Per ora abbiamo soltanto inserito dati sotto forma di stringhe all'interno delle tabelle. Tuttavia, è anche possibile inserire diversi tipi di dati in una tabella leggermente più complessa delle precedenti. Nell'esempio, creiamo una tabella che contiene la lista dei prodotti di un negozio online:
const sql = `INSERT INTO prodotti (nome, descrizione, prezzo, disponibile, data_aggiunta)
VALUES (?, ?, ?, ?, ?);`;
const valori = [
"Laptop",
"Computer portatile ad alte prestazioni",
1299.99,
true,
new Date()
];
con.query(sql, valori, function (err, result) {
if (err) throw err;
console.log("Prodotto inserito con ID: " + result.insertId);
});Nell'esempio:
nome), un testo lungo (descrizione), un numero decimale (prezzo), un valore booleano (disponibile) e una data (data_aggiunta).true e false (salvati come 1 e 0).new Date() che genera la data odierna tramite JavaScript.È importante gestire correttamente gli errori che possono verificarsi durante l'inserimento dei dati, come le violazioni di vincoli UNIQUE o NOT NULL.
Il metodo con.query() permette di conoscere se si è verificato un errore attraverso l'oggetto err. In particolare, err.code contiene il codice dell'errore MySQL.
In un’applicazione reale che utilizza MySQL, si cerca di gestire ogni errore in modo appropriato invece di interrompere semplicemente il programma.
Vediamo un esempio:
const sql = "INSERT INTO utenti (nome, email) VALUES (?, ?);";
const valori = ["Marco", "[email protected]"];
con.query(sql, valori, function (err, result) {
if (err) {
if (err.code === "ER_DUP_ENTRY") {
console.log("Errore: questa email è già registrata");
} else if (err.code === "ER_BAD_NULL_ERROR") {
console.log("Errore: un campo obbligatorio è vuoto");
} else {
console.log("Errore durante l'inserimento: " + err.message);
}
return;
}
console.log("Utente inserito correttamente");
});Nell'esempio, abbiamo diviso i vari casi in cui si può verificare un errore attraverso if e else:
ER_DUP_ENTRY indica una violazione del vincolo UNIQUE (ovvero, viene inserito un valore già presente in una delle righe inserite precedentemente nella tabella).ER_BAD_NULL_ERROR indica che un campo NOT NULL (che non può essere vuoto) non contiene nulla.Per prevenire errori quando si tenta di inserire un record che violerebbe un vincolo UNIQUE, si può utilizzare l'istruzione INSERT IGNORE.
Utilizzando INSERT IGNORE, se il record viola un vincolo UNIQUE, MySQL non genera un errore ma semplicemente non inserisce la nuova riga di dati. In questo modo, non si interrompe l'esecuzione del programma.
const sql = "INSERT IGNORE INTO utenti (nome, email) VALUES (?, ?);";
const valori = ["Sara Viola", "[email protected]"];
con.query(sql, valori, function (err, result) {
if (err) throw err;
if (result.affectedRows === 0) {
console.log("Record non inserito: email già esistente");
} else {
console.log("Utente inserito con ID: " + result.insertId);
}
});Nell'esempio, result.affectedRows sarà 0 se il record non è stato inserito, mentre 1 se è stata aggiunta una nuova riga nella tabella.
Se non siamo certi che una riga con vincolo UNIQUE esista già nella tabella, possiamo usare ON DUPLICATE KEY UPDATE: in questo modo MySQL aggiorna il record esistente oppure ne inserisce uno nuovo in base alla necessità, evitando di generare un errore. Vediamo un esempio:
const sql = `INSERT INTO utenti (nome, email) VALUES (?, ?)
ON DUPLICATE KEY UPDATE nome = ?;`;
const valori = ["Roberto", "[email protected]", "Roberto"];
con.query(sql, valori, function (err, result) {
if (err) throw err;
if (result.affectedRows === 1) {
console.log("Nuovo utente inserito");
} else if (result.affectedRows === 2) {
console.log("Utente esistente aggiornato");
}
});In questo caso, se l'email esiste già all'interno della tabella, invece di generare un errore, MySQL aggiorna il campo nome con "Roberto".
Vediamo un esempio pratico che combina Express (che abbiamo visto nella lezione su Express) con MySQL per inserire dati ricevuti da un form HTML.
Per prima cosa, creiamo un file index.html che contenga il nostro form:
<form action="/registra" method="POST">
<input type="text" name="nome" placeholder="Nome">
<input type="text" name="email" placeholder="Email">
<input type="submit" value="Invia">
</form>Una volta che l'utente avrà cliccato "Invia", verrà reindirizzato a /registra. Vediamo come creare lo script in Node.js che gestisca i dati inseriti:
const express = require("express");
const mysql = require("mysql");
const app = express();
app.use(express.urlencoded({ extended: true }));
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: "la_tua_password",
database: "esempio"
});
con.connect(function (err) {
if (err) throw err;
console.log("Connesso al database");
});
app.post("/registra", function (req, res) {
const nome = req.body.nome;
const email = req.body.email;
const sql = "INSERT INTO utenti (nome, email) VALUES (?, ?);";
con.query(sql, [nome, email], function (err, result) {
if (err) {
res.send("Errore durante la registrazione: " + err.message);
return;
}
res.send("Registrazione completata! Il tuo ID è: " + result.insertId);
});
});
app.listen(3000);Utilizziamo Express per gestire le richieste POST provenienti dal form. req.body contiene i dati inviati dall'utente. Inseriamo i dati nel database e rispondiamo all'utente con un messaggio di conferma o di errore.