Gestion des erreurs et codes SQLSTATE pour mssql-python

Le pilote mssql-python définit une hiérarchie d’exception standard, des schémas courants de gestion des erreurs et des correspondances de code SQLSTATE pour SQL Server et Azure SQL.

Hiérarchie d’exceptions

Le pilote mssql-python suit la hiérarchie des exceptions DB-API 2.0 (PEP 249) :

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

ConnectionStringParseError (standalone, not part of hierarchy)

Descriptions des exceptions

Identifiez l’exception la plus spécifique qui correspond à votre situation. Par exemple, détecter IntegrityError les violations de contraintes sur INSERT/UPDATE operations, et ProgrammingError les problèmes de syntaxe SQL pendant le développement. Ne prends la classe de Error base qu’en plan B.

Exception Lorsqu'il est soulevé
Warning Avertissements non mortels provenant de la base de données.
Error Classe de base pour toutes les erreurs de base de données.
InterfaceError Des erreurs liées à l’interface de la base de données (pilote), pas à la base de données elle-même.
DatabaseError Erreurs liées à la base de données.
DataError Erreurs dues à des problèmes avec les données traitées (division par zéro, valeur hors plage).
OperationalError Erreurs liées au fonctionnement de la base de données (perte de connexion, allocation mémoire, erreurs de transaction).
IntegrityError Erreurs lorsque l’intégrité de la base de données est affectée (violation de clé étrangère, contrainte unique).
InternalError Erreurs internes de base de données (curseur non valide, transaction désynchronisée).
ProgrammingError Erreurs de programmation (erreurs de syntaxe, table non trouvée, mauvais nombre de paramètres).
NotSupportedError Fonctionnalité non prise en charge par la base de données ou le pilote.
ConnectionStringParseError Syntaxe de chaîne de connexion invalide ou mots-clés inconnus.

Gestion des erreurs de base

Utilisez des blocs try-except pour gérer les erreurs de base de données :

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()

Accès aux exceptions via la connexion

Vous pouvez détecter des exceptions via l’instance de connexion :

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

Structure des messages d’erreur

Les objets d’exception MSSQL-Python exposent trois attributs provenant de la classe de base duException pilote :

Caractéristique Source Description
driver_error Pilote Python Texte anglais standardisé choisi par l’état SQLSTATE revenu d’ODBC (par exemple, "Communication link failure", "Invalid authorization specification", "Syntax error or access violation"). Stable entre les versions ; Sûr pour le substring match.
ddbc_error Connectivité directe à la base de données (DDBC) Le message côté serveur, généralement précédé de [Microsoft][SQL Server]. Le format n’est pas un contrat stable.
message Composé f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". C’est ce qui str(exc) revient.
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: ...

Le numéro d'erreur du moteur SQL Server (comme 208 ou 40501) n'est pas exposé comme attribut et n'est pas intégré de manière fiable dans aucune des chaînes. Classez les erreurs par sous-classe d’exception plus driver_error le texte. Pour le throttling Azure SQL, voir Logique de réessayage.

Classification SQLSTATE

mssql-python utilise l’état SQLSTATE retourné par ODBC pour choisir à la fois la sous-classe d’exception Python et le driver_error texte. Le SQLSTATE complet → la correspondance des exceptions se trouve exceptions.py dans le code source du pilote. La section suivante énumère les SQLSTATE qui apparaissent le plus souvent avec SQL Server et Azure SQL.

Erreurs de connexion

Les défaillances de connexion dues mssql_python.connect() au relance mssql_python.OperationalError, identiques à celles des autres défaillances de connectivité :

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"

Erreurs de chaîne de connexion

Les erreurs d’analyse syntaxique de chaînes de connexion entraînent 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'

Référence du code SQLSTATE

Les codes SQLSTATE sont des codes de cinq caractères qui identifient les conditions d’erreur. Les deux premiers caractères indiquent la classe, et les trois derniers la sous-classe. Vous avez rarement besoin d’inspecter ces codes directement. À la place, sélectionnez le type d’exception Python approprié (indiqué dans la colonne « Exception »). Utilisez des codes SQLSTATE lorsque vous devez distinguer des conditions d’erreur spécifiques au sein d’un même type d’exception, par exemple pour différencier un deadlock (40001) d’une défaillance générale de connexion (08S01).

