Gestione degli errori e codici SQLSTATE per mssql-python

Il driver mssql-python definisce una gerarchia standard di eccezioni, schemi comuni di gestione degli errori e mappature di codice SQLSTATE per SQL Server e Azure SQL.

Gerarchia delle eccezioni

Il driver mssql-python segue la gerarchia delle eccezioni DB-API 2.0 (PEP 249):

Exception (builtins)
├── Warning
└── Error
    ├── InterfaceError
    └── DatabaseError
        ├── DataError
        ├── OperationalError
        ├── IntegrityError
        ├── InternalError
        ├── ProgrammingError
        └── NotSupportedError

ConnectionStringParseError (standalone, not part of hierarchy)

Descrizioni delle eccezioni

Individua l'eccezione più specifica che si adatta alla tua situazione. Ad esempio, per le IntegrityError violazioni dei vincoli su INSERT/UPDATE operations e ProgrammingError per problemi di sintassi SQL durante lo sviluppo. Prendi la classe base Error solo come riserva.

Eccezione Quando generato
Warning Avvertenze non fatali dal database.
Error Classe base per tutti gli errori del database.
InterfaceError Errori legati all'interfaccia del database (driver), non al database stesso.
DatabaseError Errori legati al database.
DataError Errori dovuti a problemi con i dati elaborati (divisione per zero, valore fuori intervallo).
OperationalError Errori legati all'operazione del database (connessione persa, allocazione della memoria, errori di transazione).
IntegrityError Errori quando l'integrità del database è interessata (violazione della chiave esterna, vincolo unico).
InternalError Errori interni al database (cursore non valido, transazione fuori sincrono).
ProgrammingError Errori di programmazione (errori di sintassi, tabella non trovata, numero sbagliato di parametri).
NotSupportedError Funzionalità non supportata dal database o dal driver.
ConnectionStringParseError Sintassi di stringa di connessione invalida o parole chiave sconosciute.

Gestione di base degli errori

Usa i blocchi try-except per gestire errori nel database:

import mssql_python

try:
    conn = mssql_python.connect(connection_string)
    cursor = conn.cursor()
    cursor.execute("INSERT INTO Production.Product (Name) VALUES (%(name)s)", {"name": "Test"})
    conn.commit()
except mssql_python.IntegrityError as e:
    print(f"Constraint violation: {e}")
    conn.rollback()
except mssql_python.ProgrammingError as e:
    print(f"SQL syntax error: {e}")
except mssql_python.OperationalError as e:
    print(f"Connection or operational error: {e}")
except mssql_python.Error as e:
    print(f"Database error: {e}")
finally:
    if 'conn' in locals():
        conn.close()

Eccezioni di accesso tramite la connessione

Puoi individuare eccezioni tramite l'istanza di connessione:

try:
    cursor.execute("INVALID SQL")
except conn.ProgrammingError as e:
    print(f"Caught via connection: {e}")

Struttura del messaggio di errore

Gli oggetti eccezione mssql-python espongono tre attributi che provengono dalla classe base delException driver:

Attribute Source Descrizione
driver_error Driver Python Il testo inglese standardizzato scelto dallo SQLSTATE restituì da ODBC (ad esempio, "Communication link failure", "Invalid authorization specification", "Syntax error or access violation"). Stabile tra le uscite; sicuro da abbinare con substringhe.
ddbc_error Connettività Diretta con il Database (DDBC) Il messaggio lato server, tipicamente preceduto da [Microsoft][SQL Server]. Il formato non è un contratto stabile.
message Composto f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". Questo è ciò che str(exc) ritorna.
try:
    cursor.execute("SELECT * FROM no_such_table;")
except mssql_python.ProgrammingError as exc:
    print(exc.driver_error)  # Base table or view not found
    print(exc.ddbc_error)    # [Microsoft][SQL Server]Invalid object name 'no_such_table'.
    print(exc)               # Driver Error: Base table or view not found; DDBC Error: ...

Il numero di errore del motore SQL Server (come 208 o 40501) non è esposto come attributo e non è incorporato in modo affidabile in nessuna delle due stringhe. Classifica gli errori per sottoclasse eccezione più driver_error testo. Per il throttling di Azure SQL, vedi Retry logic.

Classificazione SQLSTATE

mssql-python utilizza lo stato SQLSTATE restituito da ODBC per scegliere sia la sottoclasse eccezione Python sia il driver_error testo. La mappatura completa di SQLSTATE → eccezioni è presente exceptions.py nel driver source. La sezione successiva elenca gli stati SQL che appaiono più spesso con SQL Server e Azure SQL.

Errori di connessione

