Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Il driver mssql-python mappa automaticamente i tipi di dati Python ai tipi SQL Server quando invia i parametri e converte i tipi SQL Server in tipi Python quando recupera i risultati.
Mappaggi da Python a SQL Server
Quando passi valori Python come parametri a execute() o executemany(), il driver seleziona automaticamente il tipo SQL Server appropriato. Per la maggior parte delle applicazioni, la mappatura automatica è corretta. Usa setinputsizes() (descritto più avanti in questo articolo) solo quando devi sovrascrivere il predefinito, ad esempio per forzare varchar invece di nvarchar o per controllare i metadati dei parametri per stringhe e ingressi interi.
| Tipo Python | Tipo SQL Server | Notes |
|---|---|---|
None |
NULL |
SQL NULL value. |
bool |
bit |
True→1, False→0. |
int |
Tinyint, smallint, int,bigint | Dimensione selezionata in base all'intervallo di valori. |
float |
float | Virgola mobile a 64 bit. |
decimal.Decimal |
decimale, numerica | Preserva la precisione fino a 38 cifre. |
str |
Varchar, Nvarchar | Usa nvarchar per i contenuti Unicode. |
bytes, bytearray |
varbinary | Dati binari. |
datetime.date |
date | Solo appuntamento. |
datetime.time |
time | Solo il tempo. |
datetime.datetime |
datetime2 | Data e ora con precisione di nanosecondi. |
uuid.UUID |
uniqueidentifier | GUID da 16 byte. |
Selezione dei tipi interi
Il driver seleziona automaticamente il tipo intero più piccolo che può contenere il valore:
| Intervallo di valori | Tipo SQL Server |
|---|---|
| da 0 a 255 | tinyint |
| Da -32.768 a 32.767 | smallint |
| Da -2.147.483.648 a 2.147.483.647 | int |
| Valori maggiori | bigint |
Tipi di grande valore
Per stringhe e dati binari che superano i limiti standard, il driver utilizza automaticamente i tipi MAX:
| Condition | Tipo SQL Server |
|---|---|
| Stringa > 8.000 byte (varchar) | varchar(max) |
| Stringa > 4.000 caratteri (nvarchar) | nvarchar(max) |
| Binario > 8.000 byte | varbinary(max) |
Il driver trasmette valori elevati al server per minimizzare l'uso di memoria.
Mappe da SQL Server a Python
Quando il driver recupera dati da SQL Server, converte i valori in tipi Python:
| Tipo SQL Server | Tipo Python | Notes |
|---|---|---|
| bit | bool |
Vero/Falso. |
| Tinyint, smallint, int,bigint | int |
Intero Python (precisione arbitraria). |
| real | float |
Virgola mobile a 32 bit. |
| float | float |
Virgola mobile a 64 bit. |
| decimale, numerica | decimal.Decimal |
Preserva la precisione. |
| Soldi, piccoli soldi | decimal.Decimal |
Precisione fissa (quattro decimali). |
| Char, Varchar, testo | str |
Decodificato come UTF-8. |
| nchar, nvarchar, ntext | str |
Decodificato come UTF-16LE. |
| binario, varbinario, immagine | bytes |
Binario grezzo. |
| date | datetime.date |
Solo appuntamento. |
| time | datetime.time |
Tempo con precisione di microsecondi. |
| Ora della data, Piccola Ora | datetime.datetime |
Tipi data-time legacy. |
| datetime2 | datetime.datetime |
Ora di appuntamento ad alta precisione. |
| datetimeoffset | datetime.datetime |
Data e ora consapevole del fuso orario. |
| uniqueidentifier | uuid.UUID |
Oggetti UUID in Python. |
| xml | str |
XML come testo. |
| Geografia, Geometria | bytes |
Tipi spaziali come binari. |
| hierarchyid | bytes |
Dati della gerarchia come binari. |
| sql_variant | Variabile | Risolto al tipo base sottostante.
sql_variant Le colonne utilizzano un percorso di recupero in streaming, che potrebbe avere un leggero impatto sulle prestazioni rispetto alle colonne di tipo fisso. |
NULL |
None |
Python nessuno. |
Costanti di tipo SQL
Il driver esporta costanti che corrispondono agli identificatori di tipo SQL ODBC. Di solito usi queste costanti per setinputsizes() sovrascrivere l'inferenza di tipo predefinita del driver quando la mappatura automatica non corrisponde al tuo schema.
Tipi di caratteri
| Costante | Valore | Descrizione |
|---|---|---|
SQL_CHAR |
1 | Carattere ANSI a lunghezza fissa. |
SQL_VARCHAR |
12 | Carattere ANSI a lunghezza variabile. |
SQL_LONGVARCHAR |
-1 | ANSI lunga a lunghezza variabile. |
SQL_WCHAR |
-8 | Unicode a lunghezza fissa. |
SQL_WVARCHAR |
-9 | Unicode a lunghezza variabile. |
SQL_WLONGVARCHAR |
-10 | Unicode lungo a lunghezza variabile. |
Tipi numerici
| Costante | Valore | Descrizione |
|---|---|---|
SQL_BIT |
-7 | Bit/boolean. |
SQL_TINYINT |
-6 | Intero senza segno a 8 bit. |
SQL_SMALLINT |
5 | Intero con segno a 16 bit. |
SQL_INTEGER |
4 | Intero con segno a 32 bit. |
SQL_BIGINT |
-5 | Intero con segno a 64 bit. |
SQL_REAL |
7 | Virgola mobile a 32 bit. |
SQL_FLOAT |
6 | Virgola mobile a 64 bit. |
SQL_DOUBLE |
8 | Virgola mobile a 64 bit. |
SQL_DECIMAL |
3 | Decimale di precisione fissa. |
SQL_NUMERIC |
2 | Numerico di precisione fissa. |
Tipi di data e ora
| Costante | Valore | Descrizione |
|---|---|---|
SQL_TYPE_DATE |
91 | Solo appuntamento. |
SQL_TYPE_TIME |
92 | Solo il tempo. |
SQL_TYPE_TIMESTAMP |
93 | Data e ora. |
SQL_SS_TIME2 |
-154 | SQL Server time(n). |
SQL_DATETIMEOFFSET |
-155 | SQL Server datetimeoffset. |
Note
SQL_SS_TIME2 e SQL_DATETIMEOFFSET sono costanti interne non esportate come attributi a livello di modulo. Usa direttamente i valori interi (-154, -155) quando si chiama add_output_converter().
Tipi binari
| Costante | Valore | Descrizione |
|---|---|---|
SQL_BINARY |
-2 | Binario a lunghezza fissa. |
SQL_VARBINARY |
-3 | Binario a lunghezza variabile. |
SQL_LONGVARBINARY |
-4 | Binario lungo a lunghezza variabile. |
Altri tipi
| Costante | Valore | Descrizione |
|---|---|---|
SQL_GUID |
-11 | Identificatore unico. |
SQL_XML |
-152 | Dati XML. |
SQL_SS_UDT |
-151 | Tipo definito dall'utente (spaziale). |
SQL_SS_VARIANT |
-150 | sql_variant dati. |
Note
SQL_SS_UDT e SQL_SS_VARIANT sono costanti interne non esportate come attributi a livello di modulo. Usa direttamente i valori interi (-151, -150) quando si chiama add_output_converter().
Usa setinputsizes()
Chiama setinputsizes() prima executemany() per dichiarare esplicitamente i tipi di parametri quando l'inferenza automatica del tipo del driver causa comportamenti inaspettati, ad esempio quando una colonna è varchar(100) ma il driver invia nvarchar:
Note
Per i valori decimali, si basano sull'inferenza automatica di tipo del driver piuttosto che SQL_DECIMAL su o SQL_NUMERIC. Quelle costanti di tipo decimale esplicite attualmente presentano un problema noto con setinputsizes(). Per maggiori informazioni, vedi Esegui query.
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),
]
)
Separatore decimale
Il driver utilizza separatori decimali consapevoli della zona. Per personalizzare:
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(",")
Convertitori di tipo personalizzato
Registra convertitori personalizzati per tipi SQL specifici:
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)
Per maggiori informazioni, vedi Convertitori di tipo personalizzati.
Tipi speciali di maniglia
Gestione UUID
Il driver si mappa uuid.UUID su uniqueidentifier automaticamente. Puoi inserire e recuperare UUID senza conversione manuale delle stringhe:
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})
Di default, il driver restituisce UNIQUEIDENTIFIER le colonne come uuid.UUID oggetti. Per restituire stringhe maiuscole compatibili con pyodbc, impostare 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()
Per la configurazione a livello di modulo, vedi l'impostazione native_uuid in Configurazione del modulo.
Data e ora con fuso orario
datetimeoffset le colonne restituiscono oggetti consapevoli datetime del fuso orario. Per indicazioni su come lavorare con valori offset-aware rispetto a offset-naiveive, vedi Gestione Datetime.
cursor.execute("SELECT SYSDATETIMEOFFSET()")
row = cursor.fetchone()
dt = row[0]
print(f"DateTime: {dt}")
print(f"Timezone: {dt.tzinfo}")
Dati spaziali
Il driver restituisce i tipi spaziali (geography, geometry) come bytes. Puoi usare stringhe di parametri in formato 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
SQL Server rowversion (precedentemente timestamp) è un tipo binario, non una data-ora:
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
Tipi di grande valore a flusso
Quando inserisce o recupera varchar(max), nvarchar(max), o varbinary(max) dati, il driver utilizza lo streaming Data-at-Execution (DAE) per trasmettere i dati a blocchi invece di caricare l'intero valore in memoria contemporaneamente.
Lo streaming si attiva automaticamente quando i dati di input superano le soglie di dimensione:
| Tipo di dati | Soglia di streaming |
|---|---|
| varchar(max) | > 8.000 byte |
| nvarchar(max) | > 4.000 caratteri |
| varbinary(max) | > 8.000 byte |
Lo streaming funziona con execute(), executemany(), e tutte le API di fetch (fetchone(), fetchmany(), fetchall()). Il driver non richiede una configurazione speciale e gestisce automaticamente lo streaming per valori elevati.
Tipi di SQL Server non supportati
I seguenti tipi di SQL Server non hanno mappe nativi di tipo Python.
| Tipo SQL Server | Condizione |
|---|---|
| json | Non supportato |
| vector | Non supportato |
| table | Non supportato (parametri a valori di tabella) |
Tip
Anche se il json tipo SQL Server non è supportato direttamente, puoi memorizzare dati JSON in nvarchar(max) colonne e interrogarli con le funzioni JSON di SQL Server (JSON_VALUE, JSON_QUERY, OPENJSON). Per pattern ed esempi, vedi dati JSON.
I seguenti tipi restituiscono dati come bytes ma non hanno mappe nativi di tipo Python:
| Tipo SQL Server | Tipo Python | Notes |
|---|---|---|
| geography | bytes |
Usa .STAsBinary() per il formato WKB. |
| geometry | bytes |
Usa .STAsBinary() per il formato WKB. |
| hierarchyid | bytes |
Rappresentazione binaria. |
| sql_variant | Variabile | Risolto al tipo base sottostante. |
Precisione decimale contro float
Usalo decimal.Decimal quando la precisione esatta è importante, come calcoli finanziari, valuta o qualsiasi valore in cui gli errori di arrotondamento sono inaccettabili. Utilizzare float quando valori approssimati sono accettabili, come misurazioni scientifiche o letture dei sensori.
Il driver si mappa decimal.Decimal su SQL Server decimal/numeric e mantiene la precisione fino a 38 cifre.
floatmappa a SQL Server float (IEEE 754 a 64 bit), che può introdurre artefatti di arrotondamento:
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'>
Quando si recuperano decimal/numeric colonne, il driver restituisce decimal.Decimal sempre oggetti. Quando si recuperano float/real le colonne, il driver restituisce Python float.
Warning
Non confrontare float i valori per l'uguaglianza. Usa invece un intervallo di tolleranza: abs(a - b) < 0.0001.
Rilegato tipo insensibile
Il mssql-python driver utilizza isinstance() controlli per determinare i tipi SQL per i parametri. I tipi di interi Numpy (numpy.int64, numpy.int32, numpy.int8) non passano isinstance(x, int) in NumPy 2.x, il che causa fallimenti di binding. Funziona direttamente solo numpy.float64 perché è una sottoclasse di Pythonfloat.
Converti i valori numpy in tipi nativi di Python prima di passarli come parametri:
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"])}
)
Se lavori molto con pandas o dati numpy, considera di usare l'integrazione Arrow o i percorsi di integrazione pandas , che gestiscono internamente la conversione dei tipi.