Datatypmappningar för mssql-python

mssql-python-drivrutinen mappar automatiskt Python-datatyper till SQL Server-typer när parametrar skickas och konverterar SQL Server-typer till Python-typer vid resultatinsamling.

Python till SQL Server-mappningar

När du skickar Python-värden som parametrar till execute() eller executemany(), väljer drivrutinen automatiskt rätt SQL Server-typ. För de flesta tillämpningar är den automatiska mappningen korrekt. Använd setinputsizes() (beskrivs senare i denna artikel) endast när du behöver åsidosätta standarden, till exempel för att tvinga varchar istället för nvarchar eller för att kontrollera parametermetadata för sträng- och heltalsindata.

Python-typ SQL Server-typ Noteringar
None NULL SQL NULL-värde.
bool bit True→1, False→0.
int tinyint, littleint, int, bigint Storlek vald baserat på värdeintervall.
float float 64-bitars flyttal.
decimal.Decimal decimal, numerisk Bevarar precision upp till 38 siffror.
str Varchar, Nvarchar Använder nvarchar för Unicode-innehåll.
bytes, bytearray varbinary Binära data.
datetime.date date Endast dejt.
datetime.time time Endast tid.
datetime.datetime datetime2 Datum och tid med nanosekundprecision.
uuid.UUID uniqueidentifier 16-bytes GUID.

Heltalstypval

Drivrutinen väljer automatiskt den minsta heltalstypen som kan hålla värdet:

Värdeintervall SQL Server-typ
0 till 255 tinyint
-32 768 till 32 767 smallint
-2 147 483 648 till 2 147 483 647 int
Större värden bigint

Stora värdetyper

För strängar och binär data som överskrider standardgränser använder drivrutinen automatiskt MAX-typer:

Tillstånd SQL Server-typ
Sträng > 8 000 byte (varchar) varchar(max)
Sträng > 4 000 tecken (nvarchar) nvarchar(max)
Binär > 8 000 byte varbinary(max)

Drivrutinen strömmar stora värden till servern för att minimera minnesanvändningen.

SQL Server till Python-mappningar

När drivrutinen hämtar data från SQL Server konverterar drivrutinen värden till Python-typer:

SQL Server-typ Python-typ Noteringar
bit bool Sant/falskt.
tinyint, littleint, int, bigint int Python heltal (godtycklig precision).
real float 32-bitars flyttal.
float float 64-bitars flyttal.
decimal, numerisk decimal.Decimal Bevarar precisionen.
pengar, småpengar decimal.Decimal Fast precision (fyra decimaler).
Char, Varchar, text str Avkodad som UTF-8.
Nchar, Nvarchar, ntext str Avkodad som UTF-16LE.
binär, varbinär, bild bytes Rå binär.
date datetime.date Endast dejt.
time datetime.time Tid med mikrosekundprecision.
Datumtid, smådatetid datetime.datetime Legacy-datum-tid-typer.
datetime2 datetime.datetime Hög precision på datetime.
datetimeoffset datetime.datetime Tidszonsmedveten datetime.
uniqueidentifier uuid.UUID Python UUID-objekt.
xml str XML som text.
json str JSON-dokumentet som text.
vector str Vektor som en JSON-arraysträng.
Geografi, geometri bytes Rumsliga typer som binära.
hierarchyid bytes Hierarkidata som binär.
sql_variant Varierar Löst till den underliggande bastypen. sql_variant Kolumner använder en strömmande hämtaväg, vilket kan ha en liten prestandapåverkan jämfört med kolumner av fast typ.
NULL None Python Ingen.

SQL-typkonstanter

Drivrutinen exporterar konstanter som motsvarar ODBC SQL-typidentifierare. Du brukar använda dessa konstanter för setinputsizes() att åsidosätta förarens standardtypinferens när den automatiska mappningen inte matchar ditt schema.

Teckentyper

Konstant Värde Beskrivning
SQL_CHAR 1 ANSI-tecken med fast längd.
SQL_VARCHAR 12 ANSI-tecken med variabel längd.
SQL_LONGVARCHAR -1 Lång variabel längd ANSI.
SQL_WCHAR -8 Unicode med fast längd.
SQL_WVARCHAR -9 Unicode med variabel längd.
SQL_WLONGVARCHAR -10 Lång variabel längd Unicode.

Numeriska typer

Konstant Värde Beskrivning
SQL_BIT -7 Bit/booleskt.
SQL_TINYINT -6 8-bitars osignerat heltal.
SQL_SMALLINT 5 16-bitars signerat heltal.
SQL_INTEGER 4 32-bitars signerat heltal.
SQL_BIGINT -5 64-bitars signerat heltal.
SQL_REAL 7 32-bitars flyttal.
SQL_FLOAT 6 64-bitars flyttal.
SQL_DOUBLE 8 64-bitars flyttal.
SQL_DECIMAL 3 Fast decimalprecision.
SQL_NUMERIC 2 Numerisk med fast precision.

Datum- och tidstyper

Konstant Värde Beskrivning
SQL_TYPE_DATE 91 Endast dejt.
SQL_TYPE_TIME 92 Endast tid.
SQL_TYPE_TIMESTAMP 93 Datum och tid.
SQL_SS_TIME2 -154 SQL Server time(n).
SQL_DATETIMEOFFSET -155 SQL Server datetimeoffset.

Note

SQL_SS_TIME2 och SQL_DATETIMEOFFSET är interna konstanter som inte exporteras som modulnivåattribut. Använd heltalsvärdena (-154, -155) direkt när du anropar add_output_converter().