I guasti di connessione da mssql_python.connect() raise mssql_python.OperationalError, identici ad altri guasti di connettività:

import mssql_python

try:
    conn = mssql_python.connect(
        "Server=unreachable-server.database.windows.net;"
        "Database=<database>;"
        "Authentication=ActiveDirectoryDefault;"
        "Encrypt=yes"
    )
except mssql_python.OperationalError as e:
    print(f"Connection failed: {e.driver_error}")
    # e.driver_error: "Client unable to establish connection"

Errori della stringa di connessione

Gli errori di parsing delle stringhe di connessione aumentano ConnectionStringParseError:

try:
    conn = mssql_python.connect("Servr=localhost;")  # Typo
except mssql_python.ConnectionStringParseError as e:
    print(f"Invalid connection string: {e}")
    # Output: Unknown keyword 'Servr'

Riferimento al codice SQLSTATE

I codici SQLSTATE sono codici di cinque caratteri che identificano le condizioni di errore. I primi due caratteri indicano la classe, e gli ultimi tre la sottoclasse. Raramente è necessario ispezionare direttamente questi codici. Invece, individua il tipo di eccezione Python appropriato (indicato nella colonna "Eccezione"). Usa i codici SQLSTATE quando devi distinguere tra specifiche condizioni di errore all'interno dello stesso tipo di eccezione, ad esempio per differenziare un deadlock (40001) da un guasto generale della connessione (08S01).

Classe 00 - Completamento con successo

SQLSTATE Eccezione Descrizione
00000 None Success

Classe 01 - Avviso

SQLSTATE Eccezione Descrizione
01000 Warning Avviso generale
01001 Warning Conflitto dell'operazione di cursore
01002 Warning Errore di disconnessione
01003 DataError Valore NULL eliminato nella funzione set
01004 DataError Dati stringa, troncamento destro
01006 Warning Privilegio non revocato
01007 Warning Privilegio non concesso
01S00 Warning Attributo di stringa di connessione non valido
01S01 Warning Errore in riga
01S02 Warning Valore dell'opzione modificato

Classe 07 - Errore SQL dinamico

SQLSTATE Eccezione Descrizione
07001 ProgrammingError Numero sbagliato di parametri
07002 ProgrammingError Campo COUNT errato
07005 ProgrammingError Istruzione preparata, non specifica del cursore
07006 ProgrammingError Violazione dell'attributo del tipo di dati con restrizioni
07009 ProgrammingError Indice descrittore non valido
07S01 ProgrammingError Uso non valido del parametro predefinito

Classe 08 - Eccezione per connessione

SQLSTATE Eccezione Descrizione
08001 ErroreOperativo Il client non è in grado di stabilire la connessione
08002 ErroreOperativo Nome connessione in uso
08003 ErroreOperativo La connessione non esiste
08004 ErroreOperativo Il server ha rifiutato la connessione
08007 ErroreOperativo Guasto della connessione durante la transazione
08S01 ErroreOperativo Errore del collegamento di comunicazione

Classe 21 - Violazione della cardinalità

SQLSTATE Eccezione Descrizione
21S01 ProgrammingError L'elenco di valori di inserimento non corrisponde all'elenco di colonne
21S02 ProgrammingError Il grado di tabella derivata non corrisponde all'elenco di colonne

Classe 22 - Eccezione dati

SQLSTATE Eccezione Descrizione
22001 DataError Dati stringa, troncamento destro
22002 DataError Variabile indicatore obbligatoria ma non fornita
22003 DataError Valore numerico non compreso nell'intervallo
22007 DataError Formato datetime non valido
22008 DataError Overflow del campo Datetime
22012 DataError Divisione per zero
22015 DataError Overflow del campo intervallo
22018 DataError Valore carattere non valido per la specifica del cast
22019 DataError Carattere di escape non valido
22025 DataError Sequenza di escape non valida
22026 DataError Lunghezza dei dati non corrispondente.

Classe 23 - Violazione dei vincoli di integrità

SQLSTATE Eccezione Descrizione
23000 Errore di integrità Violazione dei vincoli di integrità (generale)

Classe 24 - Stato del cursore invalido

SQLSTATE Eccezione Descrizione
24000 Errore Interno Stato del cursore non valido

Classe 25 - Stato della transazione invalido

SQLSTATE Eccezione Descrizione
25000 ErroreOperativo Stato della transazione invalido
25S01 ErroreOperativo Stato della transazione sconosciuto
25S02 ErroreOperativo La transazione è ancora attiva
25S03 ErroreOperativo La transazione viene annullata

Classe 28 - Specifica di autorizzazione invalida

