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 è il driver Python di prima parte di Microsoft per Microsoft SQL. Se preferisci un'opzione driver mantenuta da Microsoft, offre:
- Nessuna dipendenza da FreeTDS.
- Più cursori concorrenti per connessione.
- Pooling di connessione integrato.
- Supporto moderno per Python 3.10+.
- Autenticazione nativa Microsoft Entra.
- Oggetti riga con accesso agli attributi per impostazione predefinita.
Differenze principali
| Feature | pymssql | mssql-python |
|---|---|---|
| Stile dei parametri |
format (%s, %d) |
qmark (?) e pyformat (%(name)s) |
| Biblioteca nativa | FreeTDS | DDBC (confezionato) |
| Pool di connessioni | Esterno | Predefinito |
| Cursori per connessione | 1 | Multiple |
| Versione minima di Python | 3.6 | 3.10 |
callproc() |
Supportato | Non implementato |
as_dict cursore |
Extension | Oggetti di riga (predefinito) |
| Copia in blocco | conn.bulk_copy() |
cursor.bulkcopy() |
| Autocommit predefinito | Off | Off |
Passaggi base della migrazione
I passaggi seguenti illustrano i cambiamenti più comuni necessari per migrare un'applicazione pymssql in mssql-python.
1. Aggiornare le importazioni
Sostituisci l'importazione pymssql con mssql_python:
Prima (pymssql):
import pymssql
Dopo (mssql-python):
import mssql_python
2. Aggiorna le chiamate di connessione
PymsSQL utilizza argomenti posizionali. Il driver mssql-python utilizza una stringa di connessione o argomenti per parole chiave:
Prima (pymssql, argomenti posizionali):
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
Prima (pymssql, argomentazioni per parole chiave):
conn = pymssql.connect(
host=r"<server>\<instance>",
user="<login>",
password="<password>",
database="<database>"
)
Dopo (mssql-python, stringa di connessione):
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Dopo (mssql-python, consigliato da Microsoft Entra):
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Aggiornare i marcatori dei parametri
pymssql utilizza i segnaposto di formato %s e %d. Il driver mssql-python utilizza ? (qmark) o %(name)s (pyformat):
Prima di (pymssql):
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))
Dopo (mssql-python, stile qmark):
user_id, name = 1, "Ken"
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = ? AND FirstName = ?", (user_id, name))
print(cursor.fetchone())
cursor.execute(
"SELECT * FROM Person.Person WHERE BusinessEntityID = %(id)s AND FirstName = %(name)s",
{"id": user_id, "name": name}
)
print(cursor.fetchone())
4. Aggiorna esecuzioni
Aggiorna i segnaposto SQL da %s/%d a ? o :%(name)s
Prima (pymssql):
cursor.execute("CREATE TABLE #Persons (ID INT, Name NVARCHAR(50), Department NVARCHAR(50))")
cursor.executemany(
"INSERT INTO #Persons VALUES (%d, %s, %s)",
[(1, "John", "Sales"), (2, "Jane", "Marketing")]
)
Dopo (mssql-python, stile qmark):
cursor.execute("IF OBJECT_ID('#Persons') IS NOT NULL DROP TABLE #Persons")
cursor.execute("CREATE TABLE #Persons (ID INT, Name NVARCHAR(50), Department NVARCHAR(50))")
cursor.executemany(
"INSERT INTO #Persons VALUES (?, ?, ?)",
[(1, "John", "Sales"), (2, "Jane", "Marketing")]
)
cursor.execute("SELECT * FROM #Persons")
for row in cursor:
print(row)
5. Usa gli attributi Row invece dei cursori as_dict
PymsSQL richiede as_dict=True di accedere alle colonne per nome. Il driver mssql-python restituisce Row oggetti che supportano sia l'accesso agli attributi che all'indice di default:
Prima (pymssql):
cursor = conn.cursor(as_dict=True)
cursor.execute("SELECT BusinessEntityID, FirstName FROM Person.Person WHERE FirstName = %s", ("John",))
for row in cursor:
print("ID=%d, Name=%s" % (row["BusinessEntityID"], row["FirstName"]))
Dopo (mssql-python, accesso agli attributi per impostazione predefinita):
cursor = conn.cursor()
cursor.execute("SELECT BusinessEntityID, FirstName FROM Person.Person WHERE FirstName = ?", ("John",))
for row in cursor:
print(f"ID={row.BusinessEntityID}, Name={row.FirstName}")
# Index access also works: row[0], row[1]
Migrazione delle procedure memorizzate
Il driver mssql-python non implementa callproc(). Usa invece le istruzioni EXECUTE.
Usa EXECUTE per le stored procedure
PymsSQL supporta callproc(), ma il driver MSSQL-Python no. Usare EXECUTE invece:
Prima (pymssql):
cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
print(row)
Dopo (mssql-python):
cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
print(row)
Parametri di output
Usa variabili T-SQL per catturare i valori di output invece di affidarti ai callproc() parametri di output:
Prima di (pymssql):
cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()
Dopo (mssql-python, variabili T-SQL):
cursor.execute("""
DECLARE @count INT;
SELECT @count = COUNT(*) FROM Production.Product
WHERE ProductSubcategoryID = ?;
SELECT @count AS ProductCount;
""", (1,))
product_count = cursor.fetchval()
print(f"Product count: {product_count}")
Migrazione tramite copia in blocco
PymsSQL chiama bulk_copy() sulla connessione. Il driver mssql-python chiama bulkcopy() sul cursore con ulteriori opzioni:
Prima di (pymssql):
conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()
Dopo (mssql-python):
cursor = conn.cursor()
cursor.execute("CREATE TABLE ##BulkDemo (Col1 INT, Col2 INT)")
conn.commit()
result = cursor.bulkcopy("##BulkDemo", [(1, 2)] * 1000)
print(f"Copied {result['rows_copied']} rows")
conn.commit()
cursor.execute("DROP TABLE ##BulkDemo")
conn.commit()
Il metodo mssql-python bulkcopy() supporta batch_size, timeout, column_mappings, keep_identity, check_constraintstable_lock, keep_nulls, , fire_triggers, , e use_internal_transaction. Vedi Copia in blocco per i dettagli.
Cursori multipli
PymsSQL permette un solo cursore attivo per connessione. Il driver mssql-python supporta più cursori concorrenti:
Prima (pymssql):
c1 = conn.cursor()
c1.execute("SELECT TOP 5 * FROM Person.Person")
c2 = conn.cursor()
c2.execute("SELECT TOP 5 * FROM Sales.SalesOrderHeader")
c1.fetchall()
Dopo (mssql-python):
c1 = conn.cursor()
c1.execute("SELECT TOP 5 BusinessEntityID, FirstName FROM Person.Person")
persons = c1.fetchall()
c2 = conn.cursor()
c2.execute("SELECT TOP 5 SalesOrderID FROM Sales.SalesOrderHeader")
orders = c2.fetchall()
print(f"Persons: {len(persons)}, Orders: {len(orders)}")
Pool di connessioni
pymssql non ha un supporto integrato per il pooling. Il driver mssql-python lo include automaticamente:
Prima (pymssql, pool esterno richiesto):
from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()
Dopo mssql-python, il pooling è automatico:
conn = mssql_python.connect(connection_string)
conn.close()
Gestione degli errori
Il driver mssql-python utilizza la stessa gerarchia delle eccezioni di pymssql, quindi la maggior parte dei gestori di eccezioni richiede solo un cambio di nome del modulo:
Prima (pymssql):
try:
cursor.execute(query)
except pymssql.OperationalError as e:
print(f"Operation failed: {e}")
except pymssql.InterfaceError as e:
print(f"Interface error: {e}")
Dopo (mssql-python):
try:
cursor = conn.cursor()
cursor.execute("SELECT TOP 1 * FROM Production.Product")
row = cursor.fetchone()
print(row)
except mssql_python.OperationalError as e:
print(f"Operation failed: {e}")
except mssql_python.InterfaceError as e:
print(f"Interface error: {e}")
Esempio di migrazione completa
Quanto segue mostra la stessa funzione scritta con pymssql e poi riscritta con mssql-python.
Precedente (pymssql)
Questa versione utilizza argomenti di connessione posizionali, as_dict=True, e marcatori di parametro %d:
import pymssql
def get_orders(customer_id: int):
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
cursor = conn.cursor(as_dict=True)
cursor.execute("""
SELECT TOP 10 SalesOrderID, OrderDate, TotalDue
FROM Sales.SalesOrderHeader
WHERE CustomerID = %d
ORDER BY OrderDate DESC
""", (customer_id,))
orders = []
for row in cursor:
orders.append({
"id": row["SalesOrderID"],
"date": row["OrderDate"],
"total": row["TotalDue"]
})
cursor.close()
conn.close()
return orders
Dopo (mssql-python)
I principali cambiamenti strutturali sono i marcatori dei parametri, lo stile di connessione e l'accesso alle righe:
import mssql_python
def get_orders(customer_id: int):
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
)
cursor = conn.cursor()
cursor.execute("""
SELECT TOP 10 SalesOrderID, OrderDate, TotalDue
FROM Sales.SalesOrderHeader
WHERE CustomerID = ?
ORDER BY OrderDate DESC
""", (customer_id,))
orders = []
for row in cursor:
orders.append({
"id": row.SalesOrderID,
"date": row.OrderDate,
"total": row.TotalDue
})
cursor.close()
conn.close()
return orders
I cambiamenti strutturali sono:
-
import pymssql→import mssql_python. - Argomenti posizionali di connessione → stringa di connessione con parole chiave.
-
%dmarcatore parametro →?. -
cursor(as_dict=True)→cursor()con accesso agli attributi (row.SalesOrderIDinvece dirow["SalesOrderID"]).
Checklist
- [ ] Aggiorna le importazioni da
pymssqlamssql_python. - [ ] Converti le chiamate di connessione da argomenti posizionali a stringhe di connessione.
- [ ] Converti i marcatori di parametro
%s/%din?o%(name)s. - [ ] Usa le istruzioni
EXECUTEper chiamare le stored procedure. - [ ] Usa l'accesso agli attributi
Rowinvece dei cursorias_dict=True. - [ ] Migra
conn.bulk_copy()sucursor.bulkcopy(). - [ ] Rimuovere la configurazione del pool di connessione esterna.
- [ ] Rimuovere FreeTDS dai requisiti di dispiegamento.
- [ ] Aggiornare i nomi delle classi di gestione delle eccezioni.
- [ ] Testa tutte le query e le procedure memorizzate.