Gestión de errores y códigos SQLSTATE para mssql-python

El controlador mssql-python define una jerarquía estándar de excepciones, patrones comunes de gestión de errores y mapeos de código SQLSTATE para SQL Server y Azure SQL.

Jerarquía de excepciones

El controlador mssql-python sigue la jerarquía de excepciones DB-API 2.0 (PEP 249):

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

ConnectionStringParseError (standalone, not part of hierarchy)

Descripciones de excepciones

Detecta la excepción más específica que se adapte a tu situación. Por ejemplo, detectar IntegrityError violaciones de restricciones en INSERT/UPDATE operaciones y ProgrammingError problemas de sintaxis SQL durante el desarrollo. Captura la clase base Error solo como plan B.

Exception Cuando se levanta
Warning Advertencias no fatales de la base de datos.
Error Clase base para todos los errores de la base de datos.
InterfaceError Errores relacionados con la interfaz de la base de datos (controlador), no con la base de datos en sí.
DatabaseError Errores relacionados con la base de datos.
DataError Errores debidos a problemas con los datos procesados (división por cero, valor fuera de rango).
OperationalError Errores relacionados con la operación de la base de datos (pérdida de conexión, asignación de memoria, errores de transacción).
IntegrityError Errores cuando se ve afectada la integridad de la base de datos (violación de clave extranjera, restricción única).
InternalError Errores internos de la base de datos (cursor no válido, transacción desincronizada).
ProgrammingError Errores de programación (errores de sintaxis, tabla no encontrada, número incorrecto de parámetros).
NotSupportedError Función no soportada por la base de datos ni por el controlador.
ConnectionStringParseError Sintaxis de cadena de conexión inválida o palabras clave desconocidas.

Gestión básica de errores

Utiliza bloques try-except para gestionar errores de base de datos:

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

Excepciones de acceso a través de la conexión

Puedes detectar excepciones a través de la instancia de conexión:

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

Estructura de mensajes de error

Los objetos de excepción mssql-python exponen tres atributos que provienen de la clase base delException controlador:

Attribute Source Descripción
driver_error Controlador de Python El texto estandarizado en inglés elegido por el estado SQLS devolvía de ODBC (por ejemplo, "Communication link failure", "Invalid authorization specification", "Syntax error or access violation"). Estable entre lanzamientos; Seguro para hacer substring match.
ddbc_error Conectividad Directa con la Base de Datos (DDBC) El mensaje del lado del servidor, típicamente precedido por [Microsoft][SQL Server]. El formato no es un contrato estable.
message Compuesto f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". Esto es lo que str(exc) devuelve.
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: ...

El número de error del motor de SQL Server (como 208 o 40501) no está expuesto como atributo y no está incrustado de forma fiable en ninguna de las cadenas. Clasificar errores por subclase de excepción más driver_error texto. Para la limitación de Azure SQL, véase lógica de intento.

Clasificación SQLSTATE

mssql-python utiliza el estado SQLSTATE devuelto por ODBC para elegir tanto la subclase de excepción de Python como el driver_error texto. El mapeo completo de SQLSTATE → excepciones está en exceptions.py el código fuente del driver. La siguiente sección enumera los SQLSTATEs que aparecen con mayor frecuencia con SQL Server y Azure SQL.

Errores de conexión

Fallos de conexión por mssql_python.connect() elevación mssql_python.OperationalError, igual que otros fallos de conectividad:

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"

Errores de cadena de conexión

Los errores de análisis de cadenas de conexión aumentan 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'

Referencia del código SQLSTATE

Los códigos SQLSTATE son códigos de cinco caracteres que identifican condiciones de error. Los dos primeros caracteres indican la clase, y los tres últimos indican la subclase. Rara vez necesitas inspeccionar estos códigos directamente. En su lugar, selecciona el tipo de excepción de Python apropiado (listado en la columna "Excepción"). Utiliza códigos SQLSTATE cuando necesites distinguir entre condiciones de error específicas dentro del mismo tipo de excepción, por ejemplo para diferenciar un bloqueo (40001) de un fallo general de conexión (08S01).

