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 externe ODBC-driverafhankelijkheid.
- Ingebouwde verbindingspooling.
- Ondersteuning voor moderne Python 3.10+-versies.
- Ingebouwde Microsoft Entra-authenticatie.
Belangrijkste verschillen
| Feature | pyodbc | mssql-python |
|---|---|---|
| Parameterstijl |
qmark (?) |
qmark (?) en pyformat (%(name)s) |
| ODBC-bestuurder vereist | Yes | Nee. |
| Groepsgewijze verbindingen | External | Built-in |
| Minimale Python-versie | 3.6 | 3.10 |
callproc() |
Supported | Niet geïmplementeerd |
| Autocommit standaardinstelling | Off | Off |
Basisstappen voor migratie
De volgende stappen behandelen de sleutelwijzigingen om een pyodbc-applicatie te migreren naar mssql-python.
1. Werk importinstructies bij
Vervang de pyodbc import door mssql_python:
Voorheen (pyodbc):
import pyodbc
Na (mssql-python):
import mssql_python
2. Verbindingsreeksen bijwerken
Verwijder het DRIVER= trefwoord en werk de authenticatiemethode bij:
Daarvoor (pyodbc, een ODBC-stuurprogramma vereist):
conn = pyodbc.connect(
"DRIVER={ODBC Driver 18 for SQL Server};"
"SERVER=localhost;"
"DATABASE=AdventureWorks2022;"
"Trusted_Connection=yes;"
)
Daarna (mssql-python, geen driver nodig, gebruikmakend van Microsoft Entra-authenticatie):
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Houd je vragen ongewijzigd
De mssql-python-driver ondersteunt zowel ? (qmark) als %(name)s (pyformat) parameterstijlen. Je bestaande ? queries werken zonder wijzigingen:
Daarvoor (pyodbc):
cursor.execute("SELECT * FROM Production.Product WHERE ProductID = ? AND Color = ?", (1, "Red"))
Na (mssql-python, dezelfde query):
cursor.execute("SELECT * FROM Production.Product WHERE ProductID = ? AND Color = ?", (1, "Red"))
4. Laat executemany ongewijzigd
Bestaande executemany aanroepen met tuples en ? markeringen werken zonder wijzigingen:
Daarvoor (pyodbc):
cursor.execute("CREATE TABLE #MigrateDemo (ID INT, Name NVARCHAR(50))")
data = [(1, "Alice"), (2, "Bob"), (3, "Carol")]
cursor.executemany("INSERT INTO #MigrateDemo (ID, Name) VALUES (?, ?)", data)
Na (mssql-python, dezelfde code):
cursor.execute("DROP TABLE IF EXISTS #MigrateDemo")
cursor.execute("CREATE TABLE #MigrateDemo (ID INT, Name NVARCHAR(50))")
data = [(1, "Alice"), (2, "Bob"), (3, "Carol")]
cursor.executemany("INSERT INTO #MigrateDemo (ID, Name) VALUES (?, ?)", data)
Migratie van opgeslagen procedures
De mssql-python-driver implementeert callproc()niet . De volgende secties laten zien hoe je het in plaats daarvan kunt gebruiken EXECUTE .
Gebruik EXECUTE voor opgeslagen procedures
De pyodbc-driver ondersteunt callproc(), maar de mssql-python-driver niet. Gebruik EXECUTE in plaats daarvan:
Daarvoor (pyodbc):
cursor.callproc("dbo.uspGetEmployeeManagers", (5,))
results = cursor.fetchall()
Na (mssql-python):
cursor.execute(
"EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = %(id)s",
{"id": 5}
)
results = cursor.fetchall()
print(f"Got {len(results)} rows")
Uitvoerparameters
Gebruik T-SQL-variabelen om outputwaarden vast te leggen in plaats van te vertrouwen op callproc() outputparameters:
Daarvoor (pyodbc, met callproc):
params = (category_id, pyodbc.SQL_INTEGER)
cursor.callproc("dbo.GetProductCount", params)
count = params[1].value
Daarna (mssql-python, met T-SQL-variabelen):
cursor.execute(
"""
DECLARE @count INT;
SELECT @count = COUNT(*) FROM Production.Product
WHERE ProductSubcategoryID = %(cat_id)s;
SELECT @count AS ProductCount;
""",
{"cat_id": 1}
)
product_count = cursor.fetchval()
print(f"Product count: {product_count}")
Migraties voor specifieke functies
De volgende secties behandelen specifieke pyodbc-functies en hun mssql-python-equivalenten.
Aansluitstrengen
| Pyodbc-trefwoord | mssql-python sleutelwoord | Aantekeningen |
|---|---|---|
DRIVER={...} |
Niet nodig | De ODBC-driver wordt intern gebundeld. |
SERVER= |
Server= |
Geen gedragswijziging. |
DATABASE= |
Database= |
Geen gedragswijziging. |
Trusted_Connection= |
Trusted_Connection= |
Geen gedragswijziging. |
UID= / PWD= |
UID= / PWD= |
Geen gedragswijziging. |
Authentication= |
Authentication= |
Accepteert dezelfde waarden. |
Autocommit
Het autocommit-gedrag is hetzelfde in beide stuurprogramma's:
Pyodbc:
conn.autocommit = True
pyodbc.connect(connection_string, autocommit=True)
mssql-python:
conn.autocommit = True
Bulk-invoegingen
Om grote batches van INSERT te versnellen, stellen pyodbc-gebruikers fast_executemany = True in. De mssql-python-driver optimaliseert executemany al voor geparametriseerde batches, dus matige inserts hebben geen speciale vlag nodig. Voor grote databelastingen geef je voorkeur aan bulkcopy(), wat rijen over het bulk-copy protocol streamt en veel sneller is dan het uitgeven van individuele INSERT statements. Voor de volledige workflow, zie Gebruik bulk copy.
Pyodbc:
cursor.fast_executemany = True
cursor.executemany(query, data)
Na (mssql-python), batches beperken met executemany:
cursor.execute("DROP TABLE IF EXISTS #BulkTarget")
cursor.execute("CREATE TABLE #BulkTarget (ID INT, Name NVARCHAR(50))")
data = [(i, f"Item {i}") for i in range(100)]
cursor.executemany("INSERT INTO #BulkTarget (ID, Name) VALUES (?, ?)", data)
conn.commit()
Na (mssql-python), bij hoge belasting met bulkcopy (aanbevolen):
cursor.execute("IF OBJECT_ID('##BulkTarget') IS NOT NULL DROP TABLE ##BulkTarget")
cursor.execute("CREATE TABLE ##BulkTarget (ID INT, Name NVARCHAR(50))")
conn.commit() # Commit DDL before bulkcopy
data = [(i, f"Item {i}") for i in range(100)]
result = cursor.bulkcopy("##BulkTarget", data)
print(f"Bulk copied {result['rows_copied']} rows")
cursor.execute("DROP TABLE ##BulkTarget")
conn.commit()
Rijfabriek
De mssql-python-driver retourneert standaard Row-objecten die toegang via attributen ondersteunen, zonder dat hiervoor een aangepaste row factory nodig is:
Pyodbc (Custom Row Factory):
def namedtuple_row_factory(cursor):
from collections import namedtuple
columns = [col[0] for col in cursor.description]
Row = namedtuple("Row", columns)
return Row
mssql-python (standaard attribuuttoegang):
cursor.execute("SELECT Name, ListPrice FROM Production.Product")
row = cursor.fetchone()
print(row.Name) # Attribute access works directly
print(row[0]) # Index access also works
Foutafhandeling
De mssql-python-driver gebruikt dezelfde uitzonderingshiërarchie als pyodbc, dus de meeste uitzonderingshandlers vereisen alleen een modulenaamwijziging.
Uitzonderingshiërarchie
De namen van de uitzonderingsklassen komen rechtstreeks overeen tussen drivers:
Pyodbc:
try:
cursor.execute(query)
except pyodbc.Error as e:
pass
except pyodbc.DatabaseError as e:
pass
except pyodbc.OperationalError as e:
pass
mssql-python:
try:
cursor.execute("SELECT TOP 1 * FROM Production.Product")
print(cursor.fetchone())
except mssql_python.Error as e:
pass
except mssql_python.DatabaseError as e:
pass
except mssql_python.OperationalError as e:
pass
Foutdetails
Beide drivers geven foutdetails bloot via uitzonderingsargumenten:
Pyodbc:
try:
cursor.execute(query)
except pyodbc.Error as e:
sqlstate = e.args[0]
message = e.args[1]
mssql-python:
try:
cursor.execute("SELECT TOP 1 * FROM NonExistentTable_XYZ")
except mssql_python.Error as e:
# Error message contains SQLSTATE and details
print(str(e))
Groepsgewijze verbindingen
De mssql-python-driver bevat standaard verbindingspooling, waardoor externe poolingbibliotheken niet langer nodig zijn.
Verwijder externe pooling
Als je externe pooling met pyodbc hebt gebruikt, heeft de mssql-python-driver dit ingebouwd:
Daarvoor (pyodbc externe pool):
from dbutils.pooled_db import PooledDB
pool = PooledDB(pyodbc, 5, driver="{ODBC Driver 18 for SQL Server}",
server="your_server", database="your_database",
uid="your_username", pwd="your_password")
conn = pool.connection()
Na (mssql-python ingebouwde pooling):
conn = mssql_python.connect(connection_string)
conn.close()
Pool configureren
Overschrijf de standaard poolgrootte en timeout met mssql_python.pooling():
import mssql_python
mssql_python.pooling()
Voorbeeld van volledige migratie
Het volgende toont dezelfde functie geschreven met pyodbc en vervolgens herschreven met mssql-python.
Daarvoor (pyodbc)
Deze versie gebruikt de pyodbc-verbindingsreeks met een DRIVER trefwoord:
import pyodbc
from datetime import date
def get_orders(customer_id: int, start_date: date):
conn = pyodbc.connect(
"DRIVER={ODBC Driver 18 for SQL Server};"
"SERVER=localhost;"
"DATABASE=AdventureWorks2022;"
"Trusted_Connection=yes;"
)
cursor = conn.cursor()
cursor.execute("""
SELECT SalesOrderID, OrderDate, TotalDue
FROM Sales.SalesOrderHeader
WHERE CustomerID = ? AND OrderDate >= ?
ORDER BY OrderDate DESC
""", (customer_id, start_date))
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)
Deze versie verwijdert het DRIVER trefwoord. Alle queries, parameters en toegangspatronen voor rijen blijven identiek:
import mssql_python
from datetime import date
def get_orders(customer_id: int, start_date: date):
conn = mssql_python.connect(
"Server=localhost;"
"Database=AdventureWorks2022;"
"Trusted_Connection=yes;"
)
cursor = conn.cursor()
cursor.execute("""
SELECT SalesOrderID, OrderDate, TotalDue
FROM Sales.SalesOrderHeader
WHERE CustomerID = ? AND OrderDate >= ?
ORDER BY OrderDate DESC
""", (customer_id, start_date))
orders = []
for row in cursor:
orders.append({
"id": row.SalesOrderID,
"date": row.OrderDate,
"total": row.TotalDue
})
cursor.close()
conn.close()
return orders
De enige wijzigingen zijn de import-instructie en de verbindingsreeks (geen DRIVER trefwoord nodig). Elke query, parameter, fetch-patroon en rijtoegang blijft identiek.
Migratie testen
Voordat je de migratie voltooit, voer je dezelfde zoekopdrachten uit op beide drivers en vergelijk je de resultaten om gelijkwaardig gedrag te bevestigen.
Verifieer gelijkwaardig gedrag
Gebruik een vergelijkingsfunctie die dezelfde query uitvoert op beide drivers en de resultaatmatch bevestigt:
import pyodbc
import mssql_python
def compare_results(pyodbc_conn_str: str, mssql_conn_str: str, query: str):
"""Compare results from both drivers."""
# pyodbc query
pyodbc_conn = pyodbc.connect(pyodbc_conn_str)
pyodbc_cursor = pyodbc_conn.cursor()
pyodbc_cursor.execute(query)
pyodbc_results = pyodbc_cursor.fetchall()
pyodbc_conn.close()
# mssql-python query
mssql_conn = mssql_python.connect(mssql_conn_str)
mssql_cursor = mssql_conn.cursor()
mssql_cursor.execute(query)
mssql_results = mssql_cursor.fetchall()
mssql_conn.close()
# Compare
assert len(pyodbc_results) == len(mssql_results)
for p_row, m_row in zip(pyodbc_results, mssql_results):
assert tuple(p_row) == tuple(m_row)
print(f"Results match: {len(pyodbc_results)} rows")
Controlelijst
- [ ] Werk de importen bij van
pyodbcnaarmssql_python. - [ ] Verwijder
DRIVER=van verbindingslijnen. - [ ] Behoud bestaande
?parameterqueries (ze werken as-is). - [ ] Gebruik
EXECUTEinstructies voor aanroepen van opgeslagen procedures. - [ ] Verwijder de externe verbindingspoolconfiguratie.
- [ ] Update klassennamen voor het afhandelen van uitzonderingen.
- [ ] Test alle zoekopdrachten en opgeslagen procedures.
- [ ] Controleer de verwerking van gegevenstypen (vooral decimalen en data).
- [ ] Verwijder de ODBC-driver uit de implementatievereisten.