Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Le pilote mssql-python est le pilote Python de première partie de Microsoft pour Microsoft SQL. Si vous préférez une option de pilote maintenue par Microsoft, elle propose :
- Pas de dépendance à FreeTDS.
- Plusieurs curseurs simultanés par connexion.
- Pool de connexions intégré.
- Prise en charge moderne de Python 3.10 et versions ultérieures.
- Authentification Microsoft Entra native.
- Objets de ligne avec accès aux attributs par défaut.
Principales différences
| Fonctionnalité | pymssql | mssql-python |
|---|---|---|
| Style de paramètre |
format (%s, %d) |
qmark (?) et pyformat (%(name)s) |
| Bibliothèque native | FreeTDS | DDBC (groupé) |
| Regroupement de connexions | Externe | Intégré |
| Curseurs par connexion | 1 | Multiple |
| Minimum Python | 3.6 | 3.10 |
callproc() |
Soutenu | Non implémenté |
as_dict curseur |
Extension | Objets de ligne (par défaut) |
| Copie par lots | conn.bulk_copy() |
cursor.bulkcopy() |
| Validation automatique par défaut | Off | Off |
Étapes de base de la migration
Les étapes suivantes présentent les changements les plus courants nécessaires pour migrer une application pymssql vers mssql-python.
1. Mise à jour des importations
Remplacez l’importation pymssql par mssql_python:
Avant (pymssql) :
import pymssql
Après (mssql-python) :
import mssql_python
2. Mettre à jour les appels de connexion
PymsSQL utilise des arguments positionnels. Le pilote mssql-python utilise une chaîne de connexion ou des arguments de mots-clés :
Avant (pymssql, arguments positionnels) :
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
Avant (pymssql, arguments par mots-clés) :
conn = pymssql.connect(
host=r"<server>\<instance>",
user="<login>",
password="<password>",
database="<database>"
)
Après (mssql-python, chaîne de connexion) :
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Après (mssql-python, recommandé par Microsoft Entra) :
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Mettre à jour les marqueurs de paramètres
pymssql utilise des espaces réservés au format %s et %d. Le pilote mssql-python utilise ? (qmark) ou %(name)s (pyformat) :
Avant (pymssql) :
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))
Après (mssql-python, style « 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. Mettre à jour executemany
Mettre à jour les placeholders SQL de %s/%d vers ? ou %(name)s:
Avant (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")]
)
Après (mssql-python, style « 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. Utiliser les attributs Row au lieu des curseurs as_dict
PymsSQL nécessite as_dict=True d’accéder aux colonnes par leur nom. Le pilote mssql-python renvoie des objets Row prenant en charge, par défaut, l’accès par attribut et par index :
Avant (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"]))
Après (mssql-python, accès par défaut aux attributs) :
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]
Migration des procédures stockées
Le pilote mssql-python n’implémente pas callproc(). Utilisez EXECUTE à la place.
Utilisez EXECUTE pour les procédures stockées
PymsSQL prend en charge callproc(), mais le pilote MSSQL-Python ne le fait pas. Utilisez EXECUTE à la place :
Avant (pymssql) :
cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
print(row)
Après (mssql-python) :
cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
print(row)
Paramètres de sortie
Utilisez des variables T-SQL pour capturer les valeurs de sortie au lieu de vous fier aux callproc() paramètres de sortie :
Avant (pymssql) :
cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()
Après (mssql-python, variables 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}")
Migration massive de copies
PymsSQL appelle bulk_copy() sur la connexion. Le pilote mssql-python appelle bulkcopy() sur le curseur avec davantage d’options :
Avant (pymssql) :
conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()
Après (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()
La méthode mssql-python bulkcopy() prend en charge batch_size, timeout, column_mappings, keep_identity, check_constraints, table_lockkeep_nulls, , fire_triggers, et use_internal_transaction. Voir la copie en bloc pour plus de détails.
Curseurs multiples
PymsSQL n’autorise qu’un seul curseur actif par connexion. Le pilote mssql-python prend en charge plusieurs curseurs concurrents :
Avant (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()
Après (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)}")
Regroupement de connexions
PymsSQL n’a pas de pooling intégré. Le pilote mssql-python l’inclut automatiquement :
Avant (pymssql, pool externe requis) :
from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()
Après (mssql-python, le pooling est automatique) :
conn = mssql_python.connect(connection_string)
conn.close()
Gestion des erreurs
Le pilote mssql-python utilise la même hiérarchie d’exception que pymssql, donc la plupart des gestionnaires d’exceptions ne nécessitent qu’un changement de nom de module :
Avant (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}")
Après (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}")
Exemple de migration complet
Ce qui suit montre la même fonction écrite avec pymssql puis réécrite avec mssql-python.
Avant (pymssql)
Cette version utilise des arguments de connexion positionnelle, as_dict=True, et %d des marqueurs de paramètres :
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
Après (mssql-python)
Les principaux changements structurels sont les marqueurs de paramètres, le style de connexion et l’accès aux lignes :
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
Les changements structurels sont les suivants :
-
import pymssql→import mssql_python. - Arguments de connexion positionnels → chaîne de connexion à l’aide de mots-clés.
-
%dmarqueur de paramètre →?. -
cursor(as_dict=True)→cursor()avec un accès aux attributs (row.SalesOrderIDau lieu derow["SalesOrderID"]).
Liste de contrôle
- [ ] Mettez à jour les imports de
pymssqlversmssql_python. - [ ] Convertir les appels de connexion utilisant des arguments positionnels en chaînes de connexion.
- [ ] Convertir
%s/%dles marqueurs de paramètres en?ou .%(name)s - [ ] Utilisez les instructions
EXECUTEpour les appels à des procédures stockées. - [ ] Utilisez l’accès aux attributs
Rowau lieu des curseursas_dict=True. - [ ] Migrer
conn.bulk_copy()verscursor.bulkcopy(). - [ ] Supprimer la configuration du groupement de connexions externe.
- [ ] Retirez FreeTDS des exigences de déploiement.
- [ ] Mettre à jour les noms des classes de gestion des exceptions.
- [ ] Testez toutes les requêtes et procédures stockées.