Clase 00 - Finalización exitosa

SQLSTATE Exception Descripción
00000 None Success

Clase 01 - Advertencia

SQLSTATE Exception Descripción
01000 Advertencia Advertencia general
01001 Advertencia Conflicto de la operación del cursor
01002 Advertencia Error de desconexión
01003 DataError Valor NULL eliminado en la función set
01004 DataError Datos de cadena, truncamiento derecho
01006 Advertencia Privilegio no revocado
01007 Advertencia Privilegio no concedido
01S00 Advertencia Atributo cadena de conexión no válido
01S01 Advertencia Error en la fila
01S02 Advertencia Valor de opción cambiado

Clase 07 - Error SQL dinámico

SQLSTATE Exception Descripción
07001 ErrorProgramación Número incorrecto de parámetros
07002 ErrorProgramación Campo COUNT incorrecto
07005 ErrorProgramación Instrucción preparada, no una especificación de cursor
07006 ErrorProgramación Infracción de atributo de tipo de datos restringido
07009 ErrorProgramación Índice de descriptores inválidos
07S01 ErrorProgramación Uso no válido del parámetro predeterminado

Clase 08 - Excepción de conexión

SQLSTATE Exception Descripción
08001 ErrorOperacional El cliente no puede establecer la conexión
08002 ErrorOperacional Nombre de conexión en uso
08003 ErrorOperacional La conexión no existe
08004 ErrorOperacional El servidor rechazó la conexión
08007 ErrorOperacional Fallo de conexión durante la transacción
08S01 ErrorOperacional Error de vínculo de comunicación

Clase 21 - Violación de cardinalidad

SQLSTATE Exception Descripción
21S01 ErrorProgramación La lista de valores de inserción no coincide con la lista de columnas
21S02 ErrorProgramación El grado de la tabla derivada no coincide con la lista de columnas

Clase 22 - Excepción de datos

SQLSTATE Exception Descripción
22001 DataError Datos de cadena, truncamiento derecho
22002 DataError Variable de indicador necesaria pero no proporcionada
22003 DataError Valor numérico fuera del intervalo
22007 DataError Formato datetime no válido
22008 DataError Desbordamiento de campo datetime
22012 DataError División por cero
22015 DataError Desbordamiento de campo de intervalo
22018 DataError Valor de carácter no válido para la especificación de conversión
22019 DataError Carácter de escape no válido
22025 DataError Secuencia de escape no válida
22026 DataError Datos de cadena, desigualdad de longitud

Clase 23 - Violación de restricciones de integridad

SQLSTATE Exception Descripción
23000 IntegrityError Violación de restricciones de integridad (general)

Clase 24 - Estado del cursor inválido

SQLSTATE Exception Descripción
24000 Error interno Estado de cursor no válido

Clase 25 - Estado de transacción inválido

SQLSTATE Exception Descripción
25000 ErrorOperacional Estado de la transacción inválido
25S01 ErrorOperacional Estado de la transacción desconocido
25S02 ErrorOperacional La transacción sigue activa
25S03 ErrorOperacional La transacción se revierte

Clase 28 - Especificación de autorización inválida

SQLSTATE Exception Descripción
28000 ErrorOperacional Especificación de autorización inválida (inicio de sesión fallido)

Clase 34 - Nombre de cursor inválido

SQLSTATE Exception Descripción
34000 ErrorProgramación Nombre de cursor no válido

Clase 3C - Nombre duplicado del cursor

SQLSTATE Exception Descripción
3C000 ErrorProgramación Nombre de cursor duplicado

Clase 3D - Nombre de catálogo inválido

SQLSTATE Exception Descripción
3D000 ErrorProgramación Nombre de catálogo no válido

Clase 3F - Nombre de esquema inválido

SQLSTATE Exception Descripción
3F000 ErrorProgramación Nombre de esquema no válido

Clase 40 - Revertir transacciones

SQLSTATE Exception Descripción
40001 ErrorOperacional Fallo de serialización (bloqueo)
40002 ErrorOperacional La violación de restricciones de integridad provocó retroceso
40003 ErrorOperacional Finalización de instrucciones desconocida