Classe 00 - Réussite

SQLSTATE Exception Description
00000 None Success

Classe 01 - Avertissement

SQLSTATE Exception Description
01000 Warning Avertissement général
01001 Warning Conflit d’opérations de curseur
01002 Warning Erreur de déconnexion
01003 DataError Valeur NULL éliminée dans la fonction set
01004 DataError Données de chaîne, troncation droite
01006 Warning Privilège non révoqué
01007 Warning Privilège non accordé
01S00 Warning Attribut chaîne de connexion non valide
01S01 Warning Erreur en ligne
01S02 Warning Valeur d’option modifiée

Classe 07 - Erreur SQL dynamique

SQLSTATE Exception Description
07001 ProgrammingError Mauvais nombre de paramètres
07002 ProgrammingError Champ COUNT incorrect
07005 ProgrammingError Déclaration préparée, pas une spécification de curseur
07006 ProgrammingError Violation d’attribut de type de données restreint
07009 ProgrammingError Index descripteur invalide
07S01 ProgrammingError Utilisation non valide du paramètre par défaut

Classe 08 - Exception de connexion

SQLSTATE Exception Description
08001 ErrorOperationalError Le client ne peut pas établir de connexion
08002 ErrorOperationalError Nom de connexion en cours d’utilisation
08003 ErrorOperationalError La connexion n’existe pas
08004 ErrorOperationalError Le serveur a rejeté la connexion
08007 ErrorOperationalError Défaillance de la connexion pendant la transaction
08S01 ErrorOperationalError Échec de la liaison de communication

Classe 21 - Violation de cardinalité

SQLSTATE Exception Description
21S01 ProgrammingError La liste des valeurs d’insertion ne correspond pas à la liste de colonnes
21S02 ProgrammingError Le degré de table dérivée ne correspond pas à la liste des colonnes

Classe 22 - Exception de données

SQLSTATE Exception Description
22001 DataError Données de chaîne, troncation droite
22002 DataError Variable d’indicateur requise, mais non fournie
22003 DataError Valeur numérique hors plage
22007 DataError Format datetime non valide
22008 DataError Dépassement de champ Datetime
22012 DataError Division par zéro
22015 DataError Dépassement de champ d’intervalle
22018 DataError Valeur de caractère non valide pour la spécification de cast
22019 DataError Caractère d’échappement non valide
22025 DataError Séquence d’échappement non valide
22026 DataError Chaîne de données ou longueur non correspondante

Classe 23 - Violation des contraintes d’intégrité

SQLSTATE Exception Description
23000 IntégrityError Violation des contraintes d’intégrité (générale)

Classe 24 - État du curseur invalide

SQLSTATE Exception Description
24000 Erreur Interne État de curseur non valide

Classe 25 - État de transaction invalide

SQLSTATE Exception Description
25000 ErrorOperationalError État de transaction invalide
25S01 ErrorOperationalError État de la transaction inconnu
25S02 ErrorOperationalError La transaction est toujours active
25S03 ErrorOperationalError La transaction est annulée

Classe 28 - Spécification d’autorisation invalide

SQLSTATE Exception Description
28000 ErrorOperationalError Spécification d’autorisation invalide (connexion échouée)

Classe 34 - Nom de curseur invalide

SQLSTATE Exception Description
34000 ProgrammingError Nom de curseur non valide

Classe 3C - Nom de curseur dupliqué

SQLSTATE Exception Description
3C000 ProgrammingError Nom du curseur dupliqué

Classe 3D - Nom de catalogue invalide

SQLSTATE Exception Description
3D000 ProgrammingError Nom du catalogue non valide

Classe 3F - Nom de schéma invalide

SQLSTATE Exception Description
3F000 ProgrammingError Nom de schéma non valide

Classe 40 - Annulation de transaction

SQLSTATE Exception Description
40001 ErrorOperationalError Défaillance de la sérialisation (blocage)
40002 ErrorOperationalError La violation de contrainte d’intégrité a causé un retour en arrière
40003 ErrorOperationalError Saisie semi-automatique de l’instruction inconnue

