Migrálás a pymssql-ről az mssql-pythonra

Az mssql-python illesztőprogram a Microsoft első saját fejlesztésű Python-illesztőprogramja a Microsoft SQL-hez. Ha inkább egy Microsoft által karbantartott illesztőprogram-lehetőséget részesít előnyben, az a következőket kínálja:

  • Nincs FreeTDS függőség.
  • Több egyidejű kurzor egy kapcsolatonként.
  • Beépített csatlakozási csoportosítás.
  • Modern Python 3.10+ támogatás.
  • Natív Microsoft Entra hitelesítés.
  • Sorobjektumok attribútum-hozzáféréssel alapértelmezett.

Főbb különbségek

Feature pymsSQL mssql-python
Paraméterstílus format (%s, %d) qmark (?) és pyformat (%(name)s)
Őslakos könyvtár FreeTDS DDBC (mellékelt)
Kapcsolatmegosztás Külső Beépített
Kurzorok kapcsolatonként 1 Multiple
Minimális Python-verzió 3.6 3.10
callproc() Támogatott Nincs implementálva
as_dict kurzor Extension Sorobjektumok (alapértelmezett)
Tömeges másolás conn.bulk_copy() cursor.bulkcopy()
Autocommit alapértelmezett Off Off

Alapvető migrációs lépések

A következő lépések végigvezetik a leggyakoribb változtatásokat, amelyek szükségesek egy pymssql alkalmazás mssql-pythonra történő migrálásához.

1. Frissítsék az importokat

Az pymssql importot helyettesítsük :mssql_python

Mielőtt (pymssql):

import pymssql

(mssql-python) után:

import mssql_python

2. Frissítse a kapcsolódási hívásokat

A PymsSQL pozicionális argumentumokat használ. Az mssql-python illesztőprogram kapcsolati karakterláncot vagy kulcsszóargumentumokat használ:

Mielőtt (pymssql, pozíciós argumentumok):

conn = pymssql.connect("<server>", "<user>", "<password>", "<database>")

Mielőtt (pymssql, kulcsszava-argumentumok):

conn = pymssql.connect(
    host=r"<server>\<instance>",
    user="<login>",
    password="<password>",
    database="<database>"
)

A(z) (mssql-python, kapcsolati karakterlánc) után:

conn = mssql_python.connect(
    "Server=<server>;"
    "Database=<database>;"
    "UID=<username>;"
    "PWD=<password>;"
    "Encrypt=yes;"
)

Miután (mssql-python, Microsoft Entra ajánlott):

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes;"
)

3. Paraméterjelzők frissítése

A pymssql %s és %d formátumhelyőrzőket használ. Az mssql-python illesztőprogram a ? (qmark) vagy a %(name)s (pyformat) formátumot használja:

Mielőtt (pymssql):

cursor.execute("SELECT * FROM Person.Person WHERE BusinessEntityID = %d AND FirstName = %s", (user_id, name))

Utána (mssql-python, qmark stílus):

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. Frissítsd a végrehajtót

Frissítsd az SQL helyváltókat a -%s/%dtől vagy :?%(name)s

Mielőtt (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")]
)

Miután (mssql-python, qmark stílus):

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. Használj Sor attribútumokat as_dict kurzor helyett

A pymssql használatához a(z) as_dict=True szükséges az oszlopok név szerinti eléréséhez. Az mssql-python illezőprogram olyan objektumokat ad vissza Row , amelyek alapértelmezés szerint mind az attribútum, mind az index-hozzáférést támogatják:

Mielőtt (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"]))

Miután (mssql-python, attribútum-hozzáférés alapértelmezett):

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]

Tárolt eljárás migráció

Az mssql-python illesztőprogram nem valósítja meg a callproc() elemet. Használj EXECUTE helyette állításokat.

EXECUTE használata tárolt eljárásokhoz

A pymsSQL támogatja callproc(), de az mssql-python illesztőprogram nem. Használja inkább a következőt EXECUTE :

Mielőtt (pymssql):