Clase 42 - Error de sintaxis o violación de la regla de acceso

SQLSTATE Exception Descripción
42000 ErrorProgramación Error de sintaxis o infracción de acceso
42S01 ErrorProgramación Ya existe una tabla base o vista
42S02 ErrorProgramación Tabla base o vista no encontrada
42S11 ErrorProgramación El índice ya existe
42S12 ErrorProgramación No se encontró el índice
42S21 ErrorProgramación La columna ya existe
42S22 ErrorProgramación No se encontró la columna.

Clase 44 - VIOLACIÓN DE LA OPCIÓN DE VERIFICACIÓN

SQLSTATE Exception Descripción
44 000 IntegrityError Infracción de WITH CHECK OPTION

Clase HY - Condición específica de CLI

SQLSTATE Exception Descripción
HY000 DatabaseError Error genérico
HY001 ErrorOperacional Error de asignación de memoria
HY003 ErrorProgramación Tipo de búfer de aplicación no válido
HY004 ErrorProgramación Tipo de datos SQL no válido
HY007 ErrorProgramación La instrucción asociada no está preparada
HY008 ErrorOperacional Operación cancelada
HY009 ErrorProgramación Uso no válido del puntero nulo
HY010 ErrorProgramación Error de secuencia de funciones
HY011 ErrorProgramación El atributo no se puede establecer ahora
HY012 ErrorProgramación Código de operación de transacción inválido
HY013 ErrorOperacional Error de administración de memoria
HY014 ErrorOperacional Límite de número de asas superadas
HY015 ErrorProgramación No hay ningún nombre de cursor disponible
HY016 ErrorProgramación No se puede modificar un descriptor de fila de implementación
HY017 ErrorProgramación Uso inválido del handle descriptor asignado automáticamente
HY018 ErrorOperacional Servidor rechazó la solicitud de cancelación
HY019 ErrorProgramación Datos no caracteres y no binarios enviados en fragmentos
HY020 DataError Intento de concatenar un valor nulo
HY021 ErrorProgramación Información de descriptores inconsistente
HY024 ErrorProgramación Valor de atributo no válido
HY090 ErrorProgramación Longitud de búfer o cadena no válida
HY091 ErrorProgramación Identificador de campo descriptor inválido
HY092 ErrorProgramación Identificador de atributo/opción inválido
HY095 ErrorProgramación Tipo de función fuera de rango
HY096 ErrorProgramación Tipo de información inválido
HY097 ErrorProgramación Tipo de columna fuera de rango
HY098 ErrorProgramación Tipo de mira fuera de alcance
HY099 ErrorProgramación Tipo nulo fuera de rango
HY100 ErrorProgramación Tipo de opción de unicidad fuera del intervalo
HY101 ErrorProgramación Tipo de opción de precisión fuera del intervalo
HY103 ErrorProgramación Código de recuperación inválido
HY104 ErrorProgramación Precisión o valor de escala no válidos
HY105 ErrorProgramación Tipo de parámetro no válido
HY106 ErrorProgramación Tipo de recolección fuera de alcance
HY107 ErrorProgramación Valor de la fila fuera de rango
HY109 ErrorProgramación Posición del cursor no válida
HY110 ErrorProgramación Completación del controlador inválido
HY111 ErrorProgramación Valor de marcador inválido
HYC00 NotSupportedError Característica opcional no implementada
HYT00 ErrorOperacional Se ha agotado el tiempo de espera
HYT01 ErrorOperacional Se ha agotado el tiempo de espera de la conexión.

Clase IM - Error del entrenador del piloto