Classe 42 - Erreur de syntaxe ou violation de la règle d’accès

SQLSTATE Exception Description
42000 ProgrammingError Erreur de syntaxe ou violation d’accès
42S01 ProgrammingError La table ou la vue de base existe déjà
42S02 ProgrammingError Table de base ou vue introuvable
42S11 ProgrammingError L’index existe déjà
42S12 ProgrammingError Index introuvable
42S21 ProgrammingError La colonne existe déjà
42S22 ProgrammingError Colonne introuvable

Classe 44 - VIOLATION DE L’OPTION DE VÉRIFICATION

SQLSTATE Exception Description
44000 IntégrityError Violation de WITH CHECK OPTION

Classe HY - Condition spécifique à CLI

SQLSTATE Exception Description
HY000 DatabaseError Erreur générale
HY001 ErrorOperationalError Erreur d’allocation de mémoire
HY003 ProgrammingError Type de mémoire tampon d’application non valide
HY004 ProgrammingError Type de données SQL non valide
HY007 ProgrammingError L’instruction associée n’est pas préparée
HY008 ErrorOperationalError Opération annulée
HY009 ProgrammingError Utilisation non valide du pointeur Null
HY010 ProgrammingError Erreur de séquence de fonction
HY011 ProgrammingError Impossible de définir l’attribut maintenant
HY012 ProgrammingError Code d’opération de transaction invalide
HY013 ErrorOperationalError Erreur de gestion de la mémoire
HY014 ErrorOperationalError Limite de nombre de poignées dépassées
HY015 ProgrammingError Aucun nom de curseur disponible
HY016 ProgrammingError Impossible de modifier un descripteur de ligne d’implémentation
HY017 ProgrammingError Utilisation invalide du descriptor automatiquement alloué
HY018 ErrorOperationalError Demande d’annulation du serveur refusée
HY019 ProgrammingError Données non caractères et non binaires envoyées en morceaux
HY020 DataError Tentative de concaténation d’une valeur nulle
HY021 ProgrammingError Informations descriptives incohérentes
HY024 ProgrammingError Valeur d’attribut non valide
HY090 ProgrammingError Longueur de la chaîne ou de la mémoire tampon non valide
HY091 ProgrammingError Identifiant de champ descripteur invalide
HY092 ProgrammingError Identifiant d’attribut/option invalide
HY095 ProgrammingError Type de fonction hors de portée
HY096 ProgrammingError Type d’information invalide
HY097 ProgrammingError Type de colonne hors de portée
HY098 ProgrammingError Type de lunette hors de portée
HY0999 ProgrammingError Type nullable hors de portée
HY100 ProgrammingError Type d’option d’unicité hors plage
HY101 ProgrammingError Type d’option d’exactitude hors plage
HY103 ProgrammingError Code de récupération invalide
HY104 ProgrammingError Valeur de précision ou d’échelle non valide
HY105 ProgrammingError Type de paramètre non valide
HY106 ProgrammingError Type de récupération hors de portée
HY107 ProgrammingError Valeur de la ligne hors de la plage
HY109 ProgrammingError Position du curseur non valide
HY110 ProgrammingError Complétion invalide du pilote
HY111 ProgrammingError Valeur de marque-page invalide
HYC00 NotSupportedError Fonctionnalité facultative non implémentée
HYT00 ErrorOperationalError Délai expiré
HYT01 ErrorOperationalError Délai d’attente de la connexion expiré

Classe IM - Erreur du manager du pilote

SQLSTATE Exception Description
IM001 InterfaceError Le pilote ne prend pas en charge cette fonction
IM002 InterfaceError Nom de la source de données non trouvé
IM003 InterfaceError Impossible de charger le pilote spécifié
IM004 InterfaceError SQLAllocHandle du pilote sur SQL_HANDLE_ENV a échoué
IM005 InterfaceError SQLAllocHandle du pilote sur SQL_HANDLE_DBC a échoué
IM006 InterfaceError Le SQLSetConnectAttr du pilote a échoué
IM007 InterfaceError Aucune source de données ni pilote spécifié
IM008 InterfaceError Dialogue échoué
IM009 InterfaceError Impossible de charger la DLL de traduction
IM010 InterfaceError Nom de la source de données trop long
IM011 InterfaceError Nom du pilote trop long
IM012 InterfaceError Erreur de syntaxe de mot clé DRIVER
IM014 InterfaceError DSN invalide
IM015 InterfaceError Source de données de fichier corrompue