SQLSTATE Eccezione Descrizione
28000 ErroreOperativo Specifica di autorizzazione non valida (accesso fallito)

Classe 34 - Nome cursore invalido

SQLSTATE Eccezione Descrizione
34000 ProgrammingError Nome di cursore non valido

Classe 3C - Nome duplicato del cursore

SQLSTATE Eccezione Descrizione
3C000 ProgrammingError Nome cursore duplicato

Classe 3D - Nome del catalogo non valido

SQLSTATE Eccezione Descrizione
3D000 ProgrammingError Nome catalogo non valido

Classe 3F - Nome dello schema non valido

SQLSTATE Eccezione Descrizione
3F000 ProgrammingError Nome dello schema non valido

Classe 40 - Rollback delle transazioni

SQLSTATE Eccezione Descrizione
40001 ErroreOperativo Guasto della serializzazione (deadlock)
40002 ErroreOperativo La violazione dei vincoli di integrità ha causato un rollback
40003 ErroreOperativo Completamento istruzione sconosciuto

Classe 42 - Errore di sintassi o violazione della regola di accesso

SQLSTATE Eccezione Descrizione
42000 ProgrammingError Errore di sintassi o violazione di accesso
42S01 ProgrammingError Tabella o vista di base già esistente
42S02 ProgrammingError Tabella o vista di base non trovata
42S11 ProgrammingError Indice già esistente
42S12 ProgrammingError Indice non trovato
42S21 ProgrammingError Colonna già esistente
42S22 ProgrammingError Colonna non trovata

Classe 44 - VIOLAZIONE DELL'OPZIONE CHECK

SQLSTATE Eccezione Descrizione
44000 Errore di integrità Violazione della clausola WITH CHECK OPTION

Classe HY - condizione specifica CLI

SQLSTATE Eccezione Descrizione
HY000 DatabaseError Errore generale
HY001 ErroreOperativo Errore di allocazione della memoria
HY003 ProgrammingError Tipo di buffer dell'applicazione non valido
HY004 ProgrammingError Tipo di dati SQL non valido
HY007 ProgrammingError Istruzione associata non preparata
HY008 ErroreOperativo Operazione annullata
HY009 ProgrammingError Uso non valido del puntatore Null
HY010 ProgrammingError Errore della sequenza di funzioni
HY011 ProgrammingError Impossibile impostare l'attributo ora
HY012 ProgrammingError Codice operativo della transazione non valido
HY013 ErroreOperativo Errore di gestione della memoria
HY014 ErroreOperativo Limite di numero di maniglie superato
HY015 ProgrammingError Nessun nome di cursore disponibile
HY016 ProgrammingError Non può modificare un descrittore di riga di implementazione
HY017 ProgrammingError Uso non valido dell'handle descrittore assegnato automaticamente
HY018 ErroreOperativo Server rifiutato richiesta di cancellazione
HY019 ProgrammingError Dati non caratteri e non binari inviati in pezzi
HY020 DataError Tentare di concatenare un valore nullo
HY021 ProgrammingError Informazioni incoerenti sui descrittori
HY024 ProgrammingError Valore dell'attributo non valido
HY090 ProgrammingError Lunghezza della stringa o del buffer non valida
HY091 ProgrammingError Identificatore del campo descrittore non valido
HY092 ProgrammingError Identificatore di attributo/opzione invalido
HY095 ProgrammingError Tipo di funzione fuori dalla portata
HY096 ProgrammingError Tipo di informazione non valido
HY097 ProgrammingError Tipo di colonna fuori dalla portata
HY098 ProgrammingError Tipo di mirino fuori portata
HY099 ProgrammingError Tipo nullabile fuori dal raggio
HY100 ProgrammingError Tipo di opzione di univocità non compreso nell'intervallo
HY101 ProgrammingError Tipo di opzione accuratezza non compreso nell'intervallo
HY103 ProgrammingError Codice di recupero non valido
HY104 ProgrammingError Precisione o valore di scala non valido
HY105 ProgrammingError Tipo di parametro non valido
HY106 ProgrammingError Tipo di ritiro fuori dal raggio
HY107 ProgrammingError Valore della riga fuori dal range
HY109 ProgrammingError Posizione del cursore non valida
HY110 ProgrammingError Completamento del driver non valido
HY111 ProgrammingError Valore del segnalibro non valido
HYC00 NotSupportedError Funzionalità facoltativa non implementata
HYT00 ErroreOperativo Timeout scaduto
HYT01 ErroreOperativo Il timeout della connessione è scaduto

Classe MI - Errore del driver manager

