O driver mssql-python define uma hierarquia padrão de exceções, padrões comuns de tratamento de erros e mapeamentos de código SQLSTATE para SQL Server e SQL do Azure.
Hierarquia de exceção
O driver mssql-python segue a hierarquia de exceções DB-API 2.0 (PEP 249):
Exception (builtins)
├── Warning
└── Error
├── InterfaceError
└── DatabaseError
├── DataError
├── OperationalError
├── IntegrityError
├── InternalError
├── ProgrammingError
└── NotSupportedError
ConnectionStringParseError (standalone, not part of hierarchy)
Descrições de exceções
Apanha a exceção mais específica que corresponda à sua situação. Por exemplo, apanhar IntegrityError violações de restrições em INSERToperações/UPDATE , e ProgrammingError para problemas de sintaxe SQL durante o desenvolvimento. Apanhar a classe base Error apenas como plano B.
| Exception |
Quando levantado |
Warning |
Avisos não fatais da base de dados. |
Error |
Classe base para todos os erros da base de dados. |
InterfaceError |
Erros relacionados com a interface da base de dados (driver), não com a base de dados em si. |
DatabaseError |
Erros relacionados com a base de dados. |
DataError |
Erros devido a problemas com dados processados (divisão por zero, valor fora do intervalo). |
OperationalError |
Erros relacionados com a operação da base de dados (perda de ligação, alocação de memória, erros de transação). |
IntegrityError |
Erros quando a integridade da base de dados é afetada (violação de chave estrangeira, restrição única). |
InternalError |
Erros internos da base de dados (cursor não válido, transação fora de sincronização). |
ProgrammingError |
Erros de programação (erros de sintaxe, tabela não encontrada, número errado de parâmetros). |
NotSupportedError |
Funcionalidade não suportada pela base de dados ou pelo driver. |
ConnectionStringParseError |
Sintaxe de cadeia de ligação inválida ou palavras-chave desconhecidas. |
Gestão básica de erros
Use blocos try-except para lidar com erros na base de dados:
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()
Exceções de acesso através da ligação
Pode detetar exceções através da instância de ligação:
try:
cursor.execute("INVALID SQL")
except conn.ProgrammingError as e:
print(f"Caught via connection: {e}")
Estrutura da mensagem de erro
Os objetos de exceção mssql-python expõem três atributos que provêm da classe base doException driver:
| Attribute |
Source |
Descrição |
driver_error |
Driver Python |
O texto inglês padronizado escolhido pelo SQLSTATE devolveu do ODBC (por exemplo, "Communication link failure", "Invalid authorization specification", "Syntax error or access violation"). Estável entre lançamentos; Seguro para fazer substring match. |
ddbc_error |
Conectividade Direta de Bases de Dados (DDBC) |
A mensagem do lado do servidor, normalmente com o prefixo [Microsoft][SQL Server]de . O formato não é um contrato estável. |
message |
Composição |
f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". É isto que str(exc) regressa. |
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: ...
O número de erro do motor do SQL Server (como 208 ou 40501) não é exposto como um atributo e não está embutido de forma fiável em nenhuma das strings. Classificar erros por subclasse de exceção mais driver_error texto. Para o throttling do SQL do Azure, veja Retry logic.
Classificação SQLSTATE
mssql-python usa o SQLSTATE devolvido pelo ODBC para escolher tanto a subclasse de exceção Python como o driver_error texto. O mapeamento completo de SQLSTATE → exceções está no exceptions.py código-fonte do driver. A secção seguinte lista os SQLSTATEs que aparecem com mais frequência no SQL Server e no SQL do Azure.
Erros de ligação
Falhas de ligação do mssql_python.connect() raise mssql_python.OperationalError, iguais a outras falhas de conectividade:
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"
Erros na cadeia de ligação
Erros de análise sintática de stringas de ligação aumentam 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'
Referência de código SQLSTATE
Os códigos SQLSTATE são códigos de cinco caracteres que identificam condições de erro. Os dois primeiros caracteres indicam a classe, e os últimos três indicam a subclasse. Raramente precisa de inspecionar estes códigos diretamente. Em vez disso, escolha o tipo de exceção Python apropriado (listado na coluna "Exceção"). Use códigos SQLSTATE quando precisar de distinguir entre condições de erro específicas dentro do mesmo tipo de exceção, por exemplo, para diferenciar um deadlock (40001) de uma falha geral de ligação (08S01).
Classe 00 - Conclusão bem-sucedida
| SQLSTATE |
Exception |
Descrição |
| 00000 |
None |
Êxito |
Classe 01 - Aviso
| SQLSTATE |
Exception |
Descrição |
| 01000 |
Warning |
Aviso geral |
| 01001 |
Warning |
Conflito de operação de cursor |
| 01002 |
Warning |
Erro de desconexão |
| 01003 |
DataError |
Valor NULL eliminado na função de conjunto |
| 01004 |
DataError |
Dados de cadeia, truncagem à direita |
| 01006 |
Warning |
Privilégio não revogado |
| 01007 |
Warning |
Privilégio não concedido |
| 01S00 |
Warning |
Atributo de cadeia de ligação inválido |
| 01S01 |
Warning |
Erro em linha |
| 01S02 |
Warning |
Valor da opção alterado |
Classe 07 - Erro SQL dinâmico
| SQLSTATE |
Exception |
Descrição |
| 07001 |
ErrorProgrammingError |
Número errado de parâmetros |
| 07002 |
ErrorProgrammingError |
Campo COUNT incorreto |
| 07005 |
ErrorProgrammingError |
Instrução preparada, não uma especificação de cursor |
| 07006 |
ErrorProgrammingError |
Violação de atributo de tipo de dado restrito |
| 07009 |
ErrorProgrammingError |
Índice de descritores inválido |
| 07S01 |
ErrorProgrammingError |
Uso inválido do parâmetro padrão |
Classe 08 - Exceção de ligação
| SQLSTATE |
Exception |
Descrição |
| 08001 |
OperationalError |
Cliente incapaz de estabelecer ligação |
| 08002 |
OperationalError |
Nome da ligação em uso |
| 08003 |
OperationalError |
A ligação não existe |
| 08004 |
OperationalError |
O servidor rejeitou a ligação |
| 08007 |
OperationalError |
Falha de ligação durante a transação |
| 08S01 |
OperationalError |
Falha da ligação de comunicação |
Classe 21 - Violação de cardinalidade
| SQLSTATE |
Exception |
Descrição |
| 21S01 |
ErrorProgrammingError |
Inserir lista de valores não corresponde à lista de colunas |
| 21S02 |
ErrorProgrammingError |
O grau da tabela derivada não corresponde à lista de colunas |
Classe 22 - Exceção de dados
| SQLSTATE |
Exception |
Descrição |
| 22001 |
DataError |
Dados de cadeia, truncagem à direita |
| 22002 |
DataError |
Variável indicadora necessária, mas não fornecida |
| 22003 |
DataError |
Valor numérico fora do intervalo |
| 22007 |
DataError |
Formato de data-hora inválido |
| 22008 |
DataError |
Excesso de campo data-hora |
| 22012 |
DataError |
Divisão por zero |
| 22015 |
DataError |
Excesso de campo de intervalo |
| 22018 |
DataError |
Valor de personagem inválido para especificação de elenco |
| 22019 |
DataError |
Carácter de fuga inválido |
| 22025 |
DataError |
Sequência de fuga inválida |
| 22026 |
DataError |
Dados de cadeia de caracteres, incompatibilidade de comprimento |
Classe 23 - Violação de restrições de integridade
| SQLSTATE |
Exception |
Descrição |
| 23000 |
IntegrityError |
Violação de restrições de integridade (geral) |
Classe 24 - Estado do cursor inválido
| SQLSTATE |
Exception |
Descrição |
| 24000 |
Erro interno |
Estado do cursor inválido |
Classe 25 - Estado de transação inválido
| SQLSTATE |
Exception |
Descrição |
| 25000 |
OperationalError |
Estado inválido da transação |
| 25S01 |
OperationalError |
Estado da transação desconhecido |
| 25S02 |
OperationalError |
A transação continua ativa |
| 25S03 |
OperationalError |
A transação é revertida |
Classe 28 - Especificação de autorização inválida
| SQLSTATE |
Exception |
Descrição |
| 28000 |
OperationalError |
Especificação de autorização inválida (falha no início de sessão) |
Classe 34 - Nome do cursor inválido
| SQLSTATE |
Exception |
Descrição |
| 34000 |
ErrorProgrammingError |
Nome do cursor inválido |
Classe 3C - Nome duplicado do cursor
| SQLSTATE |
Exception |
Descrição |
| 3C000 |
ErrorProgrammingError |
Nome do cursor duplicado |
Classe 3D - Nome inválido do catálogo
| SQLSTATE |
Exception |
Descrição |
| 3D000 |
ErrorProgrammingError |
Nome do catálogo inválido |
Classe 3F - Nome inválido do esquema
| SQLSTATE |
Exception |
Descrição |
| 3F000 |
ErrorProgrammingError |
Nome de esquema inválido |
Classe 40 - Reversão de transações
| SQLSTATE |
Exception |
Descrição |
| 40001 |
OperationalError |
Falha de serialização (deadlock) |
| 40002 |
OperationalError |
A violação de restrições de integridade causou recuo |
| 40003 |
OperationalError |
Conclusão da afirmação desconhecida |
Classe 42 - Erro de sintaxe ou violação da regra de acesso
| SQLSTATE |
Exception |
Descrição |
| 42000 |
ErrorProgrammingError |
Erro de sintaxe ou violação de acesso |
| 42S01 |
ErrorProgrammingError |
A tabela base ou vista já existe |
| 42S02 |
ErrorProgrammingError |
Tabela base ou vista não encontrada |
| 42S11 |
ErrorProgrammingError |
O índice já existe |
| 42S12 |
ErrorProgrammingError |
Índice não encontrado |
| 42S21 |
ErrorProgrammingError |
A coluna já existe |
| 42S22 |
ErrorProgrammingError |
Coluna não encontrada |
Classe 44 - VIOLAÇÃO DA OPÇÃO DE VERIFICAÇÃO
| SQLSTATE |
Exception |
Descrição |
| 44000 |
IntegrityError |
COM VIOLAÇÃO DA OPÇÃO DE VERIFICAÇÃO |
Classe HY - condição específica de CLI
| SQLSTATE |
Exception |
Descrição |
| HY000 |
DatabaseError |
Erro geral |
| HY001 |
OperationalError |
Erro de alocação de memória |
| HY003 |
ErrorProgrammingError |
Tipo de buffer de aplicação inválido |
| HY004 |
ErrorProgrammingError |
Tipo de dado SQL inválido |
| HY007 |
ErrorProgrammingError |
A declaração associada não está preparada |
| HY008 |
OperationalError |
Operação cancelada |
| HY009 |
ErrorProgrammingError |
Uso inválido do ponteiro nulo |
| HY010 |
ErrorProgrammingError |
Erro de sequência de funções |
| HY011 |
ErrorProgrammingError |
O atributo não pode ser definido agora |
| HY012 |
ErrorProgrammingError |
Código de operação de transação inválido |
| HY013 |
OperationalError |
Erro de gestão de memória |
| HY014 |
OperationalError |
Limite para o número de alças ultrapassado |
| HY015 |
ErrorProgrammingError |
Não há nome de cursor disponível |
| HY016 |
ErrorProgrammingError |
Não pode modificar um descritor de linha de implementação |
| HY017 |
ErrorProgrammingError |
Uso inválido do handle de descriptor automaticamente alocado |
| HY018 |
OperationalError |
Pedido de cancelamento do servidor recusado |
| HY019 |
ErrorProgrammingError |
Dados não-caracteres e não-binários enviados em pedaços |
| HY020 |
DataError |
Tentativa de concatenar um valor nulo |
| HY021 |
ErrorProgrammingError |
Informação inconsistente do descritor |
| HY024 |
ErrorProgrammingError |
Valor de atributo inválido |
| HY090 |
ErrorProgrammingError |
Comprimento inválido da corda ou do buffer |
| HY091 |
ErrorProgrammingError |
Identificador de campo descritor inválido |
| HY092 |
ErrorProgrammingError |
Identificador de atributo/opção inválido |
| HY095 |
ErrorProgrammingError |
Tipo de função fora do alcance |
| HY096 |
ErrorProgrammingError |
Tipo de informação inválido |
| HY097 |
ErrorProgrammingError |
Tipo de coluna fora do alcance |
| HY098 |
ErrorProgrammingError |
Tipo de mira fora do alcance |
| HY099 |
ErrorProgrammingError |
Tipo anulável fora do alcance |
| HY100 |
ErrorProgrammingError |
Opção de unicidade fora do intervalo |
| HY101 |
ErrorProgrammingError |
Tipo de opção de precisão fora do alcance |
| HY103 |
ErrorProgrammingError |
Código de recuperação inválido |
| HY104 |
ErrorProgrammingError |
Precisão ou valor de escala inválidos |
| HY105 |
ErrorProgrammingError |
Tipo de parâmetro inválido |
| HY106 |
ErrorProgrammingError |
Tipo de busca fora do alcance |
| HY107 |
ErrorProgrammingError |
Valor da linha fora do intervalo |
| HY109 |
ErrorProgrammingError |
Posição inválida do cursor |
| HY110 |
ErrorProgrammingError |
Completação inválida do driver |
| HY111 |
ErrorProgrammingError |
Valor de marcador inválido |
| HYC00 |
NotSupportedError |
Funcionalidade opcional não implementada |
| HYT00 |
OperationalError |
O tempo expirou |
| HYT01 |
OperationalError |
Expirou o tempo limite de ligação |
Classe IM - Erro do gestor do piloto
| SQLSTATE |
Exception |
Descrição |
| IM001 |
InterfaceError |
O driver não suporta esta função |
| IM002 |
InterfaceError |
Nome da fonte de dados não encontrado |
| IM003 |
InterfaceError |
O driver especificado não podia ser carregado |
| IM004 |
InterfaceError |
O SQLAllocHandle do driver no SQL_HANDLE_ENV falhou |
| IM005 |
InterfaceError |
O SQLAllocHandle do driver no SQL_HANDLE_DBC falhou |
| IM006 |
InterfaceError |
O SQLSetConnectAttr do driver falhou |
| IM007 |
InterfaceError |
Sem fonte de dados ou driver especificado |
| IM008 |
InterfaceError |
Diálogo falhado |
| IM009 |
InterfaceError |
Não é possível carregar DLL de tradução |
| IM010 |
InterfaceError |
Nome da fonte de dados demasiado longo |
| IM011 |
InterfaceError |
Nome do piloto demasiado longo |
| IM012 |
InterfaceError |
Erro de sintaxe da palavra-chave DRIVER |
| IM014 |
InterfaceError |
DSN inválido |
| IM015 |
InterfaceError |
Corromper a fonte de dados do ficheiro |
Números de erro comuns do SQL Server
Para além do SQLSTATE, o SQL Server fornece números de erro nativos entre parênteses. Estes são os erros que é mais provável de encontrar no código da aplicação. Construir a lógica de retentativa em torno do erro 1205 (deadlock) e erros de ligação transitória (ver lógica de retentação).
| Erro |
Padrão de mensagens |
Resolução |
| 208 |
Nome do objeto inválido |
Verifique se a tabela ou vista existe e verifique a qualificação do esquema. |
| 547 |
Violação de restrições |
Uma restrição de chave estrangeira ou de verificação falhou. |
| 2627 |
Violação única de restrição |
Foi inserido um valor duplicado da chave. |
| 2601 |
Violação de índice único |
Existe uma chave duplicada no índice. |
| 4060 |
Não é possível abrir a base de dados |
A base de dados não existe ou o acesso é negado. |
| 18456 |
Início de sessão falhado |
Falha de autenticação. Verifica as credenciais. |
| 1205 |
Vítima do impasse |
A transação foi revertida. Repita a operação. |
Referência rápida de sintomas para exceções
Use esta tabela para mapear os sintomas comuns ao tipo de exceção que deverá detetar:
| Symptom |
Exception |
Causa provável |
| "Login falhado para o utilizador" |
OperationalError |
Credenciais erradas ou utilizador não mapeado para a base de dados. |
| "Cliente incapaz de estabelecer ligação" |
OperationalError |
Servidor inacessível, firewall ou problema de DNS. |
| "Tempo expirado" |
OperationalError |
Tempo limite de consulta ou ligação. Aumenta o timeout ou otimiza a consulta. |
| "Nome do objeto inválido" |
ProgrammingError |
A tabela não existe nem o esquema não está especificado. |
| "Sintaxe incorreta" |
ProgrammingError |
Erro de sintaxe SQL. Consulta de teste no SSMS. |
| "Número errado de parâmetros" |
ProgrammingError |
A contagem de parâmetros não corresponde aos marcadores de posição. |
| "Violação da CHAVE PRIMÁRIA" |
IntegrityError |
Duplicar a chave. Use MERGE ou verifique antes de inserir. |
| "Violação da CHAVE ESTRANGEIRA" |
IntegrityError |
A linha referenciada não existe. Insira primeiro o pai. |
| "Transação bloqueada" |
OperationalError (erro 1205) |
Contenda de fechadura. Implemente lógica de reintento. |
| "Os dados da cadeia ou binários seriam truncados" |
DataError |
O valor excede o comprimento da coluna. Verifique os dados ou aumente o tamanho da coluna. |
| "Conversão falhada" |
DataError |
Incompatibilidade de tipo. Use o tipo correto de Python para a coluna. |
| "Palavra-chave desconhecida" |
ConnectionStringParseError |
Erro tipográfico na palavra-chave da cadeia de ligação. |
| "O CallProc não é suportado" |
NotSupportedError |
Utilize cursor.execute("EXECUTE ...") em substituição. |
Melhores práticas
-
Apanha exceções específicas antes das genéricas. Ordem do mais específico (
IntegrityError) ao menos específico (Error).
-
Manusei sempre o IntegrityError para operações de modificação de dados. Violações de restrições são esperadas em funcionamento normal (por exemplo, um utilizador a tentar criar um nome de utilizador duplicado).
-
Regista o contexto completo do erro para a resolução de problemas. A exceção expõe
driver_error (texto estável, derivado do SQLSTATE) e ddbc_error (mensagem do lado do servidor). Regista ambos; classificar em driver_error.
-
Implementar lógica de retentativa para erros transitórios (falhas de ligação, bloqueios). Veja Lógica de Retentar.
-
Use rollback() nos tratadores de exceções para limpar transações falhadas. Sem um rollback explícito, a ligação permanece num estado de transação falhada.
Conteúdo relacionado