Mapeamentos de tipos de dados para mssql-python

O driver mssql-python automaticamente mapeia tipos de dados Python para tipos SQL Server ao enviar parâmetros e converte tipos SQL Server para tipos Python ao recuperar resultados.

Mapeamentos de Python para SQL Server

Quando você passa valores de Python como parâmetros para execute() ou executemany(), o driver seleciona automaticamente o tipo apropriado de SQL Server. Para a maioria das aplicações, o mapeamento automático está correto. Use setinputsizes() (descrito mais adiante neste artigo) apenas quando precisar sobrescrever o padrão, por exemplo, para forçar varchar em vez de nvarchar ou para controlar metadados de parâmetros para entradas de string e inteiros.

Tipo do Python Tipo de SQL Server Notes
None NULL SQL NULL value.
bool bit True→1, False→0.
int minúsculo, pequeno,inteligência, bigint Tamanho selecionado com base na faixa de valores.
float float Ponto flutuante de 64 bits.
decimal.Decimal decimal, numérico Mantém precisão de até 38 dígitos.
str Varchar, Nvarchar Usa nvarchar para conteúdo Unicode.
bytes, bytearray varbinary Dados binários.
datetime.date date Apenas para o encontro.
datetime.time Tempo Só o tempo.
datetime.datetime datetime2 Data e hora com precisão em nanossegundos.
uuid.UUID uniqueidentifier GUID de 16 bytes.

Seleção de tipos inteiros

O driver seleciona automaticamente o menor tipo inteiro que pode conter o valor:

Intervalo de valores Tipo de SQL Server
0 a 255 tinyint
-32.768 a 32.767 smallint
-2.147.483.648 a 2.147.483.647 int
Valores maiores bigint

Tipos de grande valor

Para strings e dados binários que excedem os limites padrão, o driver usa automaticamente os tipos MAX:

Condition Tipo de SQL Server
String > 8.000 bytes (varchar) varchar(max)
Sequência > de 4.000 caracteres (nvarchar) nvarchar(max)
Binário > 8.000 bytes varbinary(max)

O driver transmite valores altos para o servidor para minimizar o uso de memória.

Mapeamentos de SQL Server para Python

Quando o driver recupera dados do SQL Server, ele converte valores para tipos Python:

Tipo de SQL Server Tipo do Python Notes
bit bool Verdadeiro/Falso.
minúsculo, pequeno,inteligência, bigint int Python inteiro (precisão arbitrária).
real float Ponto flutuante de 32 bits.
float float Ponto flutuante de 64 bits.
decimal, numérico decimal.Decimal Preserva a precisão.
dinheiro, dinheiro pequeno decimal.Decimal Precisão fixa (quatro casas decimais).
Char, varchar, texto str Decodificado como UTF-8.
nchar, nvarchar, ntext str Decodificado como UTF-16LE.
binário, varbinário, imagem bytes Binário bruto.
date datetime.date Apenas para o encontro.
Tempo datetime.time Tempo com precisão de microssegundos.
Hora do encontro, Hora do Encontro Pequeno datetime.datetime Tipos de data-hora legado.
datetime2 datetime.datetime Data de alta precisão.
datetimeoffset datetime.datetime Horário de data, com perfil de fuso horário.
uniqueidentifier uuid.UUID Objetos UUID em Python.
xml str XML como texto.
Geografia, Geometria bytes Tipos espaciais como binários.
hierarchyid bytes Dados da hierarquia como binários.
sql_variant Variações Resolvido para o tipo base subjacente. sql_variant Colunas usam um caminho de busca em streaming, que pode ter um leve impacto no desempenho em comparação com colunas do tipo fixo.
NULL None Python Nenhum.

Constantes de tipo SQL

O driver exporta constantes que correspondem aos identificadores de tipo SQL ODBC. Normalmente você usa essas constantes para setinputsizes() sobrescrever a inferência padrão do tipo do driver quando o mapeamento automático não corresponde ao seu esquema.

Tipos de caracteres

Constante Valor Descrição
SQL_CHAR 1 Caractere ANSI de comprimento fixo.
SQL_VARCHAR 12 Caractere ANSI de comprimento variável.
SQL_LONGVARCHAR -1 ANSI longo de comprimento variável.
SQL_WCHAR -8 Unicode de comprimento fixo.
SQL_WVARCHAR -9 Unicode de comprimento variável.
SQL_WLONGVARCHAR -10 Unicode longo de comprimento variável.

Tipos numéricos

Constante Valor Descrição
SQL_BIT -7 Bit/booleano.
SQL_TINYINT -6 Inteiro sem sinal de 8 bits.
SQL_SMALLINT 5 Inteiro com sinal de 16 bits.
SQL_INTEGER 4 Inteiro com sinal de 32 bits.
SQL_BIGINT -5 Inteiro assinado de 64 bits.
SQL_REAL 7 Ponto flutuante de 32 bits.
SQL_FLOAT 6 Ponto flutuante de 64 bits.
SQL_DOUBLE 8 Ponto flutuante de 64 bits.
SQL_DECIMAL 3 Decimal de precisão fixa.
SQL_NUMERIC 2 Precisão numérica fixa.

Tipos de data e hora

Constante Valor Descrição
SQL_TYPE_DATE 91 Apenas para o encontro.
SQL_TYPE_TIME 92 Só o tempo.
SQL_TYPE_TIMESTAMP 93 Data e hora.
SQL_SS_TIME2 -154 SQL Server time(n).
SQL_DATETIMEOFFSET -155 SQL Server datetimeoffset.

Note