SQLSTATE Eccezione Descrizione
IM001 InterfaceError Il driver non supporta questa funzione
IM002 InterfaceError Nome della fonte dati non trovato
IM003 InterfaceError Impossibile caricare il driver specificato
IM004 InterfaceError SQLAllocHandle del driver su SQL_HANDLE_ENV guasto
IM005 InterfaceError SQLAllocHandle del driver su SQL_HANDLE_DBC fallito
IM006 InterfaceError Il SQLSetConnectAttr del driver è fallito
IM007 InterfaceError Nessuna fonte di dati o driver specificati
IM008 InterfaceError Dialogo fallito
IM009 InterfaceError Impossibile caricare la DLL di traduzione
IM010 InterfaceError Nome origine dati troppo lungo
IM011 InterfaceError Nome driver troppo lungo
IM012 InterfaceError Errore di sintassi delle parole chiave DRIVER
IM014 InterfaceError DSN non valido
IM015 InterfaceError Fonte di dati file corrotti

Numeri di errore comuni di SQL Server

Oltre a SQLSTATE, SQL Server fornisce numeri di errore nativi tra parentesi. Questi sono gli errori che è più probabile che incontri nel codice applicativo. Costruire la logica di ritentazione attorno all'errore 1205 (bloccaggio) e agli errori di connessione transitoria (vedi logica di ritento).

Error Modello di messaggio Resolution
208 Nome di oggetto non valido Verifica che la tabella o la vista esistano e verifica la qualificazione dello schema.
547 Violazione del vincolo Un vincolo di chiave esterna o di controllo è fallito.
2627 Violazione unica dei vincoli Veniva inserito un valore chiave duplicato.
2601 Violazione dell'indice unico Una chiave duplicata esiste nell'indice.
4060 Impossibile aprire il database Il database non esiste o l'accesso viene negato.
18456 Accesso non riuscito Errore di autenticazione. Controlla le credenziali.
1205 Vittima di deadlock Verrà eseguito il rollback della transazione. Ripetere l'operazione.

Riferimento rapido da sintomo a eccezione

Usa questa tabella per mappare i sintomi comuni al tipo di eccezione che dovresti rilevare:

Sintomo Eccezione Causa possibile
"Accesso fallito per l'utente" OperationalError Credenziali sbagliate o utente non mappato al database.
"Cliente impossibile di stabilire un connessione" OperationalError Server non raggiungibile, firewall o problema DNS.
"Time out scaduto" OperationalError Time out per query o connessione. Aumenta il timeout o ottimizza la query (query off).
"Nome oggetto non valido" ProgrammingError La tabella non esiste o lo schema non è specificato.
"Sintassi errata" ProgrammingError Errore di sintassi SQL. Test query in SSMS.
"Numero sbagliato di parametri" ProgrammingError Il conteggio dei parametri non corrisponde ai segnaposto.
"Violazione della CHIAVE PRIMARIA" IntegrityError Chiave duplicata. Usa MERGE o controlla prima di inserire.
"Violazione della CHIAVE STRANIERA" IntegrityError La riga citata non esiste. Inserisci prima il genitore.
"Transazione bloccata" OperationalError (errore 1205) Contenzione per la serratura. Implementare la logica di ripetizione dei tentativi.
"I dati della stringa o binari verrebbero troncati" DataError Il valore supera la lunghezza della colonna. Controlla i dati o aumenta la dimensione della colonna.
"Conversione fallita" DataError Tipo non corrispondente. Usa il tipo corretto di Python per la colonna.
"Parola chiave sconosciuta" ConnectionStringParseError Errore di battitura nella parola chiave della stringa di connessione.
"Callproc non è supportato" NotSupportedError Utilizzare invece cursor.execute("EXECUTE ...").

Procedure consigliate

  • Individua eccezioni specifiche prima di quelle generiche. Ordina dal più specifico (IntegrityError) al meno specifico (Error).
  • Gestisci sempre IntegrityError per le operazioni di modifica dei dati. Le violazioni dei vincoli sono attese nel funzionamento normale (ad esempio, un utente che cerca di creare un nome utente duplicato).
  • Registra il contesto completo dell'errore per la risoluzione dei problemi. L'eccezione espone driver_error (testo stabile derivato da SQLSTATE) e ddbc_error (messaggio lato server). Registra entrambi; classificare su driver_error.
  • Implementa la logica di ritentativi per errori transitori (guasti di connessione, bloccamenti). Vedi Logica di ritento.
  • Usa rollback() nei gestori di eccezioni per pulire le transazioni fallite. Senza un rollback esplicito, la connessione rimane in uno stato di transazione fallita.