Problemen met mssql-python oplossen

Diagnoseer en los veelvoorkomende problemen op bij het gebruik van de mssql-python-driver om verbinding te maken met SQL Server, Azure SQL Database, Azure SQL Managed Instance en SQL database in Microsoft Fabric.

Installatieproblemen

pip-installatie mislukt of compileert vanaf broncode

Symptomen:

error: Microsoft Visual C++ 14.0 or greater is required
ERROR: Failed building wheel for mssql-python

Mogelijke oorzaken en oplossingen:

  • Geen kant-en-klaar wiel voor je platform

    • Controleer of je een ondersteunde Python-versie (3.10 en latere versies) en platform gebruikt. Zie Support-levenscyclus voor de compatibiliteitsmatrix. Werk pip bij voordat je met pip install --upgrade pip installeert. Voor herhaalbare teamomgevingen gebruik je de vergrendelde workflow in herhaalbare implementaties of de containerpatronen in container- en lokale ontwikkeling om lokale machinedrift te verminderen.
  • Virtuele omgeving niet geactiveerd

    • Activeer eerst je virtuele omgeving. Het installeren van Python in het systeem kan permissiefouten of conflicten veroorzaken.
    python -m venv .venv
    .venv\Scripts\activate
    pip install mssql-python
    

  • Ontbrekende Linux-systeembibliotheken

Conflicterende stuurprogramma-installaties

Symptomen:

Importfouten of onverwacht gedrag na het installeren van mssql-python naast pyodbc in dezelfde omgeving.

reparatie:

mssql-python en pyodbc kunnen naast elkaar bestaan. Als je conflicten ziet, creëer dan een schone virtuele omgeving:

python -m venv .venv --clear
.venv\Scripts\activate
pip install mssql-python

Verbindingsproblemen

Kan geen verbinding maken met de server

Symptomen:

OperationalError: [08001] (0) Client unable to establish connection

Mogelijke oorzaken en oplossingen:

  • Server niet bereikbaar

    • Controleer of de servernaam en poort correct zijn.
    • Controleer de netwerkconnectiviteit: ping servername of telnet servername 1433.
    • Zorg ervoor dat de firewall uitgaande verbindingen op poort 1433 toestaat.
  • SQL Server draait niet

    • Controleer of de SQL Server-service is gestart.
    • Voor benoemde instanties controleer je of de SQL Server Browser-service draait.
  • Azure SQL firewall rules

    • Voeg je client IP toe aan de Azure SQL firewallregels in het Azure portal.
    • Voor Azure SQL Managed Instance, zorg ervoor dat je verbinding maakt vanaf een toegestan netwerk.
# 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}")

Aanmelden is mislukt

Symptomen:

OperationalError: [28000] (18456) Login failed for user 'username'.

Mogelijke oorzaken en oplossingen:

  • Niet-overeenkomende verificatiemodus

    • Gebruik voor Azure SQL Database, Azure SQL Managed Instance en SQL database in Fabric bij voorkeur een Microsoft Entra-modus zoals Authentication=ActiveDirectoryDefault.
    • Als je bewust SQL-authenticatie gebruikt, controleer dan of de server het toestaat en dat je het juiste inlogformaat voor dat endpoint gebruikt.
  • Onjuiste SQL-authenticatiegegevens

    • Controleer gebruikersnaam en wachtwoord.
    • Voor Azure SQL, vermeld de volledige gebruikersnaam: username@servername.
  • Gebruiker bestaat niet in de database

    • Controleer of de gebruiker toegang heeft tot de opgegeven database.
    • Controleer of het aanmelden is gekoppeld aan een databasegebruiker.
  • Authenticatie niet geconfigureerd

    • Gebruik Microsoft Entra-authenticatie (aanbevolen): Authentication=ActiveDirectoryDefault.
    • Als je een lokale SQL Server probeert te troubleshooten die SQL-authenticatie zou moeten accepteren, controleer dan of SQL Server mixed mode authenticatie gebruikt.

Verbindingstijdoverschrijding

Symptomen:

OperationalError: [HYT00] (0) Timeout expired
OperationalError: [HYT01] (0) Connection timeout expired

