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 proporciona métodos de cursor para la ejecución de consultas SQL, consultas parametrizadas, operaciones por lotes y sentencias preparadas.
Ejecución básica de consultas
Utiliza el método execute() de un cursor para ejecutar sentencias SQL:
import mssql_python
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("SELECT Name, ListPrice FROM Production.Product WHERE Color = 'Black'")
rows = cursor.fetchall()
for row in rows:
print(row.Name, row.ListPrice)
cursor.close()
conn.close()
Consultas parametrizadas
Use siempre consultas con parámetros para evitar la inyección de código SQL. El paramstyle predeterminado del controlador es pyformat (marcadores de posición con nombre), pero también admite qmark (marcadores de posición posicionales). Úsalo qmark para secuencias de escape ODBC {CALL} .
Estilo pyformat (por defecto)
Utiliza marcadores de posición con nombre con la sintaxis %(name)s y pasa un diccionario:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE Color = %(color)s AND ListPrice > %(price)s",
{"color": "Black", "price": 10.00}
)
Estilo Qmark
Usa marcadores posicionales con ? y pasa una tupla o lista:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = ? AND ListPrice > ?",
(1, 10.00)
)
El controlador detecta automáticamente el estilo de parámetros en función de tu consulta SQL y tipos de parámetros.
operaciones INSERT, UPDATE, DELETE
Para sentencias de modificación de datos, utiliza consultas parametrizadas y confirma la transacción:
cursor.execute("CREATE TABLE #ExecDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.execute(
"INSERT INTO #ExecDemo (Name, CategoryID, Price) VALUES (%(name)s, %(category)s, %(price)s)",
{"name": "New Product", "category": 1, "price": 19.99}
)
conn.commit()
print(f"Rows affected: {cursor.rowcount}")
Ejecución por lotes con executemany()
Úsalo executemany() para insertar varias filas de forma eficiente. El controlador utiliza la vinculación de parámetros columna a columna para un alto rendimiento:
products = [
{"name": "Product A", "category": 1, "price": 10.00},
{"name": "Product B", "category": 1, "price": 15.00},
{"name": "Product C", "category": 2, "price": 20.00},
]
cursor.execute("CREATE TABLE #BatchDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.executemany(
"INSERT INTO #BatchDemo (Name, CategoryID, Price) VALUES (%(name)s, %(category)s, %(price)s)",
products
)
conn.commit()
print(f"Rows inserted: {cursor.rowcount}")
Con el estilo qmark:
products = [
("Product A", 1, 10.00),
("Product B", 1, 15.00),
("Product C", 2, 20.00),
]
cursor.execute("CREATE TABLE #QmarkDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.executemany(
"INSERT INTO #QmarkDemo (Name, CategoryID, Price) VALUES (?, ?, ?)",
products
)
conn.commit()
Ejecución por lotes de varias sentencias
Úsalo batch_execute() en la conexión para ejecutar múltiples sentencias diferentes en una sola llamada:
results, cursor = conn.batch_execute(
[
"CREATE TABLE #BatchExec (Name NVARCHAR(50), CategoryID INT)",
"INSERT INTO #BatchExec (Name, CategoryID) VALUES (%(name)s, %(cat)s)",
"SELECT COUNT(*) FROM #BatchExec"
],
[
None, # No params for CREATE
{"name": "New Item", "cat": 1}, # Params for INSERT
None # No params for SELECT
]
)
print(f"CREATE result: {results[0]}")
print(f"INSERT affected: {results[1]} rows")
print(f"Row count: {results[2][0][0]}")
Instrucciones preparadas
El controlador prepara consultas por defecto (use_prepare=True). Cuando ejecutas la misma cadena SQL varias veces en el mismo cursor, el controlador reutiliza automáticamente la instrucción preparada en llamadas posteriores:
# First execution prepares the statement
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(subcategory_id)s",
{"subcategory_id": 1},
)
rows1 = cursor.fetchall()
# Same SQL string on same cursor → driver reuses the prepared plan
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(subcategory_id)s",
{"subcategory_id": 2},
)
rows2 = cursor.fetchall()
Para saltarse la preparación y usar la ejecución directa en su lugar:
cursor.execute(
"SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = 1",
use_prepare=False # Uses SQLExecDirectW instead of SQLPrepareW
)
Ejecución a nivel de conexión
Para consultas simples y puntuales, usa execute() directamente en la conexión:
# Creates cursor, executes, and returns cursor
cursor = conn.execute("SELECT TOP 10 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
cursor.close()
Procedimientos almacenados
Llama a procedimientos almacenados usando EXECUTE o la sintaxis de escape ODBC {CALL} . Para información sobre parámetros de salida, múltiples conjuntos de resultados y patrones de transacciones, consulte Procedimientos almacenados.
cursor.execute(
"EXECUTE dbo.uspGetManagerEmployees @BusinessEntityID = %(business_entity_id)s",
{"business_entity_id": 16}
)
rows = cursor.fetchall()
Establecer tamaños de entrada
Usar setinputsizes() para declarar explícitamente los tipos de parámetros, lo que puede mejorar el rendimiento para operaciones por lotes:
cursor.setinputsizes([
(mssql_python.SQL_WVARCHAR, 50, 0), # NVARCHAR(50)
(mssql_python.SQL_INTEGER, 0, 0), # INT
])
cursor.executemany(
"SELECT ProductID, Name FROM Production.Product WHERE Name LIKE ? AND ProductSubcategoryID = ?",
[("Road%", 2), ("Mountain%", 1)]
)
Note
No todas las constantes de tipo SQL funcionan con setinputsizes().
SQL_WVARCHAR y SQL_INTEGER son fiables. Para valores decimales, utiliza la inferencia automática de tipos del controlador en lugar de SQL_DECIMAL, que tiene un problema conocido (GitHub #503).
Gestión de errores
Envuelve las operaciones de la base de datos en bloques try-except:
try:
cursor.execute("CREATE TABLE #ErrDemo (Name NVARCHAR(50) NOT NULL)")
cursor.execute("INSERT INTO #ErrDemo (Name) VALUES (%(name)s)", {"name": None})
conn.commit()
except mssql_python.IntegrityError as e:
print(f"Constraint violation: {e}")
conn.rollback()
except mssql_python.ProgrammingError as e:
print(f"SQL error: {e}")
conn.rollback()
procedimientos recomendados
- Utiliza siempre consultas parametrizadas para evitar la inyección SQL.
-
Usa copia masiva para inserciones masivas en lugar de varias llamadas a
execute(). - Confirma transacciones explícitamente cuando desactivas el autocommit.
- Cierra cursores y conexiones cuando termines para liberar recursos.
- Utiliza gestores de contexto para la limpieza automática de recursos:
with mssql_python.connect(connection_string) as conn:
with conn.cursor() as cursor:
cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
# Connection and cursor automatically closed