Datatype-mappings voor mssql-python

De mssql-python-driver koppelt automatisch Python-datatypes aan SQL Server-types bij het verzenden van parameters en zet SQL Server-types om naar Python-types bij het ophalen van resultaten.

Python naar SQL Server-mappings

Wanneer je Python-waarden als parameters aan execute() of executemany()doorgeeft, selecteert de driver automatisch het juiste type SQL Server. Voor de meeste toepassingen is de automatische mapping correct. Gebruik setinputsizes() (later beschreven in dit artikel) alleen wanneer je de standaard moet overschrijven, bijvoorbeeld om varchar te forceren in plaats van nvarchar of om parametermetadata voor string- en integer-invoer te regelen.

type van Python SQL Server-type Aantekeningen
None NULL SQL NULL-waarde.
bool bit True→1, False→0.
int tinyint, smallint, int, bigint Grootte gekozen op basis van waardebereik.
float float 64-bits drijfkomma.
decimal.Decimal Decimaal, numeriek Behoud van precisie tot 38 cijfers.
str Varchar, Nvarchar Gebruikt nvarchar voor Unicode-content.
bytes, bytearray varbinary Binaire gegevens.
datetime.date date Alleen op date.
datetime.time time Alleen tijd.
datetime.datetime datetime2 Datum en tijd met nanosecondenprecisie.
uuid.UUID uniqueidentifier 16-byte GUID.

Selectie van gehele getaltypes

De driver selecteert automatisch het kleinste gehele getal dat de waarde kan bevatten:

Waardebereik SQL Server-type
0 tot 255 tinyint
-32.768 tot 32.767 smallint
-2.147.483.648 tot 2.147.483.647 int
Grotere waarden bigint

Grote waardetypen

Voor strings en binaire gegevens die de standaardlimieten overschrijden, gebruikt de driver automatisch MAX-typen:

Conditie SQL Server-type
String > 8.000 bytes (varchar) varchar(max)
String > 4.000 tekens (nvarchar) nvarchar(max)
Binair > 8.000 bytes varbinary(max)

De driver streamt grote waarden naar de server om het geheugengebruik te minimaliseren.

SQL Server naar Python-mappingen

Wanneer de driver gegevens ophaalt van SQL Server, zet de driver waarden om naar Python-typen:

SQL Server-type type van Python Aantekeningen
bit bool Waar/onwaar.
tinyint, smallint, int, bigint int Python integer (willekeurige precisie).
real float 32-bits drijvende komma.
float float 64-bits drijfkomma.
Decimaal, numeriek decimal.Decimal Dat behoudt precisie.
geld, kleingeld decimal.Decimal Vaste precisie (vier decimalen).
Char, Varchar, tekst str Gedecodeerd als UTF-8.
nchar, nvarchar, ntext str Gedecodeerd als UTF-16LE.
binair, varbinary, afbeelding bytes Rauw binair.
date datetime.date Alleen op date.
time datetime.time Tijd met microsecondenprecisie.
Datetime, smalldatetime datetime.datetime Legacy datumtijdtypes.
datetime2 datetime.datetime Hoge precisie op date-tijd.
datetimeoffset datetime.datetime Tijdzonebewuste datetime.
uniqueidentifier uuid.UUID Python UUID-objecten.
xml str XML als tekst.
Geografie, meetkunde bytes Ruimtelijke types als binair.
hierarchyid bytes Hiërarchiegegevens als binair.
sql_variant Varies Opgelost op het onderliggende basistype. sql_variant Kolommen gebruiken een streaming fetch-pad, wat een lichte prestatie-impact kan hebben vergeleken met vaste type kolommen.
NULL None Python Geen.

SQL-typeconstanten

De driver exporteert constanten die overeenkomen met ODBC SQL-type-identificaties. Je gebruikt deze constanten setinputsizes() meestal om de standaard type-inferentie van de bestuurder te overschrijven wanneer de automatische mapping niet overeenkomt met jouw schema.

Tekentypen

Constant Waarde Beschrijving
SQL_CHAR 1 ANSI-personage met vaste lengte.
SQL_VARCHAR 12 ANSI-karakter van variabele lengte.
SQL_LONGVARCHAR -1 Lange variabele lengte ANSI.
SQL_WCHAR -8 Unicode met vaste lengte.
SQL_WVARCHAR -9 Unicode van variabele lengte.
SQL_WLONGVARCHAR -10 Lange variabele lengte Unicode.

