Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Use este artigo para diagnosticar problemas de execução de consultas, tipo de dado, desempenho, transação e cópia em massa com o mssql-python driver.
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 incorreto do banco de dados
cursor.execute("SELECT DB_NAME()") print(cursor.fetchone()[0])Esquema não especificado
cursor.execute("SELECT * FROM dbo.TableName")A tabela não existe
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 a instrução SQL no SQL Server Management Studio (SSMS) para verificar a sintaxe.
Use uma consulta parametrizada em vez de interpolação de strings:
# Don't use string interpolation for query parameters. cursor.execute(f"SELECT * FROM Production.Product WHERE Name = '{name}'") # 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 espaços reservados e os parâmetros. As contagens devem coincidir.
Escolha o estilo de parâmetros correto:
# Qmark style: positional parameters cursor.execute( "SELECT * FROM Production.Product " "WHERE ProductID = ? AND Name LIKE ?", (1, "Adjustable%"), ) print(cursor.fetchone()) # Pyformat style: named parameters cursor.execute( "SELECT * FROM Production.Product " "WHERE ProductID = %(id)s AND Name LIKE %(name)s", {"id": 1, "name": "Adjustable%"}, ) print(cursor.fetchone())
Contagens incorretas de linhas em lotes com múltiplos resultados
Se rowcount repetir a contagem da primeira instrução após nextset(), atualize o driver. Cada atualização bem-sucedida nextset() atualiza a contagem do novo resultado. Um resultado que produz linhas começa em -1 antes de buscar. Verifique cursor.description antes de recuperar porque os resultados de modificação de dados contêm contagens em vez de linhas.
Deixe SET NOCOUNT desativado quando precisar de resultados de linhas afetadas. Para um exemplo completo, veja Rastreie cada resultado em um lote.
Questões com tipos de dados
Erros de conversão de data e hora
Sintomas:
DataError: [22007] Invalid datetime format
Solution:
Use objetos Python datetime em vez de strings.
from datetime import datetime
cursor.execute("CREATE TABLE #Events (EventDate DATETIME)")
# This value raises an error because the date is invalid.
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}")
# Use a Python datetime object.
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())
O construtor de timestamp requer um argumento de microssegundos
Se Timestamp(year, month, day, hour, minute, second) levantar TypeError por um argumento ausente microsecond , atualize mssql-python. O driver atual aceita o construtor DB-API de seis argumentos e define microsecond como zero por padrão. Para mais informações, veja DB-API construtor de carimbo de tempo.
Questões de precisão decimal
Sintomas:
Os números parecem truncados ou arredondados incorretamente.
Solution:
decimal.Decimal Use para valores numéricos precisos:
from decimal import Decimal
cursor.execute("CREATE TABLE #PriceDemo (ListPrice DECIMAL(10, 2))")
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:
Use colunas nvarchar para armazenar dados Unicode em seu banco de dados.
Passe as cordas diretamente. O driver cuida 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 faltando: 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)Agrupamento de conexões desativado: Habilitar agrupamento:
import mssql_python mssql_python.pooling(max_size=20, idle_timeout=300)
Problemas de memória com resultados grandes
Sintomas:
O processo em Python fica sem memória.
Soluções:
Transmita os resultados em fluxo, em vez de carregar todas as linhas na memória.
cursor.execute("SELECT * FROM LargeTable") for row in cursor: process_row(row)Use paginação do lado do 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
Escopo de tabelas temporárias com confirmação automática
Tabelas temporárias de sessão (#tablename) que você cria em uma transação desaparecem quando a transação é revertida. Esse comportamento geralmente causa confusão quando o autocommit está desligado, que é o padrão:
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
# An explicit rollback or an error removes #TempData.
conn.rollback()
# This statement fails with "Invalid object name '#TempData'".
cursor.execute("SELECT * FROM #TempData")
Faça um commit imediatamente após criar uma tabela temporária ou use o modo autocommit:
cursor.execute("CREATE TABLE #TempData (ID INT, Name NVARCHAR(50))")
conn.commit()
cursor.execute("INSERT INTO #TempData VALUES (1, 'test')")
conn.commit()
Instruções DDL que exigem modo autocommit, como CREATE DATABASE, falham dentro de uma transação aberta. Defina o autocommit antes de executá-los:
conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False
Transação não comprometida
Sintomas:
As mudanças nos dados não persistem depois que você fecha a conexão.
Solution:
Com autocommit=False, que é o padrão, chame commit():
cursor.execute("CREATE TABLE #Products (Name NVARCHAR(100))")
cursor.execute(
"INSERT INTO #Products (Name) VALUES (%(name)s)",
{"name": "Widget"},
)
conn.commit()
Alternativamente, use o modo autocommit:
conn = mssql_python.connect(connection_string, autocommit=True)
Erros de deadlock
Sintomas:
OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process
Solution:
A lógica de repetição lida com a falha imediata, mas bloqueios recorrentes indicam um problema de projeto. Capture o grafo de deadlock e analise as instruções e os tipos de bloqueio. As correções comuns incluem estas mudanças:
- Reordene as operações para que transações concorrentes adquiram bloqueios na mesma sequência.
- Reduza o escopo da transação.
- Adicione índices apropriados para reduzir a duração do bloqueio.
Para uma análise completa de deadlocks, consulte o guia de deadlocks. Se você usar o Banco de Dados SQL do Azure, consulte Analisar e evitar impasses.
Problemas de carregamento em massa
Cópia em massa falha após uma atualização de pacote
Se consultas normais funcionarem, mas bulkcopy() ou bulkcopy_arrow() falhar ao importar ou carregar o módulo nativo de cópia em massa, atualize o driver com dependências:
python -m pip install --upgrade mssql-python
python -m pip check
O driver exige um runtime correspondente mssql-python-rs. Uma atualização parcial ou uma instalação com --no-deps pode deixar pacotes incompatíveis instalados. Se você usar um índice de pacotes privado, espelhe ambos os pacotes companheiros e preserve as fixações de versão da dependência declaradas pelo driver. Para as fixações atuais, veja Requisitos de dependência.
Nomes de destino não suportados
bulkcopy() e bulkcopy_arrow() aceitam no máximo três partes identificadoras. Um nome de quatro partes, como server.database.schema.table, gera RuntimeError durante a consulta de metadados antes de qualquer linha ser enviada. Conecte-se diretamente ao servidor de destino e use um nome de tabela de uma, duas ou três partes. Para escape de colchetes e erros de nomes malformados, veja Nomes da tabela de destino.
Unicode ou segundos fracionais perdidos durante cópia em massa
Atualize o driver se a cópia em massa corromper o texto UTF-8 ou truncar frações de segundo ao carregar valores datetime2 compatíveis. O runtime atual de cópia em massa lida com texto UTF-8 e preserva a precisão datetime2 disponível nos tipos de origem e destino.
Use nvarchar ou uma colação UTF-8 no varchar para texto Unicode. Os valores de Python datetime e os métodos de busca Arrow do driver são limitados a microssegundos. Para valores de 100 nanossegundos já mantidos em uma coluna de data/hora de nanossegundos do Arrow, carregue em datetime2(7) sem converter para Python datetime primeiro. Para mais informações, veja Unicode e precisão temporal e precisão temporal do Arrow.
Violações 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 do seu lote violam restrições da tabela, como restrições de chave primária, de unicidade, de verificação ou de chave estrangeira.
Solution:
Valide os dados antes de carregá-los. Para grandes conjuntos de dados, carregue os dados em uma tabela de preparação e depois mescle-os à tabela de destino:
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(100))")
cursor.bulkcopy("##Staging", rows)
# Check for duplicate rows before the merge.
cursor.execute("""
SELECT s.ID
FROM ##Staging AS s
INNER JOIN dbo.Target AS t
ON s.ID = t.ID
""")
dupes = cursor.fetchall()
if dupes:
print(f"Skipping {len(dupes)} duplicate rows")
# Insert rows that don't exist in the target.
cursor.execute("""
INSERT INTO dbo.Target (ID, Name)
SELECT s.ID, s.Name
FROM ##Staging AS s
WHERE NOT EXISTS (
SELECT 1
FROM dbo.Target AS t
WHERE t.ID = s.ID
)
""")
conn.commit()
Para padrões upsert com tabelas de preparação, consulte Padrões de carregamento e movimento 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 à contagem de colunas da tabela alvo, ou as colunas estão na ordem errada.
Solution:
Certifique-se de que seus dados correspondam ao esquema da tabela na ordem e contagem:
from decimal import Decimal
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)
rows = [
(1, "Widget", Decimal("19.99")),
(2, "Gadget", Decimal("29.99")),
]
cursor.bulkcopy("dbo.MyTable", rows)
Incompatibilidades de tipo durante a cópia em massa
Sintomas:
Os dados são carregados, mas os valores são truncados, arredondados ou incorretos.
Causa:
Os valores de Python não correspondem diretamente aos tipos de dados da coluna de destino. Exemplos comuns incluem float valores carregados em colunas decimais , que podem perder precisão, e strings sobredimensionadas carregadas em colunas de comprimento fixo.
Solution:
Use tipos em Python que combinem com seu esquema:
from decimal import Decimal
rows = [
# Use Decimal for decimal and numeric columns.
(1, "Widget", Decimal("19.99")),
# Avoid float values because they can lose precision.
# (1, "Widget", 19.99),
]
cursor.bulkcopy("dbo.Products", rows)
Falhas na vinculação de tipos do NumPy
Sintomas:
Os parâmetros falham silenciosamente ou geram erros de tipo de dados quando você usa tipos inteiros ou de ponto flutuante do NumPy.
Causa:
Tipos de NumPy como numpy.int64 e numpy.int32 não passam isinstance(x, int) no NumPy 2.x. A inferência de tipo do motorista não os reconhece, o que causa comportamentos inesperados.
Solution:
Converta valores do NumPy para tipos nativos de Python antes de vinculá-los:
import numpy as np
cursor.execute(
"SELECT * FROM Production.Product WHERE ProductID = %(product_id)s",
{"product_id": int(np.int64(42))},
)
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 com o Arrow ou o pandas. Esses caminhos gerenciam a conversão de tipos internamente.
Cópia em massa com tabelas temporárias
Sintomas:
cursor.bulkcopy("#TempTable", data) gera RuntimeError: Invalid object name '#TempTable'.
Causa:
bulkcopy() Não é possível resolver tabelas temporárias de sessão (#tablename) por causa das limitações de busca de metadados. Tabelas temporárias globais (##tablename) e tabelas permanentes funcionam.
Solution:
Use uma tabela temporária global ou uma tabela de preparação regular:
# A global temp table is visible to all sessions and is dropped
# when the last session disconnects.
cursor.execute("CREATE TABLE ##Staging (ID INT, Name NVARCHAR(50))")
cursor.bulkcopy("##Staging", rows)
# Alternatively, 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 você prefere uma tabela temporária de sessão, use executemany():
cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany(
"INSERT INTO #Staging (ID, Name) VALUES (?, ?)",
rows,
)