Numéros d’erreur courants sur SQL Server

Au-delà de SQLSTATE, SQL Server fournit des numéros d’erreur natifs entre parenthèses. Ce sont les erreurs que vous êtes le plus susceptible de rencontrer dans le code de l’application. Construire la logique de réessai autour de l’erreur 1205 (blocage) et des erreurs de connexion transitoires (voir logique de réessayage).

Error Modèle de message Résolution
208 Nom d’objet non valide Vérifiez que la table ou la vue existe et vérifiez la qualification du schéma.
547 Violation de contrainte Une clé étrangère ou une contrainte de vérification a échoué.
2627 Violation unique de contrainte Une valeur clé en double a été insérée.
2601 Violation d’index unique Une clé en double existe dans l’index.
4060 Impossible d’ouvrir la base de données La base de données n’existe pas ou l’accès est refusé.
18456 Échec de la connexion Échec d’authentification. Vérifiez les diplômes.
1205 Victime d’un interblocage La transaction a été restaurée. Réessayez l’opération.

Référence rapide des symptômes à l’exception

Utilisez ce tableau pour associer les symptômes courants au type d’exception que vous devriez détecter :

Symptôme Exception Cause la plus probable
« Connexion échouée pour l’utilisateur » OperationalError Mauvaises identifiantes ou utilisateur non mappé à la base de données.
« Client incapable d’établir la connexion » OperationalError Serveur injoignable, pare-feu ou problème DNS.
« Temps mort expiré » OperationalError Délai d’attente de requête ou de connexion. Augmenter le temps d’attente ou optimiser la requête.
« Nom de l’objet invalide » ProgrammingError La table n’existe pas et le schéma n’est pas spécifié.
« Syntaxe incorrecte » ProgrammingError Erreur de syntaxe SQL. Requête de test dans SSMS.
« Mauvais nombre de paramètres » ProgrammingError Le nombre de paramètres ne correspond pas aux réserves.
« Violation de la CLÉ PRIMAIRE » IntegrityError Double de la clé. Utilisez MERGE ou vérifiez avant d’insérer.
« Violation de CLÉ ÉTRANGÈRE » IntegrityError La ligne référencée n’existe pas. Insérez d’abord le parent.
« Transaction bloquée » OperationalError (erreur 1205) Contention de serrure. Implémentez la logique de nouvelle tentative.
« Les données de chaîne ou binaires seraient tronquées » DataError La valeur dépasse la longueur de la colonne. Vérifiez les données ou augmentez la taille des colonnes.
« Conversion échouée » DataError Incompatibilité de type. Utilisez le bon type Python pour la colonne.
« Mot-clé inconnu » ConnectionStringParseError Faute de frappe dans le mot-clé de chaîne de connexion.
« Callproc n’est pas pris en charge » NotSupportedError Utilisez cursor.execute("EXECUTE ...") à la place.

Bonnes pratiques

  • Prenez les exceptions spécifiques avant les génériques. Ordre du plus spécifique (IntegrityError) au moins spécifique (Error).
  • Gérez toujours IntegrityError pour les opérations de modification des données. Les violations de contraintes sont attendues en fonctionnement normal (par exemple, un utilisateur essayant de créer un nom d’utilisateur en double).
  • Enregistrez le contexte complet des erreurs pour le dépannage. L’exception expose driver_error (texte stable, dérivé de SQLSTATE) et ddbc_error (message côté serveur). Enregistrez les deux ; classifier sur driver_error.
  • Implémentez une logique de réévaluation pour les erreurs transitoires (pannes de connexion, blocages). Voir logique de réessayage.
  • Utilisez rollback() dans les gestionnaires d’exceptions pour corriger les transactions ratées. Sans retour explicite, la connexion reste dans un état de transaction échouée.