MySQL Insert in Python
Impara a inserire righe singole, righe multiple e a gestire gli ID auto-increment in MySQL da Python con mysql-connector-python.
Inserire dati in una tabella MySQL da Python richiede tre cose: una connessione attiva, un'istruzione SQL parametrizzata e una chiamata a commit(). Questo capitolo tratta gli inserimenti di singole righe, gli inserimenti in blocco con executemany(), il recupero dell'ID generato automaticamente per la nuova riga, la gestione dei duplicati con ON DUPLICATE KEY UPDATE e le insidie più comuni per i principianti.
Prerequisiti
Prima di eseguire qualsiasi esempio qui presente, assicurati di avere:
- Python 3.x e un server MySQL in esecuzione
mysql-connector-pythoninstallato:
pip install mysql-connector-python- Un database e una tabella
customersgià creati — vedi MySQL Create Database e MySQL Create Table se devi prima configurarli.
Gli esempi presuppongono questa definizione di tabella:
CREATE TABLE IF NOT EXISTS customers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address VARCHAR(255)
);Connessione a MySQL
Ogni operazione inizia con un oggetto connessione. Passa il tuo host, le credenziali e il nome del database a mysql.connector.connect(), poi crea un cursore:
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()L'oggetto cursor invia SQL al server. Riutilizza la stessa connessione per più istruzioni invece di riconnetterti ogni volta.
Inserimento di una singola riga
Usa l'istruzione SQL INSERT INTO con i segnaposto %s e passa i valori effettivi come una tupla. Non costruire mai la stringa della query con la formattazione % o f-string di Python — questo espone il codice all'SQL injection.
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "INSERT INTO customers (name, address) VALUES (%s, %s)"
val = ("John", "Highway 21")
mycursor.execute(sql, val)
mydb.commit()
print(mycursor.rowcount, "record inserted.")
except Error as e:
print(f"Error: {e}")
mydb.rollback()
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Punti chiave:
%sè la sintassi del segnaposto permysql-connector-pythonindipendentemente dal tipo di dato della colonna (stringhe, interi, date usano tutti%s).mydb.commit()è obbligatorio — senza di esso, l'inserimento non viene mai scritto su disco. MySQL racchiude le istruzioni DML in transazioni implicite; devi eseguire il commit per finalizzarle.mydb.rollback()nel bloccoexceptannulla eventuali modifiche parziali se l'istruzione fallisce.
Recupero dell'ID Auto-Increment
Dopo un inserimento riuscito, mycursor.lastrowid contiene la chiave primaria AUTO_INCREMENT che MySQL ha assegnato alla nuova riga:
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "INSERT INTO customers (name, address) VALUES (%s, %s)"
val = ("Alice", "Maple Street 7")
mycursor.execute(sql, val)
mydb.commit()
print("Inserted row ID:", mycursor.lastrowid)
except Error as e:
print(f"Error: {e}")
mydb.rollback()
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Output di esempio:
Inserted row ID: 1Il valore è 0 se la tabella non ha una colonna AUTO_INCREMENT. Usa lastrowid per fare riferimento immediatamente al nuovo record nelle tabelle correlate (ad esempio, per inserire una riga corrispondente in una tabella orders).
Inserimento di più righe
executemany() invia un elenco di tuple di valori in un unico round-trip al server, il che è molto più efficiente che chiamare execute() in un ciclo:
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "INSERT INTO customers (name, address) VALUES (%s, %s)"
vals = [
("Peter", "Lowstreet 4"),
("Amy", "Apple St 652"),
("Hannah", "Mountain 21"),
("Michael", "Valley 345"),
("Sandy", "Ocean Blvd 2"),
("Betty", "Green Grass 1"),
("Richard", "Sky St 331"),
("Susan", "One Way 98"),
("Vicky", "Yellow Garden 2"),
("Ben", "Park Lane 38"),
("William", "Central St 954"),
("Chuck", "Main Road 989"),
("Viola", "Sideway 1633"),
]
mycursor.executemany(sql, vals)
mydb.commit()
print(mycursor.rowcount, "records inserted.")
except Error as e:
print(f"Error: {e}")
mydb.rollback()
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Output di esempio:
13 records inserted.mycursor.rowcount dopo executemany() restituisce il numero totale di righe interessate su tutte le tuple.
Quando preferire executemany() rispetto a un ciclo
| Approccio | Round-trip | Usa quando |
|---|---|---|
execute() in un ciclo | Uno per riga | Le righe dipendono dai risultati dell'una dell'altra |
executemany() | Uno totale | Inserimento di righe indipendenti in blocco |
Per dataset molto grandi (decine di migliaia di righe), considera di suddividere in blocchi da 500–1000 righe in modo che un singolo errore non scarta l'intera operazione.
Inserimento senza errori sui duplicati
Se la tua tabella ha un vincolo UNIQUE e provi a inserire una riga già esistente, MySQL genera un errore di chiave duplicata. Due strategie comuni evitano questo problema:
INSERT IGNORE
INSERT IGNORE salta silenziosamente le righe che violano un vincolo univoco:
sql = "INSERT IGNORE INTO customers (name, address) VALUES (%s, %s)"
mycursor.execute(sql, ("John", "Highway 21"))
mydb.commit()
print(mycursor.rowcount, "row(s) affected") # 0 if row already existedON DUPLICATE KEY UPDATE
ON DUPLICATE KEY UPDATE esegue un aggiornamento quando la chiave univoca esiste già, rendendo l'istruzione un "upsert" (inserimento o aggiornamento):
sql = """
INSERT INTO customers (name, address)
VALUES (%s, %s)
ON DUPLICATE KEY UPDATE address = VALUES(address)
"""
mycursor.execute(sql, ("John", "New Address 5"))
mydb.commit()
# rowcount is 1 for insert, 2 for update, 0 if row existed but was unchanged
print(mycursor.rowcount, "row(s) affected")Usa ON DUPLICATE KEY UPDATE quando vuoi che venga memorizzato il valore più recente indipendentemente dal fatto che la riga sia nuova o già esistente.
Inserimento di dati da un dizionario
Quando i dati provengono come elenco di dizionari (ad esempio, da un payload JSON analizzato), puoi costruire l'SQL e i valori dinamicamente:
import mysql.connector
from mysql.connector import Error
customers = [
{"name": "Eva", "address": "Elm Street 3"},
{"name": "Oscar", "address": "Birch Lane 9"},
]
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "INSERT INTO customers (name, address) VALUES (%(name)s, %(address)s)"
mycursor.executemany(sql, customers)
mydb.commit()
print(mycursor.rowcount, "records inserted.")
except Error as e:
print(f"Error: {e}")
mydb.rollback()
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()I segnaposto con nome (%(name)s) rendono l'intento più chiaro quando si usano dizionari e riducono il rischio di disallineare i valori posizionali.
Errori comuni da evitare
Dimenticare commit() — L'inserimento sembra funzionare (nessun errore) ma nessun dato viene salvato. Chiama sempre mydb.commit() dopo le istruzioni DML.
Costruire SQL con la formattazione di stringhe — Usare f-string o la formattazione % per incorporare input utente è la fonte più comune di SQL injection. Passa sempre i valori come secondo argomento a execute().
Lasciare le connessioni aperte — Usa un blocco finally (o un context manager) per assicurarti che cursor.close() e mydb.close() vengano sempre chiamati.
Usare INSERT quando la tabella non è stata ancora creata — Otterrai un errore Table 'mydatabase.customers' doesn't exist. Esegui prima CREATE TABLE o verifica con SHOW TABLES. Vedi MySQL Create Table.
Cosa fare dopo
Una volta inserite le righe, in genere vorrai rileggerle. Vedi MySQL Select per le query SELECT, MySQL Where per il filtraggio e MySQL Update per la modifica delle righe esistenti.