Mogelijke oorzaken en oplossingen:

  • De server reageert traag

    • Verhoog de verbindingstime-out:
    conn = mssql_python.connect(connection_string, timeout=60)
    
  • Netwerklatentie

    • Controleer het netwerkpad naar de server.
    • Overweeg een korter netwerkpad of VPN te gebruiken.
  • Server onder zware belasting

    • Probeer buiten de spitsuren verbinding te maken.
    • Neem contact op met je databasebeheerder.

SSL-certificaatfouten

Symptomen:

OperationalError: [08001] SSL Provider: The certificate chain was issued by an authority that is not trusted

Oplossingen:

Geef eerst de voorkeur aan een vertrouwd certificaat of de lokale ontwikkelingspatronen in Container en lokale ontwikkeling. Gebruik TrustServerCertificate=yes alleen voor lokale ontwikkeling tegen een server die jij beheert.

Voor ontwikkeling en testen met een zelfondertekend certificaat:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes;"
    "TrustServerCertificate=yes;"  # Don't use in production
)

Waarschuwing

TrustServerCertificate=yes is uitsluitend een lokale terugvaloptie. Neem het niet mee naar gedeelde devcontainers, CI-pijplijnen of productie-deployments. Voor bredere richtlijnen, zie Encryptie en certificaten.

Voor productie zorg ervoor dat de juiste certificaten zijn geïnstalleerd en gebruik:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes;"
    "HostnameInCertificate=<server>.domain.com;"
)

Problemen met de uitvoering van query's

Tabel of object niet gevonden

Symptomen:

ProgrammingError: [42S02] (208) Invalid object name 'TableName'.

Mogelijke oorzaken en oplossingen:

  • Verkeerde databasecontext

    # Ensure you're connected to the correct database
    cursor.execute("SELECT DB_NAME()")
    print(cursor.fetchone()[0])
    
  • Schema niet gespecificeerd

    # Use fully qualified name
    cursor.execute("SELECT * FROM dbo.TableName")
    
  • Tabel bestaat niet

    # Check if table exists
    cursor.execute("""
         SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES 
         WHERE TABLE_NAME = 'TableName'
    """)
    

Syntaxisfout

Symptomen:

ProgrammingError: [42000] (102) Incorrect syntax near '...'.

Oplossingen:

  1. Test eerst SQL in SSMS om de syntaxis te verifiëren

  2. Controleer string escaping - gebruik geparametriseerde queries:

    # 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})
    

Parameterfouten

Symptomen:

ProgrammingError: [07001] Wrong number of parameters

Oplossingen:

  1. Tel plaatshouders en parameters - ze moeten overeenkomen

  2. Kies de juiste parameterstijl:

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

Datatypeproblemen

Fouten bij data-tijdconversie

Symptomen:

DataError: [22007] Invalid datetime format

Oplossingen:

Gebruik Python datetime-objecten in plaats van strings:

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

Decimale precisieproblemen

Symptomen:

Getallen lijken afgekapt of onjuist afgerond.

Oplossingen:

Gebruik decimal.Decimal voor precieze numerieke waarden:

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")}
)

Unicode-coderingsproblemen

Symptomen:

Speciale tekens lijken onverstaanbaar of veroorzaken fouten.

Oplossingen:

  1. Gebruik NVARCHAR-kolommen voor Unicode-data in je database

  2. Geef tekenreeksen rechtstreeks door - het stuurprogramma verwerkt de codering:

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

Prestatieproblemen

Langzame query-uitvoering

Mogelijke oorzaken en oplossingen:

  • Ontbrekende indexen: Controleer het query-uitvoeringsplan in SSMS.

  • Grote resultaatsets: Gebruik fetchmany() in plaats van fetchall():

    cursor.arraysize = 1000
    while True:
         rows = cursor.fetchmany()
         if not rows:
             break
         process_rows(rows)
    
  • Verbindingspooling uitgeschakeld: Pooling inschakelen:

    import mssql_python
    mssql_python.pooling(max_size=20, idle_timeout=300)
    

Geheugenproblemen met grote resultaten

Symptomen:

