W3docs

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-python installato:
pip install mysql-connector-python

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 per mysql-connector-python indipendentemente 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 blocco except annulla 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: 1

Il 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

ApproccioRound-tripUsa quando
execute() in un cicloUno per rigaLe righe dipendono dai risultati dell'una dell'altra
executemany()Uno totaleInserimento 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 existed

ON 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.

Was this page helpful?