Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
MSSQL-python-drivrutinen är Microsoft förstaparts Python-drivrutin för Microsoft SQL. Om du föredrar ett drivrutinsalternativ som underhålls av Microsoft erbjuds det:
- Inget FreeTDS-beroende.
- Flera samtidiga markörer per anslutning.
- Inbyggd anslutningspooling.
- Stöd för modern Python 3.10+
- Inbyggd Microsoft Entra-autentisering.
- Radobjekt med attributåtkomst som standard.
Viktiga skillnader
| Feature | pymssql | mssql-python |
|---|---|---|
| Parameterstil |
format (%s, %d) |
qmark (?) och pyformat (%(name)s) |
| Inhemskt bibliotek | FreeTDS | DDBC (paketerat) |
| Anslutningspoolning | Externt | Inbyggd |
| Markörer per anslutning | 1 | Multiple |
| Minsta Python-version | 3.6 | 3.10 |
callproc() |
Stöds | Inte implementerad |
as_dict markör |
Extension | Radobjekt (standard) |
| Masskopiering | conn.bulk_copy() |
cursor.bulkcopy() |
| Standard för automatisk incheckning | Off | Off |
Grundläggande migrationssteg
Följande steg går igenom de vanligaste ändringarna som behövs för att migrera en pymssql-applikation till mssql-python.
1. Uppdatera importen
Ersätt importen pymssql med mssql_python:
Före (pymssql):
import pymssql
Efter (mssql-python):
import mssql_python
2. Uppdatera anslutningsanrop
PymsSQL använder positionsargument. Drivrutinen mssql-python använder en anslutningssträng eller nyckelordsargument:
Före (pymssql, positionsargument):
conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")
Före (pymssql, nyckelordsargument):
conn = pymssql.connect(
host=r"<server>\<instance>",
user="<login>",
password="<password>",
database="<database>"
)
Efter (mssql-python, reťazec pripojenia):
conn = mssql_python.connect(
"Server=<server>;"
"Database=<database>;"
"UID=<username>;"
"PWD=<password>;"
"Encrypt=yes;"
)
Efter (mssql-python, Microsoft Entra rekommenderas):
conn = mssql_python.connect(
"Server=<server>.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes;"
)
3. Uppdatera parametermarkörer
pymssql använder formatplatshållarna %s och %d. mssql-python-drivrutinen använder ? (qmark) eller %(name)s (pyformat):
Före (pymssql):
cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))
Efter (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. Uppdatera executemany
Uppdatera SQL-platshållarna från %s/%d till eller ?%(name)s :
Före (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")]
)
Efter (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. Använd radattribut istället för as_dict markörer
PymsSQL kräver as_dict=True att man får tillgång till kolumner med namn. mssql-python-drivrutinen returnerar Row objekt som som standard stödjer både attribut- och indexåtkomst:
Före (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"]))
Efter (mssql-python, attributåtkomst som standard):
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]
Migrering av lagrad procedur
mssql-python-drivrutinen implementerar inte callproc(). Använd EXECUTE-satser i stället.
Använd EXECUTE för lagrade procedurer
PymsSQL stödjer callproc(), men drivrutinen för mssql-python gör det inte. Använd EXECUTE i stället:
Före (pymssql):
cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
print(row)
Efter (mssql-python):
cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
print(row)
Utdataparametrar
Använd T-SQL-variabler för att fånga utdatavärden istället för att förlita dig på callproc() utdataparametrar:
Före (pymssql):
cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()
Efter (mssql-python, T-SQL-variabler):
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}")
Masskopieringsmigrering
pymssql anropar bulk_copy() på anslutningen. mssql-python-drivrutinen anropar bulkcopy() på markören med ytterligare alternativ:
Före (pymssql):
conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()
Efter (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()
Metoden mssql-python bulkcopy() stöder batch_size, timeout, column_mappings, keep_identity, check_constraints, table_lock, keep_nulls, fire_triggers och use_internal_transaction. Se Bulk-kopia för detaljer.
Flera markörer
PymsSQL tillåter endast en aktiv markör per anslutning. mssql-python-drivrutinen stöder flera samtidiga markörer:
Före (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()
Efter (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)}")
Anslutningspoolning
PymsSQL har ingen inbyggd pooling. mssql-python-drivrutinen inkluderar det automatiskt:
Innan (pymssql, extern pool krävs):
from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()
Efter (mssql-python, poolning är automatisk):
conn = mssql_python.connect(connection_string)
conn.close()
Felhantering
mssql-python-drivrutinen använder samma undantagshierarki som pymssql, så de flesta undantagshanterare kräver endast ett modulnamn:
Före (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}")
Efter (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}")
Exempel på fullständig migrering
Följande visar samma funktion skriven med pymssql och sedan omskriven med mssql-python.
Före (pymssql)
Denna version använder positionskopplingsargument, as_dict=True, och %d parametermarkörer:
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
Efter (mssql-python)
De viktigaste strukturella förändringarna är parametermarkörer, anslutningsstil och radåtkomst:
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 strukturella förändringarna är:
-
import pymssql→import mssql_python. - Positionella anslutningsargument → anslutningssträng med nyckelord.
-
%dParametermarkör →?. -
cursor(as_dict=True)→cursor()med attributåtkomst (row.SalesOrderIDistället förrow["SalesOrderID"]).
Checklista
- [ ] Uppdatera importer från
pymssqltillmssql_python. - [ ] Konvertera anslutningsanrop från positionsargument till anslutningssträngar.
- [ ] Konvertera
%s/%dparametermarkörer till?eller .%(name)s - [ ] Använd
EXECUTEinstruktioner vid anrop av lagrade procedurer. - [ ] Använd
Rowattributåtkomst istället föras_dict=Truemarkörer. - [ ] Migrera
conn.bulk_copy()tillcursor.bulkcopy(). - [ ] Ta bort konfigurationen för extern anslutningspooling.
- [ ] Ta bort FreeTDS från utplaceringskraven.
- [ ] Uppdatera klassnamn för hantering av undantag.
- [ ] Testa alla frågor och lagrade procedurer.