SQLSTATE Exception Descripción
IM001 InterfaceError El controlador no admite esta función
IM002 InterfaceError Nombre de la fuente de datos no encontrado
IM003 InterfaceError No se pudo cargar el controlador especificado
IM004 InterfaceError El SQLAllocHandle del controlador en SQL_HANDLE_ENV falló
IM005 InterfaceError El SQLAllocHandle del controlador en SQL_HANDLE_DBC falló
IM006 InterfaceError El SQLSetConnectAttr del controlador falló
IM007 InterfaceError No se especifica ninguna fuente de datos ni controlador
IM008 InterfaceError Diálogo fallido
IM009 InterfaceError No se puede cargar el archivo DLL de traducción
IM010 InterfaceError Nombre del origen de datos demasiado largo
IM011 InterfaceError Nombre del controlador demasiado largo
IM012 InterfaceError Error de sintaxis de palabra clave DRIVER
IM014 InterfaceError DSN inválido
IM015 InterfaceError Fuente de datos de archivo corrupta

Números de error comunes en SQL Server

Más allá de SQLSTATE, SQL Server proporciona números de error nativos entre paréntesis. Estos son los errores que es más probable que encuentres en el código de la aplicación. Construye la lógica de reintento alrededor del error 1205 (bloqueo) y errores de conexión transitoria (véase lógica de reintento).

Error Patrón de mensaje Resolución
208 Nombre de objeto no válido. Verifica que la tabla o vista exista y comprueba la calificación del esquema.
547 Infracción de restricción Falló una restricción de clave extranjera o comprobación.
2627 Violación única de restricciones Se insertó un valor clave duplicado.
2601 Violación única del índice Existe una clave duplicada en el índice.
4060 No se puede abrir la base de datos La base de datos no existe o se niega el acceso.
18456 Error de inicio de sesión Fallo de autenticación. Consulta las credenciales.
1205 Víctima de interbloqueo La transacción se revirtió. Vuelva a intentar la operación.

Referencia rápida de síntoma a excepción

Utiliza esta tabla para mapear los síntomas comunes al tipo de excepción que deberías detectar:

Síntoma Exception Causa probable
"Inicio de sesión fallido para el usuario" OperationalError Credenciales incorrectas o usuario no asignado a la base de datos.
"Cliente incapaz de establecer conexión" OperationalError Servidor inalcanzable, problema con firewall o DNS.
"Tiempo muerto expirado" OperationalError Tiempo de espera de consulta o conexión. Aumenta el tiempo de espera o optimiza la consulta.
"Nombre de objeto inválido" ProgrammingError No existe la tabla ni el esquema no está especificado.
"Sintaxis incorrecta" ProgrammingError Error de sintaxis SQL. Consulta de prueba en SSMS.
"Número incorrecto de parámetros" ProgrammingError El recuento de parámetros no coincide con los marcadores de posición.
"Violación de la CLAVE PRIMARIA" IntegrityError Duplicar la llave. Úsalo MERGE o comprueba antes de insertarlo.
"Violación de CLAVE EXTRANJERA" IntegrityError La fila referenciada no existe. Inserta primero a los padres.
"La transacción quedó bloqueada" OperationalError (error 1205) Contención de bloqueo. Implemente la lógica de reintento.
"Los datos de cadena o binarios se truncarían" DataError El valor supera la longitud de la columna. Revisa los datos o aumenta el tamaño de la columna.
"Conversión fallida" DataError Error de coincidencia de tipos. Usa el tipo correcto de Python para la columna.
"Palabra clave desconocida" ConnectionStringParseError Error tipográfico en la palabra clave de cadena de conexión.
"callproc no es compatible" NotSupportedError Utilice cursor.execute("EXECUTE ...") en su lugar.

procedimientos recomendados

  • Detecta excepciones específicas antes que genéricas. Ordena de más específico (IntegrityError) a menos específico (Error).
  • Siempre maneja IntegrityError para las operaciones de modificación de datos. Se esperan violaciones de restricciones en el funcionamiento normal (por ejemplo, un usuario que intenta crear un nombre de usuario duplicado).
  • Registra el contexto completo del error para la resolución de problemas. La excepción expone driver_error (texto estable derivado de SQLSTATE) y ddbc_error (mensaje del lado del servidor). Registrar ambos; clasificar en driver_error.
  • Implementa lógica de reintento para errores transitorios (fallos de conexión, bloqueos). Consulta lógica de reintento.
  • Utiliza rollback() en los gestores de excepciones para limpiar transacciones fallidas. Sin una reversión explícita, la conexión permanece en estado de transacción fallida.