Pymssql'den mssql-python'a migrate

mssql-python sürücüsü, Microsoft'un Microsoft SQL için birinci taraf Python sürücüsüdür. Microsoft tarafından desteklenen bir sürücü seçeneği tercih ederseniz, şunları sunar:

  • FreeTDS bağımlılığı yok.
  • Her bağlantı için birden fazla eşzamanlı imleç.
  • Yerleşik bağlantı havuzlaması.
  • Modern Python 3.10+ desteği.
  • Yerel Microsoft Entra kimlik doğrulaması.
  • Varsayılan olarak öznitelik erişimine sahip satır nesneler.

Önemli farklar

Özellik pymssql mssql-python
Parametre stili format (%s, %d) qmark (?) ve pyformat (%(name)s)
Yerel kütüphane FreeTDS DDBC (paketli)
Bağlantı havuzlama Harici Yerleşik
Bağlantı başına imleç 1 Multiple
Minimum Python sürümü 3.6 3.10
callproc() Destekleniyor Uygulanmadı
as_dict imleç Extension Satır nesneleri (varsayılan)
Toplu kopya conn.bulk_copy() cursor.bulkcopy()
Varsayılan Otomatik İşleme Off Off

Temel göç adımları

Aşağıdaki adımlar, pymssql uygulamasını mssql-python'a taşımak için gereken en yaygın değişiklikleri izliyor.

1. İç aktarmaları güncelle

pymssql içe aktarmasını mssql_python ile değiştirin:

Önce (pymssql):

import pymssql

(mssql-python)'den sonra:

import mssql_python

2. Bağlantı çağrılarını güncelle

PymsSQL pozisyonsal argümanlar kullanır. mssql-python sürücüsü, bir bağlantı dizesi veya anahtar kelime argümanları kullanır:

Öncesinde (pymssql, pozisyonel argümanlar):

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

Önce (pymssql, anahtar kelime argümanları):

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

(mssql-python, bağlantı dizesi)'nden sonra:

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

Sonra (mssql-python, Microsoft Entra önerir):

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

3. Parametre işaretleyicilerini güncelle

pymssql, %s ve %d biçiminde yer tutucular kullanır. mssql-python sürücüsü, ? (qmark) veya %(name)s (pyformat) kullanır:

Önce (pymssql):

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

Sonra (mssql-python, qmark stili):

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'yi güncelle

SQL yer tutucularını %s/%d'den ? veya %(name)s'e güncelleyin:

Önce (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")]
)

Sonra (mssql-python, qmark stili):

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. as_dict imleç yerine Sıra niteliklerini kullanın

PymsSQL sütunlara isimle erişmeyi gerektirir as_dict=True . mssql-python sürücüsü, hem öznitelik hem de indeks erişimini varsayılan olarak destekleyen nesneleri döndürür Row :

Önce (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"]))

Sonra (mssql-python, varsayılan olarak öznitelik erişimi):

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]

Depolanmış prosedür göçü

mssql-python sürücüsü callproc() uygulamaz. Bunun yerine EXECUTE komutlarını kullanın.

Depolanmış prosedürler için EXECUTE kullanın

pymssql, callproc() öğesini destekler, ancak mssql-python sürücüsü desteklemez. Bunun yerine şunu kullanın EXECUTE :

Önce (pymssql):

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

(mssql-python)'den sonra:

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

Çıkış parametreleri

Çıktı parametrelerine güvenmek yerine callproc() çıktı değerlerini yakalamak için T-SQL değişkenleri kullanın:

Önce (pymssql):

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

Sonra (mssql-python, T-SQL değişkenleri):

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

Toplu kopya göçü

pymssql, bağlantı üzerinde bulk_copy() çağrısı yapar. mssql-python sürücüsü, imleç üzerinde daha fazla seçenekle bulkcopy() çağrısı yapar:

Önce (pymssql):

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

(mssql-python)'den sonra:

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

mssql-python bulkcopy() yöntemi batch_size, timeout, column_mappings, keep_identity, check_constraints, table_lock, keep_nulls, fire_triggers ve use_internal_transaction destekler. Ayrıntılar için Toplu kopyalama bölümüne bakın.

Birden çok imleç

PYMSSQL her bağlantı için yalnızca bir aktif imleç izin verir. mssql-python sürücüsü, birden fazla eşzamanlı imleci destekler:

Önce (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)'den sonra:

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

Bağlantı havuzlama

PymsSQL'de yerleşik havuzlama yok. mssql-python sürücüsü bunu otomatik olarak içeriyor:

Before (pymssql, harici havuz gerekli):

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

(mssql-python, havuzlama otomatik olur) sonra:

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

Hata yönetimi

mssql-python sürücüsü, pymssql ile aynı istisna hiyerarşisini kullanır, bu nedenle çoğu istisna işleyicisi yalnızca modül adı değişikliği gerektirir:

Önce (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)'den sonra:

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

Tam geçiş örneği

Aşağıda aynı fonksiyonun pymssql ile yazıldığı ve ardından mssql-python ile yeniden yazıldığı gösterilmektedir.

Önce (pymssql)

Bu versiyon, konumsal bağlantı argümanları ve as_dict=True%d parametre işaretleyicileri kullanır:

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

Sonra (mssql-python)

Temel yapısal değişiklikler parametre işaretleyicileri, bağlantı stili ve satır erişimidir:

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

Yapısal değişiklikler şunlardır:

  1. import pymssqlimport mssql_python.
  2. Konumsal bağlantı argümanları → anahtar sözcükler içeren bağlantı dizesi.
  3. %d parametre belirtisi → ?.
  4. cursor(as_dict=True)cursor() öznitelik erişimine sahip (row.SalesOrderID yerine row["SalesOrderID"]).

Checklist

  • [ ] İçe aktarma işlemlerini pymssql konumundan mssql_python konumuna güncelle.
  • [ ] Bağlantı çağrılarını konumsal argümanlardan bağlantı dizelerine dönüştür.
  • [ ] %s/%d parametre işaretleyicilerini ? veya %(name)s olarak dönüştürün.
  • [ ] Saklı yordam çağrıları için EXECUTE deyimlerini kullanın.
  • [ ] as_dict=True imleçleri yerine Row öznitelik erişimi kullanın.
  • [ ] conn.bulk_copy() öğesini cursor.bulkcopy() öğesine taşıyın.
  • [ ] Harici bağlantı havuzlama yapılandırmasını kaldırın.
  • [ ] FreeTDS'yi konuşlandırma gereksinimlerinden kaldırın.
  • [ ] İstisna işleme sınıf isimlerini güncelledin.
  • [ ] Tüm sorguları ve saklanan prosedürleri test edin.