Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De mssql-python-driver is Microsoft's eigen Python-driver voor Microsoft SQL. Als je liever een door Microsoft onderhouden driveroptie hebt, biedt het:
- Geen FreeTDS-afhankelijkheid.
- Meerdere gelijktijdige cursors per verbinding.
- Ingebouwde verbindingspooling.
- Ondersteuning voor moderne Python 3.10+-versies.
- Ingebouwde Microsoft Entra-authenticatie.
- Rijobjecten met standaard attribuuttoegang.
Belangrijkste verschillen
| Feature | pymssql | mssql-python |
|---|---|---|
| Parameterstijl |
format (%s, %d) |
qmark (?) en pyformat (%(name)s) |
| Inheemse bibliotheek | FreeTDS | DDBC (gebundeld) |
| Groepsgewijze verbindingen | External | Built-in |
| Cursors per verbinding | 1 | Multiple |
| Minimale Python-versie | 3.6 | 3.10 |
callproc() |
Supported | Niet geïmplementeerd |
as_dict cursor |
Extension | Rijobjecten (standaard) |
| Bulksgewijs kopiëren | conn.bulk_copy() |
cursor.bulkcopy() |
| Autocommit standaardinstelling | Off | Off |
Basisstappen voor migratie
De volgende stappen bespreken de meest voorkomende wijzigingen die nodig zijn om een pymssql-applicatie naar mssql-python te migreren.
1. Werk importinstructies bij
Vervang de pymssql import door mssql_python:
Voor (pymssql):
import pymssql
Na (mssql-python):
import mssql_python
2. Verbindingsaanroepen bijwerken
PymsSQL gebruikt positionele argumenten. De mssql-python-driver gebruikt een verbindingsreeks of trefwoordargumenten:
Voor (pymssql, positionele argumenten):
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
Voor (pymssql, trefwoordargumenten):
conn = pymssql.connect(
host=r"<server>\<instance>",
user="<login>",
password="<password>",
database="<database>"
)
Na (mssql-python, verbindingsreeks):
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Na (mssql-python, Microsoft Entra raadde aan):
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Parametermarkers bijwerken
PymsSQL gebruikt %s en %d formateert plaatsvervangers. De mssql-python-driver gebruikt ? (qmark) of %(name)s (pyformat):
Voor (pymssql):
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))
Na (mssql-python, qmark-stijl):
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. executemany bijwerken
Werk de SQL-placeholders bij van %s/%d naar ? of %(name)s:
Voor (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")]
)
Na (mssql-python, qmark-stijl):
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. Gebruik rijattributen in plaats van as_dict cursors
PymsSQL vereist as_dict=True dat kolommen op naam worden geraadpleegd. De mssql-python-driver levert objecten terug Row die standaard zowel attribuut- als indextoegang ondersteunen:
Voor (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"]))
Na (mssql-python, standaard toegang via attributen):
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]
Migratie van opgeslagen procedures
De mssql-python-driver implementeert callproc()niet . Gebruik EXECUTE in plaats daarvan statements.
Gebruik EXECUTE voor opgeslagen procedures
PymsSQL ondersteunt callproc(), maar de MSSQL-Python-driver niet. Gebruik EXECUTE in plaats daarvan:
Voor (pymssql):
cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
print(row)
Na (mssql-python):
cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
print(row)
Uitvoerparameters
Gebruik T-SQL-variabelen om outputwaarden vast te leggen in plaats van te vertrouwen op callproc() outputparameters:
Voor (pymssql):
cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()
Na (mssql-python, T-SQL variabelen):
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}")
Migratie door bulkkopiëren
pymssql roept bulk_copy() aan op de verbinding. De mssql-python-driver roept bulkcopy() op de cursor aan met extra opties:
Voor (pymssql):
conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()
Na (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()
De mssql-python-methode bulkcopy() ondersteunt batch_size, timeout, column_mappings, keep_identity, check_constraintstable_lockkeep_nullsfire_triggers, en .use_internal_transaction Zie Bulk copy voor details.
Meerdere cursors
PymsSQL staat slechts één actieve cursor per verbinding toe. De mssql-python-driver ondersteunt meerdere gelijktijdige cursors:
Voor (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()
Na (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)}")
Groepsgewijze verbindingen
PymsSQL heeft geen ingebouwde pooling. De mssql-python-driver bevat het automatisch:
Voor (pymssql, externe pool vereist):
from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()
Daarna (mssql-python, pooling gaat automatisch):
conn = mssql_python.connect(connection_string)
conn.close()
Foutafhandeling
De mssql-python-driver gebruikt dezelfde uitzonderingshiërarchie als pymssql, dus de meeste uitzonderingshandlers vereisen alleen een modulenaamwijziging:
Voor (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}")
Na (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}")
Voorbeeld van volledige migratie
Het volgende toont dezelfde functie geschreven met pymssql en vervolgens herschreven met mssql-python.
Daarvoor (pymssql)
Deze versie gebruikt positionele argumenten voor connect, as_dict=True en %d parametermarkeringen:
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
Na (mssql-python)
De belangrijkste structurele veranderingen zijn parametermarkers, verbindingsstijl en rijtoegang:
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
De structurele veranderingen zijn:
-
import pymssql→import mssql_python. - Positionele verbindingsargumenten → verbindingsreeks met trefwoorden.
-
%dparametermarker →?. -
cursor(as_dict=True)→cursor()met attribuuttoegang (row.SalesOrderIDin plaats vanrow["SalesOrderID"]).
Controlelijst
- [ ] Werk de importen bij van
pymssqlnaarmssql_python. - [ ] Zet verbindingsoproepen om van positionele argumenten naar verbindingsstrings.
- [ ] Converteer
%s/%dparametermarkers naar?of%(name)s. - [ ] Gebruik
EXECUTEinstructies voor aanroepen van opgeslagen procedures. - [ ] Gebruik
Rowattribuuttoegang in plaats vanas_dict=Truecursors. - [ ] Migreren
conn.bulk_copy()naarcursor.bulkcopy(). - [ ] Verwijder de externe verbindingspoolconfiguratie.
- [ ] Verwijder FreeTDS uit de implementatievereisten.
- [ ] Update klassennamen voor het afhandelen van uitzonderingen.
- [ ] Test alle zoekopdrachten en opgeslagen procedures.