SQL_SS_TIME2 e SQL_DATETIMEOFFSET são constantes internas não exportadas como atributos em nível de módulo. Use os valores inteiros (-154, -155) diretamente ao chamar add_output_converter().

Tipos binários

Constante Valor Descrição
SQL_BINARY -2 Binário de comprimento fixo.
SQL_VARBINARY -3 Binário de comprimento variável.
SQL_LONGVARBINARY -4 Binário longo de comprimento variável.

Outros tipos

Constante Valor Descrição
SQL_GUID -11 Identificador único.
SQL_XML -152 Dados XML.
SQL_SS_UDT -151 Tipo definido pelo usuário (espacial).
SQL_SS_VARIANT -150 sql_variant dados.

Note

SQL_SS_UDT e SQL_SS_VARIANT são constantes internas não exportadas como atributos em nível de módulo. Use os valores inteiros (-151, -150) diretamente ao chamar add_output_converter().

Use setinputsizes()

Chame setinputsizes() antes executemany() para declarar explicitamente os tipos de parâmetros quando a inferência automática de tipos do driver causa um comportamento inesperado, por exemplo, quando uma coluna é varchar(100) mas o driver envia nvarchar:

Note

Para valores decimais, confie na inferência automática de tipos do driver em vez de SQL_DECIMAL ou SQL_NUMERIC. Essas constantes explícitas do tipo decimal atualmente têm um problema conhecido com setinputsizes(). Para mais informações, veja Executar 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

O driver utiliza separadores decimais conscientes da localidade. 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(",")

Conversores de tipo personalizado

Registre conversores personalizados para tipos específicos de SQL:

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 mais informações, veja Conversores de tipo personalizado.

Tipos especiais de alças

Tratamento com UUID

O driver mapeia uuid.UUID para uniqueidentifier automaticamente. Você pode inserir e recuperar UUIDs sem conversão manual de cordas:

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 padrão, o driver retorna UNIQUEIDENTIFIER as colunas como uuid.UUID objetos. Para retornar cordas maiúsculas compatíveis com pyodbc, defina 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 configuração em nível de módulo, veja a native_uuid configuração em Configuração do módulo.

Data-hora com fuso horário

datetimeoffset colunas retornam objetos conscientes datetime do fuso horário. Para orientações sobre como trabalhar com valores conscientes do offset versus valores ingênuais no deslocamento, veja Gerenciamento do Tempo de Data.

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

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

Dados espaciais

O driver retorna tipos espaciais (geography, geometry) como bytes. Você pode usar strings de parâmetros no 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

O SQL Server rowversion (anteriormentetimestamp) é um tipo binário, não uma data-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 grande valor de fluxo

Ao inserir ou recuperar varchar(max), nvarchar(max), ou varbinary(max) dados, o driver utiliza o streaming Data-at-Execution (DAE) para transmitir dados em blocos, em vez de carregar o valor total na memória de uma vez.

O streaming é ativado automaticamente quando os dados de entrada ultrapassam os limites de tamanho:

Tipo de dados Limiar de transmissão
varchar(max) > 8.000 bytes
nvarchar(max) > 4.000 caracteres
varbinary(max) > 8.000 bytes

O streaming funciona com execute(), executemany(), e todas as APIs de busca (fetchone(), fetchmany(), fetchall()). O driver não requer configuração especial e gerencia o streaming automaticamente para valores altos.

Tipos de SQL Server não suportados

Os seguintes tipos de SQL Server não possuem mapeamentos nativos de tipos Python.

Tipo de SQL Server Status
json Sem suporte
vector Sem suporte
table Não suportado (parâmetros com valores de tabela)

Tip

Embora o json tipo SQL Server não seja suportado diretamente, você pode armazenar dados JSON em nvarchar(max) colunas e consultá-los com as funções JSON do SQL Server (JSON_VALUE, JSON_QUERY, OPENJSON). Para padrões e exemplos, veja dados JSON.

Os seguintes tipos retornam dados como bytes mapeamento nativo de Python:

Tipo de SQL Server Tipo do Python Notes
geography bytes Use .STAsBinary() para o formato WKB.
geometry bytes Use .STAsBinary() para o formato WKB.
hierarchyid bytes Representação binária.
sql_variant Variações Resolvido para o tipo base subjacente.

Precisão decimal versus flutuante

Use decimal.Decimal quando a precisão exata importa, como cálculos financeiros, moeda ou qualquer valor onde erros de arredondamento sejam inaceitáveis. Use float quando valores aproximados são aceitáveis, como medições científicas ou leituras de sensores.

O driver mapeia decimal.Decimal para o SQL Server decimal/numeric e preserva a precisão de até 38 dígitos. floatmapes para SQL Server float (IEEE 754 de 64 bits), que pode introduzir artefatos de arredondamento:

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

Ao recuperar decimal/numeric colunas, o driver sempre retorna decimal.Decimal objetos. Ao recuperar float/real colunas, o driver retorna Python . float

Warning

Não compare float valores para igualdade. Use uma faixa de tolerância em vez disso: abs(a - b) < 0.0001.

Encadernação tipo anestesia

O mssql-python driver usa isinstance() verificações para determinar os tipos SQL dos parâmetros. Os tipos inteiros com numpy (numpy.int64, numpy.int32, numpy.int8) não passam isinstance(x, int) no NumPy 2.x, o que causa falhas de binding. Só numpy.float64 funciona diretamente porque é uma subclasse de Pythonfloat.

Converta valores numpy para tipos nativos de Python antes de passá-los 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"])}
    )

Se você trabalha bastante com dados pandas ou numpy, considere usar os caminhos de integração Arrow ou pandas , que gerenciam a conversão de tipos internamente.