Het Python-proces heeft onvoldoende geheugen.

Oplossingen:

  1. Stroomresultaten in plaats van alles in het geheugen te laden:

    cursor.execute("SELECT * FROM LargeTable")
    for row in cursor:  # Iterates one row at a time
        process_row(row)
    
  2. Gebruik paginering aan de serverzijde:

    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
    

Transactieproblemen

Bereik van tijdelijke tabellen met autocommit

Tijdelijke tabellen (#tablename) die binnen een transactie zijn aangemaakt, verdwijnen wanneer de transactie wordt teruggerold. Dit is een veelvoorkomende bron van verwarring wanneer autocommit uit staat (de standaard):

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

Oplossing: Commit direct na het aanmaken van een tijdelijke tabel, of gebruik autocommit-modus:

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

DDL-instructies die autocommit vereisen, zoals CREATE DATABASE, falen binnen een open transactie. Stel autocommit in voordat je ze uitvoert:

conn.autocommit = True
cursor.execute("CREATE DATABASE TestDB")
conn.autocommit = False

Transactie niet gerealiseerd

Symptomen:

Datawijzigingen blijven niet behouden nadat de verbinding is gesloten.

Oplossing:

Met autocommit=False (de standaardinstelling) moet je commit() aanroepen:

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!

Of gebruik de automatische commit-modus:

conn = mssql_python.connect(connection_string, autocommit=True)

Deadlockfouten

Symptomen:

OperationalError: [40001] (1205) Transaction ... was deadlocked on lock resources with another process

Oplossing:

Retry-logica (zie Retry-logica) behandelt de directe fout, maar terugkerende deadlocks wijzen op een ontwerpprobleem. Om de oorzaak te herstellen, leg je de deadlock-grafiek vast en analyseer je welke statements en locktypes betrokken zijn. Veelvoorkomende oplossingen zijn het herschikken van bewerkingen zodat concurrerende transacties vergrendelingen in dezelfde volgorde verkrijgen, het verkleinen van de transactiescope en het toevoegen van passende indexen om de duur van de vergrendeling te verkorten.

Voor een volledige walkthrough van deadlock-analyse, zie de Deadlocks-gids. Als u Azure SQL Database gebruikt, raadpleeg dan Deadlocks analyseren en voorkomen.

Problemen met bulklading

Beperkingsovertredingen tijdens bulkcopy

Symptomen:

RuntimeError: CHECK constraint ... Conflict occurred in database ...
RuntimeError: Cannot insert duplicate key ... violation of PRIMARY KEY constraint

Oorzaak:

De gegevens in je batch overtreden de tabelbeperkingen (primaire sleutel, unique, CHECK of vreemde sleutel).

reparatie:

Valideer de gegevens voordat je laadt. Voor grote datasets laad je deze eerst in een stagingtabel en voeg je ze vervolgens samen in de doeltabel:

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

Voor upsert-patronen met stagingtabellen, zie Patronen voor het laden en verplaatsen van gegevens.

Kolomafbeeldingsfouten

Symptomen:

RuntimeError: Bulk copy failure - column count mismatch

Oorzaak:

Het aantal kolommen in je data komt niet overeen met het aantal kolommen in de doel-tabel, of de kolommen staan in de verkeerde volgorde.

reparatie:

Zorg ervoor dat je data exact overeenkomt met het tabelschema in volgorde en aantal:

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

Typeverschillen tijdens een bulkcopy

Symptomen:

Gegevens worden geladen, maar waarden worden afgekapt, afgerond of zijn onjuist.

Oorzaak:

Python-waarden worden niet netjes gekoppeld aan de doelkolomtypen. Veelvoorkomende gevallen: float-waarden geladen in decimal-kolommen (precisieverlies), of te lange tekenreeksen geladen in kolommen van vaste lengte.

reparatie:

Gebruik de juiste Python-types die bij jouw schema passen:

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)

Bindingsfouten van het type NumPy

Symptomen:

Parameters falen stilletjes of veroorzaken fouten in het datatype bij gebruik van numpy integer- of float-types.

Oorzaak:

