Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Diagnostice e resolva problemas comuns ao utilizar o driver mssql-python para se ligar ao SQL Server, Base de Dados SQL do Azure, Azure SQL Managed Instance e base de dados SQL no Microsoft Fabric.
Problemas de instalação
o pip install falha ou compila a partir do código-fonte
Sintomas:
error: Microsoft Visual C++ 14.0 or greater is required
ERROR: Failed building wheel for mssql-python
Possíveis causas e soluções:
Não há volante pré-montado para a tua plataforma
- Verifica se estás a usar uma versão de Python suportada (versões 3.10 e posteriores) e uma plataforma. Consulte ciclo de vida do suporte para a matriz de compatibilidade. Atualize o pip antes de instalar com
pip install --upgrade pip. Para ambientes de equipa reproduzíveis, utilize o workflow bloqueado em Implementações reproduzíveis ou os padrões de contentores em Contentores e desenvolvimento local para reduzir a divergência das máquinas locais.
- Verifica se estás a usar uma versão de Python suportada (versões 3.10 e posteriores) e uma plataforma. Consulte ciclo de vida do suporte para a matriz de compatibilidade. Atualize o pip antes de instalar com
Ambiente virtual não ativado
- Ative primeiro o seu ambiente virtual. Instalar Python no sistema pode causar erros ou conflitos de permissões.
python -m venv .venv .venv\Scripts\activate pip install mssql-python
-
Bibliotecas do sistema Linux em falta
- O driver requer um pequeno conjunto de bibliotecas de sistema no Linux. Consulte Dependências específicas da plataforma para os pacotes a instalar.
Instalações de drivers conflitantes
Sintomas:
Erros de importação ou comportamentos inesperados após instalar mssql-python ao lado pyodbc no mesmo ambiente.
Correção:
mssql-python e pyodbc podem coexistir. Se vir conflitos, crie um ambiente virtual limpo:
python -m venv .venv --clear
.venv\Scripts\activate
pip install mssql-python
Problemas de conexão
Impossível ligar-se ao servidor
Sintomas:
OperationalError: [08001] (0) Client unable to establish connection
Possíveis causas e soluções:
Servidor inacessível
- Verifica que o nome do servidor e a porta estão corretos.
- Verifique a conectividade da rede:
ping servernameoutelnet servername 1433. - Garante que o firewall permite ligações de saída na porta 1433.
SQL Server não está a correr
- Verifique se o serviço SQL Server foi iniciado.
- Para instâncias nomeadas, verifique se o serviço SQL Server Browser está a funcionar.
Regras de firewall do SQL do Azure
- Adicione o IP do seu cliente às regras do firewall SQL do Azure no portal Azure.
- Para Azure SQL Managed Instance, certifique-se de que está a ligar-se a partir de uma rede permitida.
# Test basic connectivity
import socket
try:
sock = socket.create_connection(("<server>.database.windows.net", 1433), timeout=5)
print("TCP connection successful")
sock.close()
except Exception as e:
print(f"Cannot reach server: {e}")
Início de sessão falhado
Sintomas:
OperationalError: [28000] (18456) Login failed for user 'username'.
Possíveis causas e soluções:
Incompatibilidade dos modos de autenticação
- Para Base de Dados SQL do Azure, Azure SQL Managed Instance e a base de dados SQL no Fabric, privilegie um modo do Microsoft Entra, como
Authentication=ActiveDirectoryDefault. - Se estiveres a usar autenticação SQL intencionalmente, verifica se o servidor a permite e se estás a usar o formato de login correto para esse endpoint.
- Para Base de Dados SQL do Azure, Azure SQL Managed Instance e a base de dados SQL no Fabric, privilegie um modo do Microsoft Entra, como
Credenciais de autenticação SQL incorretas
- Verifique nome de utilizador e palavra-passe.
- Para SQL do Azure, inclua o nome de utilizador completo:
username@servername.
O utilizador não existe na base de dados
- Verifique se o utilizador tem acesso à base de dados especificada.
- Verifique se o início de sessão está mapeado para um utilizador da base de dados.
Autenticação não configurada
- Utilize a autenticação do Microsoft Entra (recomendada):
Authentication=ActiveDirectoryDefault. - Se estiveres a resolver problemas num SQL Server local que deveria aceitar autenticação SQL, verifica se o SQL Server usa autenticação em modo misto.
- Utilize a autenticação do Microsoft Entra (recomendada):
Tempo limite de ligação
Sintomas:
OperationalError: [HYT00] (0) Timeout expired
OperationalError: [HYT01] (0) Connection timeout expired
Possíveis causas e soluções:
O servidor demora a responder
- Aumentar o tempo de espera da ligação:
conn = mssql_python.connect(connection_string, timeout=60)Latência da rede
- Verifique o caminho da rede até ao servidor.
- Considera usar um caminho de rede mais curto ou VPN.
Servidor sob carga elevada
- Tenta ligar-te durante as horas de menor afluência.
- Contacte o administrador da sua base de dados.
Erros de certificado SSL
Sintomas:
OperationalError: [08001] SSL Provider: The certificate chain was issued by an authority that is not trusted
Soluções:
Primeiro, prefira um certificado de confiança ou os padrões de desenvolvimento local em Container e desenvolvimento local. Usa TrustServerCertificate=yes apenas para desenvolvimento local contra um servidor que controlas.
Para desenvolvimento e testes com um certificado auto-assinado:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
"TrustServerCertificate=yes;" # Don't use in production
)
Atenção
TrustServerCertificate=yes é uma alternativa de recurso exclusivamente local. Não a leves para devcontainers partilhados, pipelines de CI ou implementações para produção. Para orientações mais abrangentes, consulte Encriptação e certificados.
Em produção, certifique-se de que os certificados adequados estão instalados e utilize:
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
"HostnameInCertificate=<server>.domain.com;"
)
Problemas de execução de consultas
Tabela ou objeto não encontrado
Sintomas:
ProgrammingError: [42S02] (208) Invalid object name 'TableName'.
Possíveis causas e soluções:
Contexto errado da base de dados
# Ensure you're connected to the correct database cursor.execute("SELECT DB_NAME()") print(cursor.fetchone()[0])Esquema não especificado
# Use fully qualified name cursor.execute("SELECT * FROM dbo.TableName")A tabela não existe
# Check if table exists cursor.execute(""" SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TableName' """)
Erro de sintaxe
Sintomas:
ProgrammingError: [42000] (102) Incorrect syntax near '...'.
Soluções:
Teste primeiro o SQL no SSMS para verificar a sintaxe
Verificar o escape de cadeias de caracteres - use consultas com parâmetros:
# Wrong - vulnerable to syntax issues and SQL injection cursor.execute(f"SELECT * FROM Production.Product WHERE Name = '{name}'") # Correct - use parameters cursor.execute("SELECT * FROM Production.Product WHERE Name = %(name)s", {"name": name})
Erros de parâmetros
Sintomas:
ProgrammingError: [07001] Wrong number of parameters
Soluções:
Conte os marcadores de posição e os parâmetros - devem corresponder
Escolha o estilo de parâmetros correto:
# Qmark style - positional cursor.execute("SELECT * FROM Production.Product WHERE ProductID = ? AND Name LIKE ?", (1, "Adjustable%")) print(cursor.fetchone()) # Pyformat style - named cursor.execute("SELECT * FROM Production.Product WHERE ProductID = %(id)s AND Name LIKE %(name)s", {"id": 1, "name": "Adjustable%"}) print(cursor.fetchone())
Problemas de tipo de dados
Erros de conversão de data e hora
Sintomas:
DataError: [22007] Invalid datetime format
Soluções:
Use objetos data-hora em Python em vez de cadeias de caracteres:
from datetime import datetime
cursor.execute("CREATE TABLE #Events (EventDate DATETIME)")
# Wrong - this raises an error for invalid dates
try:
cursor.execute("INSERT INTO #Events (EventDate) VALUES (%(event_date)s)", {"event_date": "2024-13-45"})
except Exception as e:
print(f"Expected error: {e}")
# Correct - use Python datetime objects
cursor.execute("INSERT INTO #Events (EventDate) VALUES (%(event_date)s)", {"event_date": datetime(2024, 3, 15)})
cursor.execute("SELECT EventDate FROM #Events")
print(cursor.fetchone())
Questões de precisão decimal
Sintomas:
Os números parecem truncados ou arredondados incorretamente.
Soluções:
Utilização decimal.Decimal para valores numéricos precisos:
from decimal import Decimal
cursor.execute("CREATE TABLE #PriceDemo (ListPrice DECIMAL(10,2))")
# Preserve full precision
cursor.execute(
"INSERT INTO #PriceDemo (ListPrice) VALUES (%(list_price)s)",
{"list_price": Decimal("19.99")}
)
Problemas de codificação Unicode
Sintomas:
Caracteres especiais aparecem distorcidos ou causam erros.
Soluções:
Utilize colunas NVARCHAR para dados Unicode na base de dados
Passe as cadeias diretamente - o driver trata da codificação:
cursor.execute("CREATE TABLE #UnicodeDemo (Name NVARCHAR(50))") cursor.execute("INSERT INTO #UnicodeDemo (Name) VALUES (%(name)s)", {"name": "日本語"}) cursor.execute("SELECT Name FROM #UnicodeDemo") print(cursor.fetchone())
Problemas de desempenho
Execução lenta da consulta
Possíveis causas e soluções:
Índices em falta: Verifique o plano de execução da consulta no SSMS.
Grandes conjuntos de resultados: Use
fetchmany()em vez defetchall():cursor.arraysize = 1000 while True: rows = cursor.fetchmany() if not rows: break process_rows(rows)Agregação de ligações desativada: Ativar agregação:
import mssql_python mssql_python.pooling(max_size=20, idle_timeout=300)
Problemas de memória com resultados de grande dimensão
Sintomas:
O processo Python fica sem memória.
Soluções:
Resultados do fluxo em vez de carregar tudo na memória:
cursor.execute("SELECT * FROM LargeTable") for row in cursor: # Iterates one row at a time process_row(row)Utilize a paginação no servidor:
page_size = 1000 offset = 0 while True: cursor.execute( "SELECT * FROM LargeTable ORDER BY ID " "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY", (offset, page_size) ) rows = cursor.fetchall() if not rows: break process_rows(rows) offset += page_size
Questões de transação
Âmbito da tabela temporária com autocommit
As tabelas temporárias (#tablename) criadas dentro de uma transação desaparecem quando a transação é revertida. Esta é uma fonte comum de confusão quando o autocommit está desligado (o padrão):
conn = mssql_python.connect(connection_string) # autocommit=False by default
cursor = conn.cursor()
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
# If the connection rolls back (explicit or on error), #TempData disappears
conn.rollback()
# This fails: Invalid object name '#TempData'
cursor.execute("SELECT * FROM #TempData")
Correção: Faça commit imediatamente após criar uma tabela temporária ou use o modo de confirmação automática:
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
conn.commit() # Lock in the table definition
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
conn.commit()
As instruções DDL que exigem modo de autocommit, como CREATE DATABASE, falham dentro de uma transação aberta. Defina a confirmação automática antes de os executar:
conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False
Transação não comprometida
Sintomas:
As alterações nos dados não persistem após o fecho da ligação.
Solution:
Com autocommit=False (predefinição), tem de chamar commit():
cursor.execute("CREATE TABLE #Products (Name NVARCHAR(100))")
cursor.execute("INSERT INTO #Products (Name) VALUES (%(name)s)", {"name": "Widget"})
conn.commit() # Don't forget this!
Ou utilize o modo autocommit:
conn = mssql_python.connect(connection_string, autocommit=True)
Erros de bloqueio
Sintomas:
OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process
Solution:
A lógica de repetição (ver lógica de repetição) lida com a falha imediata, mas impasses recorrentes indicam um problema de conceção. Para corrigir a causa raiz, capture o gráfico de deadlock e analise quais as instruções e tipos de bloqueio envolvidos. Correções comuns incluem reordenar operações para que transações concorrentes adquiram bloqueios na mesma sequência, reduzir o âmbito das transações e adicionar índices apropriados para diminuir a duração dos bloqueios.
Para uma explicação detalhada da análise de deadlocks, consulte o guia sobre Deadlocks. Se estiveres a usar o Base de Dados SQL do Azure, consulta Analisar e prevenir interbloqueios.
Problemas de carregamento em massa
Violação de restrições durante a cópia em massa
Sintomas:
RuntimeError: CHECK constraint ... Conflict occurred in database ...
RuntimeError: Cannot insert duplicate key ... violation of PRIMARY KEY constraint
Causa:
Os dados no seu lote violam as restrições das tabelas (chave primária, única, CHECK ou chave estrangeira).
Correção:
Valida os dados antes de carregar. Para conjuntos de dados de grande dimensão, carregue-os primeiro para uma tabela intermédia e, em seguida, faça a fusão com a tabela de destino:
# Load into staging, then validate
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(100))")
cursor.bulkcopy("##Staging", rows)
# Check for duplicates before merging
cursor.execute("""
SELECT s.ID FROM ##Staging s
INNER JOIN dbo.Target t ON s.ID = t.ID
""")
dupes = cursor.fetchall()
if dupes:
print(f"Skipping {len(dupes)} duplicate rows")
# Insert only non-duplicate rows
cursor.execute("""
INSERT INTO dbo.Target (ID, Name)
SELECT s.ID, s.Name FROM ##Staging s
WHERE NOT EXISTS (SELECT 1 FROM dbo.Target t WHERE t.ID = s.ID)
""")
conn.commit()
Para padrões de upsert com tabelas de preparação, consulte Padrões de carregamento e movimentação de dados.
Erros de mapeamento de colunas
Sintomas:
RuntimeError: Bulk copy failure - column count mismatch
Causa:
O número de colunas nos seus dados não corresponde ao número de colunas da tabela alvo, ou as colunas estão na ordem errada.
Correção:
Certifique-se de que os seus dados correspondem exatamente ao esquema da tabela na ordem e no número de elementos:
# Check the target table schema
cursor.execute("""
SELECT COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable'
ORDER BY ORDINAL_POSITION
""")
for col in cursor.fetchall():
print(col)
# Match your data to the column order
rows = [
(1, "Widget", Decimal("19.99")), # Must match table column order
(2, "Gadget", Decimal("29.99")),
]
cursor.bulkcopy("dbo.MyTable", rows)
Desajustes de tipo durante a cópia em massa
Sintomas:
Os dados são carregados, mas os valores estão truncados, arredondados ou incorretos.
Causa:
Os valores de Python não correspondem de forma clara aos tipos de coluna de destino. Casos comuns: float valores carregados em decimal colunas (perda de precisão), ou cadeias sobredimensionadas carregadas em colunas de comprimento fixo.
Correção:
Use os tipos corretos de Python que correspondam ao seu esquema:
from decimal import Decimal
# Use Decimal for decimal/numeric columns, not float
rows = [
(1, "Widget", Decimal("19.99")), # Correct
# (1, "Widget", 19.99), # Avoid: float loses precision
]
cursor.bulkcopy("dbo.Products", rows)
Falhas na associação de tipos do NumPy
Sintomas:
Os parâmetros falham silenciosamente ou levantam erros de tipo de dados ao usar números inteiros ou tipos float.
Causa:
Tipos NumPy como numpy.int64 e numpy.int32 não são aceites por isinstance(x, int) no NumPy 2.x. A inferência de tipo do condutor não os reconhece, o que causa comportamentos inesperados.
Correção:
Converter valores numpy para tipos nativos de Python antes de fazer a ligação:
import numpy as np
# Convert individual values
cursor.execute("SELECT * FROM Production.Product WHERE ProductID = %(product_id)s", {"product_id": int(np.int64(42))})
# Convert DataFrame values
for _, row in df.iterrows():
cursor.execute(
"INSERT INTO #Orders (ProductID, Qty) VALUES (%(product_id)s, %(qty)s)",
{"product_id": int(row["ProductID"]), "qty": int(row["Qty"])}
)
Para conjuntos de dados maiores, use os caminhos de integração Arrow ou pandas em vez disso, que tratam internamente da conversão de tipos.
Cópia em massa com tabelas temporárias
Sintomas:
cursor.bulkcopy("#TempTable", data) aumenta RuntimeError: Invalid object name '#TempTable'.
Causa:
bulkcopy() Não é possível resolver tabelas temporárias de sessão (#tablename) devido a limitações de consulta de metadados. As tabelas temporárias globais (##tablename) e as tabelas permanentes funcionam.
Correção:
Use uma tabela temporária global ou uma tabela de preparação regular:
# Global temp table (visible to all sessions, dropped when last session disconnects)
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("##Staging", rows)
# Or use a permanent staging table
cursor.execute("CREATE TABLE dbo.Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("dbo.Staging", rows)
Para conjuntos de dados pequenos onde se prefere uma tabela temporária de sessão, use executemany() em vez disso:
cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany("INSERT INTO #Staging (ID, Name) VALUES (?, ?)", rows)
Questões de contentores e CI
Bibliotecas de sistema em falta no Linux
Sintomas:
ImportError: libltdl.so.7: cannot open shared object file: No such file or directory
ImportError: libkrb5.so.3: cannot open shared object file
Correção:
Instale os pacotes de sistema necessários. Os pacotes diferem pela distribuição:
| Distribution | Comando de Instalação |
|---|---|
| Ubuntu / Debian | sudo apt-get install libltdl7 libkrb5-3 libgssapi-krb5-2 |
| Red Hat / Fedora | sudo dnf install libtool-ltdl krb5-libs |
| Alpine | apk add libltdl krb5-libs |
Para exemplos de Dockerfile, veja Contentor e desenvolvimento local.
Erros SSL do macOS após a instalação
Sintomas:
Erros relacionados com SSL ao ligar a partir do macOS, especialmente no Apple Silicon.
Correção:
Instale o OpenSSL via Homebrew e defina as bandeiras do linker:
brew install openssl
export LDFLAGS="-L/opt/homebrew/opt/openssl/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl/include"
Ferramentas de diagnóstico
Ativar o registo do controlador
Utilize mssql_python.setup_logging() para ativar registos de DEBUG detalhados para diagnóstico de problemas. Todas as operações do driver são registadas, incluindo instruções SQL, parâmetros, operações ODBC internas e alterações no estado da ligação.
import mssql_python
# Enable logging to file (default)
mssql_python.setup_logging()
# Output to stdout (useful for CI/CD and containers)
mssql_python.setup_logging(output='stdout')
# Output to both file and stdout
mssql_python.setup_logging(output='both')
# Custom log file path (must use .txt, .log, or .csv extension)
mssql_python.setup_logging(log_file_path="/var/log/myapp/mssql.log")
Os ficheiros de registo são escritos em formato CSV e rodam automaticamente a 512 MB com cinco backups. Dados sensíveis, como palavras-passe e tokens de acesso, são automaticamente higienizados na saída do log.
Para adicionar as suas próprias entradas de registo juntamente com os registos do controlador, use driver_logger:
from mssql_python.logging import driver_logger
mssql_python.setup_logging()
driver_logger.debug("[App] Starting data processing")
driver_logger.error("[App] Failed to process record")
# Your entries appear in the same file with the same format
Atenção
O registo tem um impacto no desempenho. Ative-o apenas para resolução de problemas, não por predefinição em produção.
Obtenha informações sobre o condutor
Recupere a versão do driver e os dados do servidor de uma ligação ativa:
import mssql_python
conn = mssql_python.connect(connection_string)
# Driver version
print(f"Version: {mssql_python.__version__}")
# Server information
print(f"Server name: {conn.getinfo(mssql_python.SQL_SERVER_NAME)}")
print(f"Database name: {conn.getinfo(mssql_python.SQL_DATABASE_NAME)}")
Verificar o estado da ligação
Teste se uma ligação ainda está aberta antes de tentar operações:
try:
cursor = conn.cursor()
cursor.execute("SELECT 1")
print("Connection is open")
except mssql_python.Error:
print("Connection is closed or broken")
Referência rápida: Erros comuns
| Erro | SQLSTATE | Causa comum | Correção rápida |
|---|---|---|---|
| Cliente incapaz de estabelecer ligação | 08001 | Servidor inacessível | Verifique o nome/porta do servidor |
| Início de sessão falhado | 28000 | Credenciais erradas | Verificar nome de utilizador/palavra-passe |
| O tempo limite expirou | HYT00/HYT01 | Rede lenta | Aumentar o tempo limite |
| Nome do objeto inválido | 42S02 | Tabela/esquema errado | Use nomes totalmente qualificados |
| Erro de sintaxe | 42000 | Erro SQL | Utilizar consultas parametrizadas |
| Violação de restrições | 23000 | Violação FK/PK | Verificar a integridade dos dados |
| Impasse | 40001 | Contenção de bloqueio | Tente novamente e, em seguida, analise o gráfico de interbloqueio |