Mappage de types de données pour mssql-python

Le pilote mssql-python associe automatiquement les types de données Python aux types SQL Server lors de l’envoi de paramètres et convertit les types SQL Server en types Python lors de la récupération des résultats.

Mappages de Python vers SQL Server

Lorsque vous passez des valeurs Python comme paramètres vers execute() ou executemany(), le pilote sélectionne automatiquement le type de SQL Server approprié. Pour la plupart des applications, la correspondance automatique est correcte. Utilisez setinputsizes() (décrite plus loin dans cet article) uniquement lorsque vous devez passer outre le défaut, par exemple pour forcer varchar au lieu de nvarchar ou pour contrôler les métadonnées des paramètres des entrées de chaîne et d’entiers.

Type Python Type SQL Server Notes
None NULL SQL NULL value.
bool bit True→1, False→0.
int Tinyint, smallint, int,bigint Taille sélectionnée en fonction de la plage de valeurs.
float float Virgule flottante 64 bits.
decimal.Decimal décimal, numérique Préserve la précision jusqu’à 38 chiffres.
str Varchar, Nvarchar Utilise nvarchar pour le contenu Unicode.
bytes, bytearray varbinary Données binaires.
datetime.date date Date uniquement.
datetime.time time Juste le temps.
datetime.datetime datetime2 Date et heure avec une précision de nanoseconde.
uuid.UUID uniqueidentifier GHID de 16 octets.

Sélection des types entiers

Le pilote sélectionne automatiquement le plus petit type entier pouvant contenir la valeur :

Plage de valeurs Type SQL Server
0 à 255 tinyint
-32 768 à 32 767 smallint
-2 147 483 648 à 2 147 483 647 int
Valeurs plus grandes bigint

Grandes valeurs

Pour les chaînes et données binaires dépassant les limites standard, le pilote utilise automatiquement les types MAX :

Pathologie Type SQL Server
Chaîne > de 8 000 octets (varchar) varchar(max)
Chaîne > 4 000 caractères (nvarchar) nvarchar(max)
Binaire > 8 000 octets varbinary(max)

Le pilote diffuse de grandes valeurs vers le serveur pour minimiser l’utilisation de la mémoire.

Mappages de SQL Server vers Python

Lorsque le pilote récupère des données depuis SQL Server, il convertit les valeurs en types Python :

Type SQL Server Type Python Notes
bit bool Vrai/Faux.
Tinyint, smallint, int,bigint int Python entier (précision arbitraire).
real float Virgule flottante 32 bits.
float float Virgule flottante 64 bits.
décimal, numérique decimal.Decimal Préserve la précision.
L’argent, petit argent decimal.Decimal Précision fixe (quatre décimales).
Char, Varchar, texte str Décodé en UTF-8.
nchar, nvarchar, ntext str Décodé sous le nom UTF-16LE.
binaire, varbinaire, image bytes Binaire brut.
date datetime.date Date uniquement.
time datetime.time Temps avec une précision de microseconde.
Heure du rendez-vous, PetiteRendez-Heure datetime.datetime Types de dates hérités.
datetime2 datetime.datetime Rendez-vous de haute précision.
datetimeoffset datetime.datetime Date-heure en fonction du fuseau horaire.
uniqueidentifier uuid.UUID Objets UUID Python.
xml str XML comme texte.
Géographie, géométrie bytes Les types spatiaux sont binaires.
hierarchyid bytes Données hiérarchiques en tant que binaires.
sql_variant Varie Résolu au type de base sous-jacent. sql_variant Les colonnes utilisent un chemin de récupération en streaming, qui peut avoir un léger impact sur les performances par rapport aux colonnes de type fixe.
NULL None Python Aucun.

Constantes de type SQL

Le pilote exporte des constantes correspondant aux identifiants de type SQL ODBC. Vous utilisez généralement ces constantes pour setinputsizes() écraser l’inférence de type par défaut du pilote lorsque la correspondance automatique ne correspond pas à votre schéma.