Binära typer

Konstant Värde Beskrivning
SQL_BINARY -2 Binära med fast längd.
SQL_VARBINARY -3 Variabellängds binär.
SQL_LONGVARBINARY -4 Långvarigad binär.

Andra typer

Konstant Värde Beskrivning
SQL_GUID -11 Unikidentifierare.
SQL_XML -152 XML-data.
SQL_SS_UDT -151 Användardefinierad typ (rumslig).
SQL_SS_VARIANT -150 sql_variant data.

Note

SQL_SS_UDT och SQL_SS_VARIANT är interna konstanter som inte exporteras som modulnivåattribut. Använd heltalsvärdena (-151, -150) direkt när du anropar add_output_converter().

Använd setinputsizes()

Anropa setinputsizes() före executemany() för att uttryckligen deklarera parametertyper när förarens automatiska typinferens orsakar oväntat beteende, till exempel när en kolumn är varchar(100) men föraren skickar nvarchar:

Note

För decimalvärden, förlita dig på förarens automatiska typinferens snarare än SQL_DECIMAL eller SQL_NUMERIC. Dessa explicita decimaltypkonstanter har för närvarande ett känt problem med setinputsizes(). För mer information, se Utför frågor.

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),
    ]
)

Decimaltecken

Föraren använder lokalmedvetna decimalseparatorer. Så här anpassar du:

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

Specialtypomvandlare

Registrera anpassade konverterare för specifika SQL-typer:

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)

För mer information, se Anpassade typomvandlare.

Hantera specialtyper

UUID-hantering

Drivrutinen mappas uuid.UUID automatiskt till uniqueidentifier det. Du kan sätta in och hämta UUID:er utan manuell strängkonvertering:

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

Som standard returnerar UNIQUEIDENTIFIER drivrutinen kolumner som uuid.UUID objekt. För att returnera pyodbc-kompatibla versalisatorsträngar istället, sätt native_uuid=False:

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

För modulnivåkonfiguration, se inställningen native_uuid i Modulkonfiguration.

Datumtid med tidszon

datetimeoffset kolumner returnerar objekt som är tidszonsmedvetna datetime . För vägledning om hur man arbetar med offset-medvetna kontra offset-naive värden, se Datetime-hantering.

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

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

Geodata

Drivern returnerar rumsliga typer (geography, geometry) som bytes. Du kan använda parametersträngar i WKT-format:

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

Radversion/tidsstämpel

SQL Server rowversion (tidigare timestamp) är en binär typ, inte en datetime:

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

Strömtyper med stort värde

När man infogar eller hämtar varchar(max), nvarchar(max), eller varbinary(max) data, använder drivrutinen Data-at-Execution (DAE) strömning för att överföra data i delar istället för att ladda hela värdet i minnet på en gång.

Streaming aktiveras automatiskt när indatan överskrider storlekströskeln:

Datatyp Strömningströskel
varchar(max) > 8 000 byte
nvarchar(max) > 4 000 tecken
varbinary(max) > 8 000 byte

Streaming fungerar med execute(), executemany(), och alla hämta-API:er (fetchone(), fetchmany(), fetchall()). Drivrutinen kräver ingen speciell konfiguration och hanterar streaming automatiskt för stora värden.

Icke-stödda SQL Server-typer

Följande SQL Server-typer har inte inbyggda Python-typer.

SQL Server-typ Status
table Ej stödd (tabellvärda parametrar)

Tip

Drivern returnerar json och vector värderar som str. På servrar utan den inbyggda json typen, lagra JSON-data i nvarchar(max) kolumner och fråga den med SQL Server JSON-funktioner (JSON_VALUE, JSON_QUERY, OPENJSON). För mönster och exempel, se JSON-data.

Följande typer returnerar data som bytes men har inte inbyggda Python-typer:

SQL Server-typ Python-typ Noteringar
geography bytes Användning .STAsBinary() för WKB-format.
geometry bytes Användning .STAsBinary() för WKB-format.
hierarchyid bytes Binära representation.
sql_variant Varierar Löst till den underliggande bastypen.

Decimal kontra flottörprecision.

Använd decimal.Decimal när exakt precision är viktig, såsom finansiella beräkningar, valuta eller andra värden där avrundningsfel är oacceptabla. Använd float när ungefärliga värden är acceptabla, såsom vetenskapliga mätningar eller sensoravläsningar.

Drivrutinen mappas decimal.Decimal till SQL Server decimal/numeric och bevarar precision upp till 38 siffror. floatmappar till SQL Server float (64-bitars IEEE 754), vilket kan introducera avrundningsartefakter:

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'>

När man hämtar kolumner decimal/numeric returnerar decimal.Decimal drivrutinen alltid objekt. När kolumner hämtas float/real returnerar drivrutinen Python. float

Varning

Jämför float inte värden för jämlikhet. Använd istället ett toleransintervall: abs(a - b) < 0.0001.

Numpy-typbindning

Drivrutinen mssql-python använder isinstance() kontroller för att bestämma SQL-typer för parametrar. Numpy-heltalstyper (numpy.int64, numpy.int32, numpy.int8) passerar isinstance(x, int) inte i NumPy 2.x, vilket orsakar bindningsfel. Fungerar bara numpy.float64 direkt eftersom det är en underklass av Pythonfloat.

Konvertera numpy-värden till inbyggda Python-typer innan du skickar dem som parametrar:

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

Om du arbetar mycket med pandas eller numpy-data, överväg att använda Arrow-integrationen eller pandas-integrationsvägarna , som hanterar typkonvertering internt.