Numerieke typen

Constant Waarde Beschrijving
SQL_BIT -7 Bit/booleaan.
SQL_TINYINT -6 8-bits geheel getal zonder teken.
SQL_SMALLINT 5 16-bits ondertekend geheel getal.
SQL_INTEGER 4 32-bits ondertekend geheel getal.
SQL_BIGINT -5 64-bits getekend geheel getal.
SQL_REAL 7 32-bits drijvende komma.
SQL_FLOAT 6 64-bits drijfkomma.
SQL_DOUBLE 8 64-bits drijfkomma.
SQL_DECIMAL 3 Vaste precisie decimaal.
SQL_NUMERIC 2 Vaste precisie numeriek.

Datum- en tijdtypen

Constant Waarde Beschrijving
SQL_TYPE_DATE 91 Alleen op date.
SQL_TYPE_TIME 92 Alleen tijd.
SQL_TYPE_TIMESTAMP 93 Datum en tijd.
SQL_SS_TIME2 -154 SQL Server time(n).
SQL_DATETIMEOFFSET -155 SQL Server datetimeoffset.

Opmerking

SQL_SS_TIME2 en SQL_DATETIMEOFFSET zijn interne constanten die niet als module-niveau attributen worden geëxporteerd. Gebruik direct de gehele getalwaarden (-154, -155) bij het aanroepen add_output_converter()van .

Binaire typen

Constant Waarde Beschrijving
SQL_BINARY -2 Binaire variabele lengte met vaste lengte.
SQL_VARBINARY -3 Variabele lengte binaire functie.
SQL_LONGVARBINARY -4 Lange variabele lengte binaire artiesten.

Andere typen

Constant Waarde Beschrijving
SQL_GUID -11 Uniqueidentifier.
SQL_XML -152 XML-gegevens.
SQL_SS_UDT -151 Door de gebruiker gedefinieerd type (ruimtelijk).
SQL_SS_VARIANT -150 sql_variant data.

Opmerking

SQL_SS_UDT en SQL_SS_VARIANT zijn interne constanten die niet als module-niveau attributen worden geëxporteerd. Gebruik direct de gehele getalwaarden (-151, -150) bij het aanroepen add_output_converter()van .

Gebruik setinputsizes()

Roep setinputsizes() eerder executemany() aan om expliciet parametertypes te declareren wanneer de automatische typeinferentie van de bestuurder onverwacht gedrag veroorzaakt, bijvoorbeeld wanneer een kolom is varchar(100) maar de driver stuurt nvarchar:

Opmerking

Voor decimale waarden kun je vertrouwen op de automatische typeinferentie van de bestuurder in plaats van SQL_DECIMAL op of SQL_NUMERIC. Die expliciete decimale typeconstanten hebben momenteel een bekend probleem met setinputsizes(). Voor meer informatie, zie Uitvoeren van zoekopdrachten.

import mssql_python

conn = mssql_python.connect(connection_string)
cursor = conn.cursor()

# Declare types: (sql_type, precision, scale)
cursor.setinputsizes([
    (mssql_python.SQL_WVARCHAR, 100, 0),  # nvarchar(100)
    (mssql_python.SQL_INTEGER, 0, 0),     # int
])

cursor.executemany(
    "SELECT ProductID, Name FROM Production.Product WHERE Name LIKE ? AND ProductSubcategoryID = ?",
    [
        ("Road%", 2),
        ("Mountain%", 1),
    ]
)

Decimaalteken

De bestuurder gebruikt locale-bewuste decimale scheidingstekens. Om aan te passen:

import mssql_python

# Get current separator
sep = mssql_python.getDecimalSeparator()
print(f"Current separator: {sep}")  # Usually "."

# Set custom separator (for locales using comma)
mssql_python.setDecimalSeparator(",")

Aangepaste type omzetters

Registreer aangepaste converters voor specifieke SQL-typen:

import mssql_python
from decimal import Decimal

def money_to_float(value):
    """Convert money values to float instead of Decimal."""
    if value is None:
        return None
    return float(value)

conn.add_output_converter(Decimal, money_to_float)

Voor meer informatie, zie Custom type converters.

Hanteer speciale types

UUID-behandeling

De driver wordt automatisch toegewezen uuid.UUIDuniqueidentifier . Je kunt UUID's invoegen en ophalen zonder handmatige stringconversie:

import uuid