Types de caractères

Constante Valeur Description
SQL_CHAR 1 Caractère ANSI de longueur fixe.
SQL_VARCHAR 12 Caractère ANSI de longueur variable.
SQL_LONGVARCHAR -1 ANSI long à longueur variable.
SQL_WCHAR -8 Unicode à longueur fixe.
SQL_WVARCHAR -9 Unicode à longueur variable.
SQL_WLONGVARCHAR -10 Unicode long à longueur variable.

Types valeurs numériques

Constante Valeur Description
SQL_BIT -7 Bit/booléen.
SQL_TINYINT -6 Entier non signé 8 bits.
SQL_SMALLINT 5 Entier signé 16 bits.
SQL_INTEGER 4 Entier signé 32 bits.
SQL_BIGINT -5 Entier signé 64 bits.
SQL_REAL 7 Virgule flottante 32 bits.
SQL_FLOAT 6 Virgule flottante 64 bits.
SQL_DOUBLE 8 Virgule flottante 64 bits.
SQL_DECIMAL 3 Décimal de précision fixe.
SQL_NUMERIC 2 Numérique de précision fixe.

Types date et time

Constante Valeur Description
SQL_TYPE_DATE 91 Date uniquement.
SQL_TYPE_TIME 92 Juste le temps.
SQL_TYPE_TIMESTAMP 93 Date et heure.
SQL_SS_TIME2 -154 SQL Server temps(n).
SQL_DATETIMEOFFSET -155 SQL Server datetimeoffset.

Note

SQL_SS_TIME2 et SQL_DATETIMEOFFSET sont des constantes internes non exportées comme attributs au niveau du module. Utilisez directement les valeurs entières (-154, -155) lors de l’appel add_output_converter()de .

Types binaires

Constante Valeur Description
SQL_BINARY -2 Binaire à longueur fixe.
SQL_VARBINARY -3 Binaire de longueur variable.
SQL_LONGVARBINARY -4 Binaire long à longueur variable.

Autres types

Constante Valeur Description
SQL_GUID -11 Identifiant unique.
SQL_XML -152 Données XML.
SQL_SS_UDT -151 Type défini par l’utilisateur (spatial).
SQL_SS_VARIANT -150 sql_variant données.

Note

SQL_SS_UDT et SQL_SS_VARIANT sont des constantes internes non exportées comme attributs au niveau du module. Utilisez directement les valeurs entières (-151, -150) lors de l’appel add_output_converter()de .

Utilisez setinputsizes()

Appelez setinputsizes() avant executemany() pour déclarer explicitement les types de paramètres lorsque l’inférence automatique de type du pilote provoque un comportement inattendu, par exemple lorsqu’une colonne est varchar(100) mais que le pilote envoie nvarchar:

Note

Pour les valeurs décimales, il faut se fier à l’inférence automatique de type du pilote plutôt qu’à SQL_DECIMAL ou SQL_NUMERIC. Ces constantes décimales explicites présentent actuellement un problème connu avec setinputsizes(). Pour plus d’informations, voir Exécuter des requêtes.

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

Séparateur décimal

Le pilote utilise des séparateurs décimaux sensibles à la localisation. Pour personnaliser :

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

Convertisseurs de type personnalisé

Enregistrez des convertisseurs personnalisés pour des types SQL spécifiques :

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)

Pour plus d’informations, voir Convertisseurs de type personnalisé.

Types spéciaux de manipulation

Gestion des UUID

Le conducteur est assigné uuid.UUID à uniqueidentifier automatiquement. Vous pouvez insérer et récupérer des UUID sans conversion manuelle des chaînes :

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

Par défaut, le pilote renvoie UNIQUEIDENTIFIER les colonnes sous forme uuid.UUID d’objets. Pour retourner des cordes majuscules compatibles pyodbc, on met 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()

Pour la configuration au niveau du module, voir le native_uuid paramètre dans Configuration du module.