NumPy-typen zoals numpy.int64 en numpy.int32 doorstaan isinstance(x, int) niet in NumPy 2.x. De type-inferentie van de bestuurder herkent ze niet, wat onverwacht gedrag veroorzaakt.

reparatie:

Converteer numpy-waarden naar native Python-types voordat je bindt:

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"])}
    )

Voor grotere datasets gebruik je in plaats daarvan de integratiepaden van Arrow of pandas , die de typeconversie intern afhandelen.

Bulkkopiëren met tijdelijke tabellen

Symptomen:

cursor.bulkcopy("#TempTable", data) verhoogt RuntimeError: Invalid object name '#TempTable'.

Oorzaak:

bulkcopy() Kan sessie-tijdelijke tabellen (#tablename) niet oplossen vanwege beperkingen in metadata-opzoeken. Globale tijdelijke tabellen (##tablename) en permanente tabellen werken.

reparatie:

Gebruik een globale tijdelijke tabel of een gewone stagingtabel:

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

Voor kleine datasets waarbij een sessie-tijdelijke tabel de voorkeur heeft, gebruik executemany() in plaats daarvan:

cursor.execute("CREATE TABLE #Staging (ID INT, Name NVARCHAR(50))")
cursor.executemany("INSERT INTO #Staging (ID, Name) VALUES (?, ?)", rows)

Container- en CI-problemen

Ontbrekende systeembibliotheken op Linux

Symptomen:

ImportError: libltdl.so.7: cannot open shared object file: No such file or directory
ImportError: libkrb5.so.3: cannot open shared object file

reparatie:

Installeer de benodigde systeempakketten. De pakketten verschillen per distributie:

Distribution Opdracht Installeren
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

Voor voorbeelden van Dockerfile, zie Container en lokale ontwikkeling.

macOS SSL-fouten na installatie

Symptomen:

SSL-gerelateerde fouten bij verbinding vanaf macOS, vooral op Apple Silicon.

reparatie:

Installeer OpenSSL via Homebrew en stel de linker-vlaggen in:

brew install openssl
export LDFLAGS="-L/opt/homebrew/opt/openssl/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl/include"

Diagnostische hulpmiddelen

Driver logging inschakelen

Gebruik mssql_python.setup_logging() om uitgebreide DEBUG-logging in te schakelen voor probleemoplossing. Alle driverbewerkingen worden gelogd, inclusief SQL-instructies, parameters, interne ODBC-operaties en wijzigingen in de verbindingsstatus.

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

Logbestanden worden geschreven in CSV-formaat en roteren automatisch op 512 MB met vijf back-ups. Gevoelige gegevens zoals wachtwoorden en toegangstokens worden automatisch gezuiverd in de loguitvoer.

Om je eigen logboekvermeldingen naast driverlogs toe te voegen, gebruik 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

Waarschuwing

Logging brengt prestatie-overhead met zich mee. Schakel het alleen in tijdens het oplossen van problemen, niet standaard in productie.

Vraag om chauffeursinformatie

Haal de driverversie en servergegevens op van een actieve verbinding:

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)}")

Verbindingsstatus controleren

Test of een verbinding nog open is voordat je bewerkingen probeert:

try:
    cursor = conn.cursor()
    cursor.execute("SELECT 1")
    print("Connection is open")
except mssql_python.Error:
    print("Connection is closed or broken")

Snelle referentie: Veelvoorkomende fouten

Fout SQLSTATE Veelvoorkomende oorzaak Snelle oplossing
Client kan geen verbinding tot stand brengen 08001 Server onbereikbaar Controleer servernaam/poort
Aanmelden is mislukt 28000 Verkeerde kwalificaties Verifieer gebruikersnaam/wachtwoord
Time-out verlopen HYT00/HYT01 Traag netwerk Time-out verlengen
Ongeldige objectnaam 42S02 Verkeerde tabel/schema Gebruik volledig gekwalificeerde namen
Syntaxisfout 42000 SQL-fout Geparameteriseerde query's gebruiken
Beperkingsschending 23000 FK/PK-schending Controleer de integriteit van de data
Impasse 40001 Conflict bij vergrendeling Probeer het opnieuw, en analyseer vervolgens de deadlock-grafiek