cursor.execute("CREATE TABLE #Users (UserId UNIQUEIDENTIFIER PRIMARY KEY, Name NVARCHAR(100))")

# Insert a generated UUID
user_id = uuid.uuid4()
cursor.execute("INSERT INTO #Users (UserId, Name) VALUES (%(user_id)s, %(name)s)", {"user_id": user_id, "name": "Alice"})
conn.commit()

# Retrieve as uuid.UUID object (default behavior)
cursor.execute("SELECT UserId, Name FROM #Users WHERE Name = %(name)s", {"name": "Alice"})
row = cursor.fetchone()
print(f"Type: {type(row.UserId)}")  # <class 'uuid.UUID'>
print(f"UUID: {row.UserId}")        # e.g., 3b4c8f2a-...

# Use the returned UUID directly in subsequent queries
cursor.execute("SELECT Name FROM #Users WHERE UserId = %(user_id)s", {"user_id": row.UserId})

Standaard levert de driver kolommen als UNIQUEIDENTIFIER objecten teruguuid.UUID. Om pyodbc-compatibele hoofdletterstrings terug te geven, zet native_uuid=Falseje :

import uuid

# Per-connection: return UUIDs as strings
conn2 = mssql_python.connect(connection_string, native_uuid=False)
cursor2 = conn2.cursor()
cursor2.execute("CREATE TABLE #UuidDemo (Id UNIQUEIDENTIFIER DEFAULT NEWID(), Label NVARCHAR(50))")
cursor2.execute("INSERT INTO #UuidDemo (Label) VALUES (%(label)s)", {"label": "test"})
conn2.commit()

cursor2.execute("SELECT Id FROM #UuidDemo")
row = cursor2.fetchone()
print(type(row[0]))  # <class 'str'>
print(row[0])        # e.g., 3B4C8F2A-...
conn2.close()

Voor module-niveau configuratie, zie de native_uuid instelling in Moduleconfiguratie.

Datumtijd met tijdzone

datetimeoffset kolommen geven objecten terug die zich bewust datetime zijn van de tijdzone. Voor richtlijnen over het werken met offset-aware versus offset-naïeve waarden, zie Datetime handling.

cursor.execute("SELECT SYSDATETIMEOFFSET()")
row = cursor.fetchone()
dt = row[0]

print(f"DateTime: {dt}")
print(f"Timezone: {dt.tzinfo}")

Ruimtelijke gegevens

De driver geeft ruimtelijke types (geography, geometry) terug als bytes. Je kunt parameterstrings gebruiken in WKT-formaat:

# Insert using WKT
cursor.execute("CREATE TABLE #Locations (Name NVARCHAR(100), Geo GEOGRAPHY)")
cursor.execute(
    "INSERT INTO #Locations (Name, Geo) VALUES (%(name)s, geography::STGeomFromText(%(wkt)s, 4326))",
    {"name": "Seattle", "wkt": "POINT(-122.33 47.60)"}
)

# Retrieve as bytes
cursor.execute("SELECT Geo.STAsBinary() FROM #Locations")
row = cursor.fetchone()
geo_bytes = row[0]

Rijversie/Tijdstempel

SQL Server's rowversion (voorheen timestamp) is een binair type, geen datumtijd:

cursor.execute("""
    CREATE TABLE #RowVersionDemo (
        ID int PRIMARY KEY,
        Version rowversion
    )
""")
cursor.execute("INSERT INTO #RowVersionDemo (ID) VALUES (1)")
cursor.execute("SELECT Version FROM #RowVersionDemo WHERE ID = 1")
row = cursor.fetchone()
version = row[0]  # bytes, not datetime

Stream-typen met grote waarde

Bij het invoegen of ophalen varchar(max)van , nvarchar(max), of varbinary(max) data, gebruikt de driver Data-at-Execution (DAE) streaming om data in stukken te verzenden in plaats van de volledige waarde in één keer in het geheugen te laden.

Streaming wordt automatisch geactiveerd wanneer de invoerdata de groottedrempels overschrijdt:

Gegevenstype Streamingdrempel
varchar(max) > 8.000 bytes
nvarchar(max) > 4.000 tekens
varbinary(max) > 8.000 bytes

Streaming werkt met execute(), executemany(), en alle fetch API's (fetchone(), fetchmany(), fetchall()). De driver vereist geen speciale configuratie en verwerkt streaming automatisch voor grote waarden.

