Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El controlador mssql-python asigna automáticamente los tipos de datos Python a tipos SQL Server al enviar parámetros y convierte los tipos de SQL Server a tipos Python al recuperar los resultados.
Mapeos de Python a SQL Server
Cuando pasas valores de Python como parámetros a execute() o executemany(), el controlador selecciona automáticamente el tipo de SQL Server apropiado. Para la mayoría de las aplicaciones, el mapeo automático es correcto. Úsalo setinputsizes() (descrito más adelante en este artículo) solo cuando necesites sobrescribir el valor por defecto, por ejemplo para forzar varchar en lugar de nvarchar o para controlar metadatos de parámetros para cadenas y entradas enteras.
| Tipo de Python | Tipo de SQL Server | Notas |
|---|---|---|
None |
NULL |
SQL NULL value. |
bool |
bit |
True→1, False→0. |
int |
minúsculo, pequeño,int,bigint | Tamaño seleccionado según el rango de valores. |
float |
float | Punto flotante de 64 bits. |
decimal.Decimal |
decimal, numérico | Preserva la precisión hasta 38 dígitos. |
str |
Varchar, Nvarchar | Usa nvarchar para contenido Unicode. |
bytes, bytearray |
varbinary | Datos binarios. |
datetime.date |
date | Solo fecha. |
datetime.time |
time | Solo tiempo. |
datetime.datetime |
datetime2 | Fecha y hora con precisión de nanosegundos. |
uuid.UUID |
uniqueidentifier | GUID de 16 bytes. |
Selección de tipos enteros
El controlador selecciona automáticamente el tipo entero más pequeño que puede contener el valor:
| Intervalo de valores | Tipo de SQL Server |
|---|---|
| De 0 a 255 | tinyint |
| -32.768 a 32.767 | smallint |
| -2.147.483.648 a 2.147.483.647 | int |
| Valores mayores | bigint |
Tipos de valor grande
Para cadenas y datos binarios que superan los límites estándar, el controlador utiliza automáticamente los tipos MAX:
| Condition | Tipo de SQL Server |
|---|---|
| Cadena > de 8.000 bytes (varchar) | varchar(max) |
| Cadena > de 4.000 caracteres (nvarchar) | nvarchar(max) |
| Binario > de 8.000 bytes | varbinary(max) |
El controlador transmite valores grandes al servidor para minimizar el uso de memoria.
Mapeos de SQL Server a Python
Cuando el controlador recupera datos de SQL Server, convierte valores a tipos Python:
| Tipo de SQL Server | Tipo de Python | Notas |
|---|---|---|
| bit | bool |
Verdadero/Falso. |
| minúsculo, pequeño,int,bigint | int |
Entero Python (precisión arbitraria). |
| real | float |
Punto flotante de 32 bits. |
| float | float |
Punto flotante de 64 bits. |
| decimal, numérico | decimal.Decimal |
Preserva la precisión. |
| Dinero, dinero pequeño | decimal.Decimal |
Precisión fija (cuatro decimales). |
| Char, Varchar, texto | str |
Descifrado como UTF-8. |
| nchar, nvarchar, ntext | str |
Descodificado como UTF-16LE. |
| binario, varbinario, imagen | bytes |
Binario puro. |
| date | datetime.date |
Solo fecha. |
| time | datetime.time |
Tiempo con precisión de microsegundos. |
| Hora de cita, Hora de la Cita Pequeña | datetime.datetime |
Tipos de fecha y hora heredados. |
| datetime2 | datetime.datetime |
Hora de cita de alta precisión. |
| datetimeoffset | datetime.datetime |
Fecha y hora con conciencia de la zona horaria. |
| uniqueidentifier | uuid.UUID |
Objetos UUID en Python. |
| xml | str |
XML como texto. |
| Geografía, geometría | bytes |
Tipos espaciales como binarios. |
| hierarchyid | bytes |
Datos de jerarquía como binarios. |
| sql_variant | Varía | Resuelto al tipo base subyacente.
sql_variant Las columnas utilizan una ruta de obtención en streaming, que puede tener un pequeño impacto en el rendimiento en comparación con las columnas de tipo fijo. |
NULL |
None |
Python Ninguna. |
Constantes de tipo SQL
El controlador exporta constantes que corresponden a identificadores de tipo SQL ODBC. Normalmente usas estas constantes para setinputsizes() anular la inferencia de tipo por defecto del controlador cuando el mapeo automático no coincide con tu esquema.
Tipos de caracteres
| Constante | Valor | Descripción |
|---|---|---|
SQL_CHAR |
1 | Carácter ANSI de longitud fija. |
SQL_VARCHAR |
12 | Carácter ANSI de longitud variable. |
SQL_LONGVARCHAR |
-1 | ANSI largo de longitud variable. |
SQL_WCHAR |
-8 | Unicode de longitud fija. |
SQL_WVARCHAR |
-9 | Unicode de longitud variable. |
SQL_WLONGVARCHAR |
-10 | Unicode largo de longitud variable. |
Tipos numéricos
| Constante | Valor | Descripción |
|---|---|---|
SQL_BIT |
-7 | Bit/booleano. |
SQL_TINYINT |
-6 | Entero sin signo de 8 bits. |
SQL_SMALLINT |
5 | Entero de 16 bits con signo. |
SQL_INTEGER |
4 | Entero de 32 bits con signo. |
SQL_BIGINT |
-5 | Entero con signo de 64 bits. |
SQL_REAL |
7 | Punto flotante de 32 bits. |
SQL_FLOAT |
6 | Punto flotante de 64 bits. |
SQL_DOUBLE |
8 | Punto flotante de 64 bits. |
SQL_DECIMAL |
3 | Decimal de precisión fija. |
SQL_NUMERIC |
2 | Precisión fija numérica. |
Tipos de fecha y hora
| Constante | Valor | Descripción |
|---|---|---|
SQL_TYPE_DATE |
91 | Solo fecha. |
SQL_TYPE_TIME |
92 | Solo tiempo. |
SQL_TYPE_TIMESTAMP |
93 | Fecha y hora. |
SQL_SS_TIME2 |
-154 | SQL Server tiempo(n). |
SQL_DATETIMEOFFSET |
-155 | SQL Server datetimeoffset. |
Note
SQL_SS_TIME2 y SQL_DATETIMEOFFSET son constantes internas que no se exportan como atributos a nivel de módulo. Utiliza los valores enteros (-154, -155) directamente al llamar add_output_converter()a .
Tipos binarios
| Constante | Valor | Descripción |
|---|---|---|
SQL_BINARY |
-2 | Binario de longitud fija. |
SQL_VARBINARY |
-3 | Binario de longitud variable. |
SQL_LONGVARBINARY |
-4 | Binario largo de longitud variable. |
Otros tipos
| Constante | Valor | Descripción |
|---|---|---|
SQL_GUID |
-11 | Identificador único. |
SQL_XML |
-152 | Datos XML. |
SQL_SS_UDT |
-151 | Tipo definido por el usuario (espacial). |
SQL_SS_VARIANT |
-150 | sql_variant datos. |
Note
SQL_SS_UDT y SQL_SS_VARIANT son constantes internas que no se exportan como atributos a nivel de módulo. Utiliza los valores enteros (-151, -150) directamente al llamar add_output_converter()a .
Usa setinputsizes()
Llama setinputsizes() antes executemany() para declarar explícitamente los tipos de parámetros cuando la inferencia automática de tipos del controlador causa un comportamiento inesperado, por ejemplo cuando una columna es varchar(100) pero el controlador envía nvarchar:
Note
Para valores decimales, basémonos en la inferencia automática de tipos del controlador en lugar de SQL_DECIMAL o SQL_NUMERIC. Esas constantes explícitas de tipo decimal actualmente tienen un problema conocido con setinputsizes(). Para más información, véase Ejecutar consultas.
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),
]
)
Separador decimal
El controlador utiliza separadores decimales con conocimiento local. Para personalizar:
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(",")
Convertidores de tipo personalizado
Registra convertidores personalizados para tipos SQL específicos:
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)
Para más información, véase Convertidores de tipo personalizado.
Tipos especiales de manejo
Manejo de UUID
El conductor se asigna uuid.UUID automáticamente uniqueidentifier . Puedes insertar y recuperar UUIDs sin necesidad de conversión manual de cadenas:
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})
Por defecto, el controlador devuelve UNIQUEIDENTIFIER columnas como uuid.UUID objetos. Para devolver cuerdas mayúsculas compatibles con pyodbc, se configura 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()
Para la configuración a nivel de módulo, véase la native_uuid configuración en Configuración de módulos.
Fecha y hora con huso horario
datetimeoffset las columnas devolven objetos conscientes datetime de la zona horaria. Para orientación sobre cómo trabajar con valores conscientes del offset frente a los ingenuos del offset, véase Manejo de la hora de la fecha.
cursor.execute("SELECT SYSDATETIMEOFFSET()")
row = cursor.fetchone()
dt = row[0]
print(f"DateTime: {dt}")
print(f"Timezone: {dt.tzinfo}")
Datos espaciales
El driver devuelve los tipos espaciales (geography, geometry) como bytes. Puedes usar cadenas de parámetros en 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
El de rowversion SQL Server (anteriormentetimestamp) es un tipo binario, no una fecha y hora:
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
Tipos de gran valor de flujo
Al insertar o recuperar varchar(max), nvarchar(max), o varbinary(max) datos, el controlador utiliza la transmisión de datos en ejecución (DAE) para transmitir datos en bloques en lugar de cargar el valor completo en la memoria de una vez.
El streaming se activa automáticamente cuando los datos de entrada superan los umbrales de tamaño:
| Tipo de dato | Umbral de transmisión |
|---|---|
| varchar(max) | > 8.000 bytes |
| nvarchar(max) | > 4.000 caracteres |
| varbinary(max) | > 8.000 bytes |
El streaming funciona con execute(), executemany(), y todas las APIs de obtención (fetchone(), fetchmany(), fetchall()). El controlador no requiere ninguna configuración especial y gestiona el streaming automáticamente para valores grandes.
Tipos de SQL Server no soportados
Los siguientes tipos de SQL Server no tienen mapeos nativos de tipos Python.
| Tipo de SQL Server | Situación |
|---|---|
| json | No soportado |
| vector | No soportado |
| table | No soportado (parámetros con valores de tabla) |
Tip
Aunque el json tipo SQL Server no es compatible directamente, puedes almacenar datos JSON en nvarchar(max) columnas y consultarlos con funciones JSON de SQL Server (JSON_VALUE, JSON_QUERY, OPENJSON). Para patrones y ejemplos, véase datos JSON.
Los siguientes tipos devuelven datos como bytes pero no tienen mapeos nativos de tipos Python:
| Tipo de SQL Server | Tipo de Python | Notas |
|---|---|---|
| geography | bytes |
Úsalo .STAsBinary() para el formato WKB. |
| geometry | bytes |
Úsalo .STAsBinary() para el formato WKB. |
| hierarchyid | bytes |
Representación binaria. |
| sql_variant | Varía | Resuelto al tipo base subyacente. |
Precisión decimal frente a flotador
Úsalo decimal.Decimal cuando la precisión exacta importe, como cálculos financieros, moneda o cualquier valor donde los errores de redondeo sean inaceptables. Úsalo float cuando los valores aproximados son aceptables, como mediciones científicas o lecturas de sensores.
El controlador se asigna decimal.Decimal a SQL Server decimal/numeric y mantiene la precisión hasta 38 dígitos.
floatmapeos a SQL Server float (IEEE 754 de 64 bits), que puede introducir artefactos de redondeo:
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'>
Al recuperar decimal/numeric columnas, el controlador siempre devuelve decimal.Decimal objetos. Al recuperar float/real columnas, el controlador devuelve Python . float
Advertencia
No compares float valores para igualdad. Utiliza un rango de tolerancia en su lugar: abs(a - b) < 0.0001.
Encuadernación tipo entumecido
El mssql-python controlador utiliza isinstance() comprobaciones para determinar los tipos SQL de los parámetros. Los tipos enteros insensibles (numpy.int64, numpy.int32, numpy.int8) no pasan isinstance(x, int) en NumPy 2.x, lo que provoca fallos de enlace. Solo numpy.float64 funciona directamente porque es una subclase de Pythonfloat.
Convierte los valores numpy a tipos nativos de Python antes de pasarlos como parámetros:
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 trabajas mucho con pandas o datos numpy, considera usar la integración de Arrow o las rutas de integración de pandas , que gestionan la conversión de tipos internamente.