Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sterownik mssql-python to pierwszy oficjalny sterownik Python firmy Microsoft do Microsoft SQL. Jeśli wolisz opcję sterownika utrzymywanego przez Microsoft, oferuje:
- Brak zależności od FreeTDS.
- Wiele współbieżnych kursorów na połączenie.
- Wbudowane łączenie połączeń.
- Nowoczesne wsparcie dla Python 3.10+.
- Natywne uwierzytelnianie Microsoft Entra.
- Domyślnie obiekty wierszowe z dostępem do atrybutów.
Podstawowe różnice
| Funkcja | pymssql | mssql-python |
|---|---|---|
| Styl parametrów |
format (%s, %d) |
qmark (?) oraz pyformat (%(name)s) |
| Rodzima biblioteka | FreeTDS | DDBC (w zestawie) |
| Buforowanie połączeń | Zewnętrzne | Built-in |
| Kursory na każde połączenie | 1 | Wielokrotny |
| Minimalna wersja języka Python | 3.6 | 3.10 |
callproc() |
Wsparte | Nie zaimplementowano |
as_dict kursor |
Extension | Obiekty wierszowe (domyślnie) |
| Kopiowanie zbiorcze | conn.bulk_copy() |
cursor.bulkcopy() |
| Domyślne ustawienie automatycznego zatwierdzania | Off | Off |
Podstawowe kroki migracji
Poniższe kroki przedstawiają najczęstsze zmiany potrzebne do migracji aplikacji pymssql do mssql-python.
1. Aktualizuj importy
Zastąp import pymssql elementem mssql_python:
Przed (pymssql):
import pymssql
Po (mssql-python):
import mssql_python
2. Aktualizacja wywołań połączeń
PymsSQL używa argumentów pozycyjnych. Sterownik mssql-python wykorzystuje parametry połączenia lub argumenty słów kluczowych:
Przed (pymssql, argumenty pozycyjne):
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
Przed (pymssql, argumenty słów kluczowych):
conn = pymssql.connect(
host=r"<server>\<instance>",
user="<login>",
password="<password>",
database="<database>"
)
Po (mssql-python, parametry połączenia):
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Po (mssql-python, zalecane: Microsoft Entra):
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Aktualizuj markery parametrów
pymssql używa symboli zastępczych formatu %s i %d. Sterownik mssql-python używa ? (qmark) lub %(name)s (pyformat):
Przed (pymssql):
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))
After (mssql-python, styl 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. Zaktualizuj executemany
Zaktualizuj symbole zastępcze SQL z %s/%d na ? lub %(name)s:
Przed (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")]
)
After (mssql-python, styl 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. Używaj atrybutów wiersza zamiast as_dict kursorów
pymssql wymaga as_dict=True, aby uzyskać dostęp do kolumn według nazw. Sterownik mssql-python domyślnie zwraca Row obiekty obsługujące zarówno dostęp do atrybutów, jak i indeksów:
Przed (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"]))
Po (mssql-python, domyślny dostęp do atrybutów):
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]
Migracja procedur przechowywanych
Sterownik mssql-python nie implementuje callproc(). Zamiast tego używaj instrukcji EXECUTE.
Użyj EXECUTE dla procedur przechowywanych
PymsSQL obsługuje callproc(), ale sterownik MSSQL-Python nie. Użyj EXECUTE zamiast tego:
Przed (pymssql):
cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
print(row)
Po (mssql-python):
cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
print(row)
Parametry wyjściowe
Używaj zmiennych T-SQL do rejestrowania wartości wyjściowych zamiast polegać na parametrach callproc() wyjściowych:
Przed (pymssql):
cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()
Po (mssql-python, zmienne 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}")
Migracja kopii masowych
pymssql wywołuje bulk_copy() dla połączenia. Sterownik mssql-python wywołuje bulkcopy() na kursorze z dodatkowymi opcjami:
Przed (pymssql):
conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()
Po (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()
Metoda mssql-python bulkcopy() obsługuje batch_size, timeout, column_mappings, keep_identitycheck_constraints, table_lock, , keep_nulls, , fire_triggersoraz .use_internal_transaction Zobacz kopię zbiorczą dla szczegółów.
Wiele kursorów
pymssql pozwala tylko na jeden aktywny kursor na połączenie. Sterownik mssql-python obsługuje wiele równoczesnych kursorów:
Przed (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()
Po (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)}")
Buforowanie połączeń
PymsSQL nie ma wbudowanego poolingu. Sterownik mssql-python zawiera go automatycznie:
Przed (pymssql, wymagana zewnętrzna pula):
from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()
Po (mssql-python, pulowanie jest automatyczne):
conn = mssql_python.connect(connection_string)
conn.close()
Obsługa błędów
Sterownik mssql-python używa tej samej hierarchii wyjątków co pymssql, więc większość obsługiwaczy wyjątków wymaga jedynie zmiany nazwy modułu:
Przed (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}")
Po (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}")
Kompletny przykład migracji
Poniżej przedstawiono tę samą funkcję napisaną w pymssql, a następnie przepisaną w mssql-python.
Przed (pymssql)
Ta wersja wykorzystuje argumenty pozycyjne funkcji connect oraz znaczniki parametrów as_dict=True i %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
Po (mssql-python)
Kluczowe zmiany strukturalne to znaczniki parametrów, styl połączenia oraz dostęp do wierszy:
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
Zmiany strukturalne to:
-
import pymssql→import mssql_python. - Pozycyjne argumenty połączenia → parametry połączenia ze słowami kluczowymi.
-
%dMarker parametrów →?. -
cursor(as_dict=True)→cursor()z dostępem do atrybutów (row.SalesOrderIDzamiastrow["SalesOrderID"]).
Lista kontrolna
- [ ] Aktualizuj importy z
pymssqldo .mssql_python - [ ] Przekonwertuj wywołania połączeń z argumentów pozycyjnych na ciągi połączeń.
- [ ] Przekonwertuj
%s/%dznaczniki parametrów na?lub%(name)s. - [ ] Używaj
EXECUTEinstrukcji do wywołań procedur przechowywanych. - [ ] Używaj
Rowdostępu do atrybutów zamiastas_dict=Truekursorów. - [ ] Migruj
conn.bulk_copy()docursor.bulkcopy(). - [ ] Usuń konfigurację pulowania połączeń zewnętrznych.
- [ ] Usuń FreeTDS z wymagań wdrożenia.
- [ ] Aktualizuj nazwy klas obsługujących wyjątki.
- [ ] Testuj wszystkie zapytania i procedury przechowywane.