Niet-ondersteunde SQL Server-typen

De volgende SQL Server-types hebben geen native Python-type mappings.

SQL Server-type Status
json Niet ondersteund
vector Niet ondersteund
table Niet ondersteund (tabelwaardige parameters)

Tip

Hoewel het json type SQL Server niet direct wordt ondersteund, kun je JSON-gegevens in nvarchar(max) kolommen opslaan en deze opvragen met SQL Server JSON-functies (JSON_VALUE, JSON_QUERY, OPENJSON). Voor patronen en voorbeelden, zie JSON-gegevens.

De volgende types geven data terug alsbytes, maar hebben geen native Python-type mappings:

SQL Server-type type van Python Aantekeningen
geography bytes Gebruik .STAsBinary() voor WKB-formaat.
geometry bytes Gebruik .STAsBinary() voor WKB-formaat.
hierarchyid bytes Binaire representatie.
sql_variant Varies Opgelost op het onderliggende basistype.

Decimale versus floatprecisie

Gebruik decimal.Decimal wanneer exacte precisie belangrijk is, zoals financiële berekeningen, valuta of elke waarde waarbij afrondingsfouten onacceptabel zijn. Gebruik float wanneer benaderende waarden acceptabel zijn, zoals wetenschappelijke metingen of sensormetingen.

De driver is gekoppeld decimal.Decimal aan SQL Server decimal/numeric en behoudt precisie tot 38 cijfers. floatafbeeldingen naar SQL Server float (64-bit IEEE 754), wat afrondingsartefacten kan introduceren:

from decimal import Decimal

# Exact - use for currency and financial data
price = Decimal("19.99")
tax_rate = Decimal("0.0825")
total = price * (1 + tax_rate)  # Decimal("21.6391750")

cursor.execute("""
    CREATE TABLE #PrecisionDemo (
        Description NVARCHAR(100),
        DiscountPct DECIMAL(5,2),
        Rating FLOAT
    )
""")

cursor.execute(
    "INSERT INTO #PrecisionDemo (Description, DiscountPct, Rating) VALUES (%(desc)s, %(pct)s, %(rating)s)",
    {"desc": "Summer sale", "pct": Decimal("0.15"), "rating": 4.5}
)

cursor.execute("SELECT DiscountPct, Rating FROM #PrecisionDemo WHERE Description = %(desc)s", {"desc": "Summer sale"})
row = cursor.fetchone()
print(type(row.DiscountPct))  # <class 'decimal.Decimal'>
print(type(row.Rating))       # <class 'float'>

Bij het decimal/numeric ophalen van kolommen geeft de driver altijd objecten terug.decimal.Decimal Bij het float/real ophalen van kolommen geeft de driver Python . float

Warning

Vergelijk float geen waarden voor gelijkheid. Gebruik in plaats daarvan een tolerantiebereik: abs(a - b) < 0.0001.

Numpy-type binding

De mssql-python driver gebruikt isinstance() controles om SQL-types voor parameters te bepalen. Numpy integertypes (numpy.int64, , ) numpy.int32worden niet doorgegeven numpy.int8 in NumPy 2.x, wat leidt tot isinstance(x, int)binding failures. Werkt alleen numpy.float64 direct omdat het een subklasse van Python floatis.

Converteer numpy-waarden naar native Python-types voordat je ze als parameters doorgeeft:

import numpy as np

row_id = np.int64(42)
score = np.float32(3.14)

# This fails: numpy.int64 is not recognized as int
# cursor.execute("SELECT * FROM Products WHERE ID = ?", (row_id,))

# Convert to native Python types first
cursor.execute(
    "SELECT * FROM Production.Product WHERE ProductID = %(product_id)s",
    {"product_id": int(row_id)}
)

# For DataFrames, convert the whole column
import pandas as pd

df = pd.DataFrame({"ProductID": [1, 2, 3], "Quantity": [10, 20, 30]})

cursor.execute("CREATE TABLE #Orders (ProductID INT, Quantity INT)")

for _, row in df.iterrows():
    cursor.execute(
        "INSERT INTO #Orders (ProductID, Quantity) VALUES (%(product_id)s, %(quantity)s)",
        {"product_id": int(row["ProductID"]), "quantity": int(row["Quantity"])}
    )

Als je veel werkt met pandas of numpy-data, overweeg dan de Arrow-integratie - of pandas-integratiepaden te gebruiken, die de typeconversie intern regelen.