Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der mssql-python-Treiber ist Microsofts erster hauseigener Python-Treiber für Microsoft SQL. Wenn Sie eine von Microsoft getreue Treiberoption bevorzugen, bietet sie Folgendes an:
- Keine FreeTDS-Abhängigkeit.
- Mehrere gleichzeitige Cursor pro Verbindung.
- Eingebautes Verbindungspooling.
- Unterstützung für Modern Python 3.10+
- Native Microsoft Entra-Authentifizierung.
- Zeilenobjekte mit standardmäßig Attributzugriff.
Wichtige Unterschiede
| Funktion | pymssql | mssql-python |
|---|---|---|
| Parameterstil |
format (%s, %d) |
qmark (?) und pyformat (%(name)s) |
| Heimische Bibliothek | FreeTDS | DDBC (gebündelt) |
| Verbindungspooling | Extern | Integriert |
| Cursor pro Verbindung | 1 | Multiple |
| Mindestversion von Python | 3.6 | 3.10 |
callproc() |
Unterstützt | Nicht implementiert |
as_dict Cursor |
Extension | Zeilenobjekte (Standard) |
| Massenkopieren | conn.bulk_copy() |
cursor.bulkcopy() |
| Autocommit-Standardwert | Off | Off |
Grundlegende Migrationsschritte
Die folgenden Schritte zeigen die häufigsten Änderungen, die erforderlich sind, um eine Pymssql-Anwendung auf mssql-python zu migrieren.
1. Importe aktualisieren
Ersetzen Sie den Import pymssql durch mssql_python:
Vor (pymssql):
import pymssql
Nach (mssql-python):
import mssql_python
2. Verbindende Anrufe aktualisieren
PymsSQL verwendet positionsbezogene Argumente. Der mssql-python-Treiber verwendet eine Verbindungszeichenfolge oder Schlüsselwortargumente:
Vor (pymssql, Positionsargumente):
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
Vor (pymssql, Schlüsselwortargumente):
conn = pymssql.connect(
host=r"<server>\<instance>",
user="<login>",
password="<password>",
database="<database>"
)
Danach (mssql-python, Verbindungszeichenfolge):
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Danach (mssql-python, Microsoft Entra empfohlen):
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Aktualisierung der Parametermarker
pymssql verwendet Platzhalter im Format %s und %d. Der mssql-python-Treiber verwendet ? (qmark) oder %(name)s (pyformat):
Vor (pymssql):
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))
Danach (mssql-python, qmark-Stil):
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 aktualisieren
Aktualisieren Sie die SQL-Platzhalter von %s/%d zu ? oder %(name)s:
Vor (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")]
)
Danach (mssql-python, qmark-Stil):
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. Verwenden Sie Row-Attribute anstelle von as_dict-Cursorn
PymsSQL erfordert as_dict=True den Zugriff auf Spalten nach Namen. Der mssql-python-Treiber liefert standardmäßig Objekte zurück, Row die sowohl Attribut- als auch Indexzugriff unterstützen:
Vor (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"]))
Danach (mssql-python, standardmäßig Attributzugriff):
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 von gespeicherten Prozeduren
Der mssql-python-Treiber implementiert callproc()nicht . Verwenden Sie stattdessen EXECUTE-Anweisungen.
Verwenden Sie EXECUTE für gespeicherte Prozeduren
PymsSQL unterstützt callproc(), aber der MSSQL-Python-Treiber nicht. Verwenden Sie EXECUTE stattdessen:
Vor (pymssql):
cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
print(row)
Nach (mssql-python):
cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
print(row)
Ausgabeparameter
Verwenden Sie T-SQL-Variablen, um Ausgabewerte zu erfassen, anstatt sich auf callproc() Ausgabeparameter zu verlassen:
Vor (pymssql):
cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()
Nach (mssql-python, T-SQL-Variablen):
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}")
Massen-Kopiermigration
pymssql ruft bulk_copy() für die Verbindung auf. Der mssql-python-Treiber ruft auf dem Cursor bulkcopy() mit zusätzlichen Optionen auf:
Vor (pymssql):
conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()
Nach (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()
Die mssql-python-Methode bulkcopy() unterstützt batch_size, timeout, column_mappings, keep_identity, check_constraints, table_lock, keep_nulls, fire_triggers und use_internal_transaction. Weitere Informationen finden Sie unter Massenkopieren.
Mehrere Cursor
PymsSQL erlaubt nur einen aktiven Cursor pro Verbindung. Der mssql-python-Treiber unterstützt mehrere gleichzeitige Cursor:
Vor (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()
Nach (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)}")
Verbindungspooling
PymsSQL hat kein integriertes Pooling. Der mssql-python-Treiber enthält sie automatisch:
Vorher (pymssql, externer Pool erforderlich):
from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()
Nach (mssql-python, Pooling erfolgt automatisch):
conn = mssql_python.connect(connection_string)
conn.close()
Fehlerbehandlung
Der mssql-python-Treiber verwendet dieselbe Ausnahmehierarchie wie pymssql, daher erfordern die meisten Ausnahmehandler nur eine Modulnamensänderung:
Vor (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}")
Nach (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}")
Vollständiges Migrationsbeispiel
Das Folgende zeigt dieselbe Funktion, die mit pymssql geschrieben und dann mit mssql-python neu geschrieben wurde.
Vorher (pymssql)
Diese Version verwendet positionsbezogene Verbindungsargumente, as_dict=True, und %d Parametermarker:
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
Danach (mssql-python)
Die wichtigsten strukturellen Änderungen sind Parametermarker, Verbindungsstil und Zeilenzugriff:
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
Die strukturellen Änderungen sind:
-
import pymssql→import mssql_python. - Positionale Verbindungsargumente → Verbindungszeichenfolge mit Schlüsselwörtern.
-
%dParametermarker →?. -
cursor(as_dict=True)→cursor()mit Attributzugriff (row.SalesOrderIDstattrow["SalesOrderID"]).
Checklist
- [ ] Importe aktualisieren von
pymssqlzumssql_python. - [ ] Konvertiere Verbindungsaufrufe von Positionsargumenten in Verbindungsstrings.
- [ ] Konvertiere
%s/%dParametermarker in?oder .%(name)s - [ ] Verwenden Sie
EXECUTEAnweisungen für gespeicherte Prozeduraufrufe. - [ ] Verwenden Sie
RowAttributzugriff stattas_dict=TrueCursor. - [ ] Migrieren
conn.bulk_copy()nachcursor.bulkcopy(). - [ ] Externe Verbindungspooling-Konfiguration entfernen.
- [ ] Entfernen von FreeTDS aus den Einsatzanforderungen.
- [ ] Aktualisieren der Klassennamen für Ausnahmebehandlung.
- [ ] Teste alle Abfragen und gespeicherten Verfahren.