cursor.callproc("uspGetEmployeeManagers", (5,))
for row in cursor:
    print(row)

(mssql-python) után:

cursor.execute("EXECUTE dbo.uspGetEmployeeManagers @BusinessEntityID = ?", (5,))
for row in cursor:
    print(row)

Kimeneti paraméterek

Használj T-SQL változókat a kimeneti értékek rögzítésére a callproc() kimeneti paraméterek helyett:

Mielőtt (pymssql):

cursor.callproc("GetProductCount", (category_id,))
count = cursor.fetchval()

After (mssql-python, T-SQL változók):

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}")

Tömeges másolat migráció

A pymssql a kapcsolaton hívja meg a(z) bulk_copy() elemet. Az mssql-python illesztőprogram a kurzoron hívja meg a(z) bulkcopy() elemet további opciókkal:

Mielőtt (pymssql):

conn.bulk_copy("##BulkDemo", [(1, 2)] * 1000)
conn.commit()

(mssql-python) után:

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()

Az mssql-python bulkcopy() módszer támogatja batch_size, timeout, column_mappings, , keep_identity, check_constraintstable_lockkeep_nullsfire_triggers, és .use_internal_transaction A részletekért lásd a Tömeges másolás részt.

Több kurzor

A pymsSQL minden kapcsolaton csak egy aktív kurzort engedélyez. Az mssql-python illesztőprogram több párhuzamos kurzort támogat:

Mielőtt (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()

(mssql-python) után:

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)}")

Kapcsolatmegosztás

A pymsSQL nincs beépített pooling. Az mssql-python illesztőprogram automatikusan tartalmazza ezt:

Mielőtt (pymssql, külső pool szükséges):

from dbutils.pooled_db import PooledDB
pool = PooledDB(pymssql, host="server", user="user", password="pwd", database="db")
conn = pool.connection()

Az mssql-python után a pooling automatikus:

conn = mssql_python.connect(connection_string)
conn.close()

Hibakezelés

Az mssql-python illesztőprogram ugyanazt a kivételhierarchiát használja, mint a pymssql, így a legtöbb kivételkezelő csak modulnévváltoztatást igényel:

Mielőtt (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}")

(mssql-python) után:

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}")

Teljes migrálási példa

Az alábbiakban ugyanazt a függvényt mutatja pymssql-lel írva, majd mssql-pythonnal újraírva.

Előtte (pymssql)

Ez a verzió pozicionális kapcsolati argumentumokat és as_dict=True%d paraméterjelölőket használ:

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

Miután (mssql-python)

A kulcsfontosságú szerkezeti változások a paraméterjelölők, a kapcsolati stílus és a sorhozzáférés:

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

A szerkezeti változások a következők:

  1. import pymssqlimport mssql_python.
  2. Pozíciós kapcsolódási argumentumok → kulcsszavakkal ellátott kapcsolati karakterlánc
  3. %d paraméterjelölő → ?.
  4. cursor(as_dict=True)cursor() attribútumhozzáféréssel (row.SalesOrderID helyett row["SalesOrderID"]).

Checklist

  • [ ] Frissítse az importokat a pymssql -től -re mssql_python.
  • [ ] Kapcsolódási hívásokat pozíciós argumentumokról kapcsolati láncokká alakítsuk.
  • [ ] Alakítsa át a %s/%d paraméterjelölőket ? vagy %(name)s formátumra.
  • [ ] Használj EXECUTE utasításokat tárolt eljáráshívásokhoz.
  • [ ] Használj Row attribútum-hozzáférést kurzor as_dict=True helyett.
  • [ ] Migrálás erről: conn.bulk_copy() erre: cursor.bulkcopy().
  • [ ] Távolítsd el a külső kapcsolatcsoportosítás konfigurációját.
  • [ ] Távolítsa el a FreeTDS-t a telepítési követelményekből.
  • [ ] Frissítse a kivételkezelő osztályneveket.
  • [ ] Teszteljük az összes lekérdezést és tárolt eljárást.