Heure de date avec fuseau horaire

datetimeoffset Les colonnes renvoient des objets conscients datetime du fuseau horaire. Pour des conseils sur la gestion des valeurs sensibles au décalage versus celles naïves au décalage, voir Gestion du temps de date.

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

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

Données spatiales

Le driver retourne les types spatiaux (geography, geometry) comme bytes. Vous pouvez utiliser des chaînes de paramètres au format WKT :

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

Rowversion/timestamp

Le type de rowversion SQL Server (anciennement timestamp) est un type binaire, pas une date et heure :

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

Types de grande valeur en flux

Lors de l’insertion ou de la récupération varchar(max)de , nvarchar(max), ou varbinary(max) de données, le pilote utilise le flux Data-at-Execution (DAE) pour transmettre les données par blocs plutôt que de charger la totalité de la valeur en mémoire d’un coup.

Le streaming s’active automatiquement lorsque les données d’entrée dépassent les seuils de taille :

Type de données Seuil de diffusion en continu
varchar(max) > 8 000 octets
nvarchar(max) > 4 000 caractères
varbinary(max) > 8 000 octets

Le streaming fonctionne avec execute(), executemany(), et toutes les API de récupération (fetchone(), fetchmany(), fetchall()). Le pilote ne nécessite aucune configuration particulière et gère automatiquement le streaming pour les valeurs importantes.

Types de SQL Server non pris en charge

Les types de SQL Server suivants ne possèdent pas de mappage de type Python natif.

Type SQL Server Status
json Non pris en charge
vector Non pris en charge
table Non pris en charge (paramètres à valeurs de table)

Tip

Bien que le json type SQL Server ne soit pas directement pris en charge, vous pouvez stocker des données JSON dans nvarchar(max) des colonnes et les interroger avec les fonctions JSON de SQL Server (JSON_VALUE, JSON_QUERY, OPENJSON). Pour des motifs et des exemples, voir données JSON.

Les types suivants renvoient les données comme bytes n'ayant pas de mappage de type Python natif :

Type SQL Server Type Python Notes
geography bytes Utilisez .STAsBinary() pour le format WKB.
geometry bytes Utilisez .STAsBinary() pour le format WKB.
hierarchyid bytes Représentation binaire.
sql_variant Varie Résolu au type de base sous-jacent.

Précision décimale versus flotteur

À utiliser decimal.Decimal lorsque la précision exacte compte, comme les calculs financiers, la monnaie ou toute valeur où les erreurs d’arrondi sont inacceptables. À utiliser float lorsque des valeurs approximatives sont acceptables, comme des mesures scientifiques ou des relevés de capteurs.

Le pilote correspond decimal.Decimal à SQL Server decimal/numeric et conserve la précision jusqu’à 38 chiffres. floatmaps à SQL Server float (IEEE 754 64 bits), qui peut introduire des artefacts d’arrondi :

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

Lors de la récupération decimal/numeric des colonnes, le pilote renvoie decimal.Decimal toujours des objets. Lors de la récupération float/real des colonnes, le pilote retourne Python . float

Warning

Ne comparez float pas les valeurs pour l’égalité. Utilisez plutôt une plage de tolérance : abs(a - b) < 0.0001.

Binding de type numpy

Le mssql-python pilote utilise isinstance() des vérifications pour déterminer les types SQL des paramètres. Les types d’entiers Numpy (numpy.int64, numpy.int32, numpy.int8) ne passent isinstance(x, int) pas dans NumPy 2.x, ce qui provoque des échecs de liaison. Ça ne fonctionne directement que numpy.float64 parce que c'est une sous-classe de Pythonfloat.

Convertir les valeurs numpy en types natifs Python avant de les passer comme paramètres :

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

Si vous travaillez beaucoup avec pandas ou des données numpy, envisagez d’utiliser l’intégration Arrow ou les chemins d’intégration pandas , qui gèrent la conversion de type en interne.