mssql-python ile sorguları çalıştır

mssql-python sürücüsü, SQL sorgu yürütme, parametreli sorgular, toplu işlemler ve hazırlanmış ibetler için imleç yöntemleri sağlar.

Temel sorgu yürütme

SQL ifadelerini çalıştırmak için bir imlecin execute() yöntemini kullanın:

import mssql_python

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

cursor.execute("SELECT Name, ListPrice FROM Production.Product WHERE Color = 'Black'")
rows = cursor.fetchall()

for row in rows:
    print(row.Name, row.ListPrice)

cursor.close()
conn.close()

Parametreli sorgular

SQL eklemesini önlemek için her zaman parametreli sorgular kullanın. Sürücünün varsayılan parametre stili pyformat (adlandırılmış yer tutucular) olsa da, qmark (konumsal yer tutucular) desteği de sunar. ODBC qmark kaçış dizileri için {CALL} kullanın.

Pyformat stili (varsayılan)

Adlandırılmış yer tutucular için %(name)s sözdizimini kullanın ve bir sözlük iletin:

cursor.execute(
    "SELECT Name, ListPrice FROM Production.Product WHERE Color = %(color)s AND ListPrice > %(price)s",
    {"color": "Black", "price": 10.00}
)

Qmark stili

? ile konumsal yer tutucular kullanın ve bir demet veya liste iletin:

cursor.execute(
    "SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = ? AND ListPrice > ?",
    (1, 10.00)
)

Sürücü, SQL sorgusunuza ve parametre türlerinize göre parametre stilini otomatik olarak algılar.

INSERT, UPDATE, DELETE işlemler

Veri değiştirme ifadeleri için parametreli sorgular kullanın ve işlemi taahhüt edin:

cursor.execute("CREATE TABLE #ExecDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.execute(
    "INSERT INTO #ExecDemo (Name, CategoryID, Price) VALUES (%(name)s, %(category)s, %(price)s)",
    {"name": "New Product", "category": 1, "price": 19.99}
)
conn.commit()

print(f"Rows affected: {cursor.rowcount}")

executemany() ile toplu yürütme

Birden fazla satırı verimli bir şekilde eklemek için executemany() kullanın. Sürücü, yüksek performans için sütunlu parametre bağlaması kullanır:

products = [
    {"name": "Product A", "category": 1, "price": 10.00},
    {"name": "Product B", "category": 1, "price": 15.00},
    {"name": "Product C", "category": 2, "price": 20.00},
]

cursor.execute("CREATE TABLE #BatchDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.executemany(
    "INSERT INTO #BatchDemo (Name, CategoryID, Price) VALUES (%(name)s, %(category)s, %(price)s)",
    products
)
conn.commit()

print(f"Rows inserted: {cursor.rowcount}")

Qmark stiliyle:

products = [
    ("Product A", 1, 10.00),
    ("Product B", 1, 15.00),
    ("Product C", 2, 20.00),
]

cursor.execute("CREATE TABLE #QmarkDemo (Name NVARCHAR(50), CategoryID INT, Price DECIMAL(10,2))")
cursor.executemany(
    "INSERT INTO #QmarkDemo (Name, CategoryID, Price) VALUES (?, ?, ?)",
    products
)
conn.commit()

Birden çok komutun toplu çalıştırılması

Çok ifadeli Transact-SQL (T-SQL) partisini cursor.execute() öğesine ilettiğinizde, sonuçlar arasında ilerlemek için nextset() çağırın. Her başarılı çağrı, o sonuç için cursor.rowcount öğesini yeniler. cursor.description öğesini getirmeden önce kontrol edin çünkü INSERT, UPDATE ve DELETE sonuçların satırlar yerine etkilenen satır sayıları vardır. Daha fazla bilgi için, Bir toplu işlemde her sonucu izleme.

Bağlantıda tek bir çağrıda birden fazla farklı ifadeyi çalıştırmak için kullanılır batch_execute() :

results, cursor = conn.batch_execute(
    [
        "CREATE TABLE #BatchExec (Name NVARCHAR(50), CategoryID INT)",
        "INSERT INTO #BatchExec (Name, CategoryID) VALUES (%(name)s, %(cat)s)",
        "SELECT COUNT(*) FROM #BatchExec"
    ],
    [
        None,                                 # No params for CREATE
        {"name": "New Item", "cat": 1},       # Params for INSERT
        None                                  # No params for SELECT
    ]
)

print(f"CREATE result: {results[0]}")
print(f"INSERT affected: {results[1]} rows")
print(f"Row count: {results[2][0][0]}")

Hazırlanmış ifadeler

Sürücü, sorguları varsayılan olarak (use_prepare=True) hazırlar. Aynı SQL dizesini aynı imlecte birden fazla kez çalıştırdığınızda, sürücü hazırlanmış ifadeyi sonraki çağrılarda otomatik olarak yeniden kullanır:

# First execution prepares the statement
cursor.execute(
    "SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(subcategory_id)s",
    {"subcategory_id": 1},
)
rows1 = cursor.fetchall()

# Same SQL string on same cursor → driver reuses the prepared plan
cursor.execute(
    "SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = %(subcategory_id)s",
    {"subcategory_id": 2},
)
rows2 = cursor.fetchall()

Hazırlıkları atlayıp doğrudan uygulama kullanmak için:

cursor.execute(
    "SELECT Name, ListPrice FROM Production.Product WHERE ProductSubcategoryID = 1",
    use_prepare=False  # Uses SQLExecDirectW instead of SQLPrepareW
)

Bağlantı düzeyinde çalıştır

Basit tek seferlik sorgular için, doğrudan bağlantı üzerinde kullanın execute() :

# Creates cursor, executes, and returns cursor
cursor = conn.execute("SELECT TOP 10 Name, ListPrice FROM Production.Product")
rows = cursor.fetchall()
cursor.close()

Saklanan prosedürler

Depolanmış yordamları EXECUTE veya ODBC {CALL} kaçış söz dizimini kullanarak çağırın. Çıktı parametreleri, çoklu sonuç kümeleri ve işlem desenleri hakkında bilgi için Stored prosedürler sayfasına bakınız.

cursor.execute(
    "EXECUTE dbo.uspGetManagerEmployees @BusinessEntityID = %(business_entity_id)s",
    {"business_entity_id": 16}
)
rows = cursor.fetchall()

Giriş boyutlarını ayarla

Parametre türlerini açıkça bildirmek için kullanılır setinputsizes() , bu da toplu işlemler için performansı artırabilir:

cursor.setinputsizes([
    (mssql_python.SQL_WVARCHAR, 50, 0),   # NVARCHAR(50)
    (mssql_python.SQL_INTEGER, 0, 0),     # INT
])

cursor.executemany(
    "SELECT ProductID, Name FROM Production.Product WHERE Name LIKE ? AND ProductSubcategoryID = ?",
    [("Road%", 2), ("Mountain%", 1)]
)

Note

Tüm SQL tip sabitleri ile setinputsizes()çalışmaz. SQL_WVARCHAR ve SQL_INTEGER güvenilirdir. Ondalık değerler için, bilinen bir sorun olan sürücünün otomatik tip çıkarımı yerine SQL_DECIMALkullanın (GitHub #503).

Hata yönetimi

Veritabanı işlemlerini try-except blokları içine alın:

try:
    cursor.execute("CREATE TABLE #ErrDemo (Name NVARCHAR(50) NOT NULL)")
    cursor.execute("INSERT INTO #ErrDemo (Name) VALUES (%(name)s)", {"name": None})
    conn.commit()
except mssql_python.IntegrityError as e:
    print(f"Constraint violation: {e}")
    conn.rollback()
except mssql_python.ProgrammingError as e:
    print(f"SQL error: {e}")
    conn.rollback()

En iyi uygulamalar

  1. SQL enjeksiyonunu önlemek için her zaman parametreli sorgular kullanın.
  2. execute() kullanın.
  3. İşlemleri açıkça onaylayın; otomatik onayı devre dışı bıraktığınızda.
  4. İş tamamlandığında imlecleri ve bağlantıları kapatarak kaynakları serbest bırakın.
  5. Otomatik kaynak temizleme için bağlam yöneticileri kullanın:
with mssql_python.connect(connection_string) as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT TOP 5 Name, ListPrice FROM Production.Product")
        rows = cursor.fetchall()
# Connection and cursor automatically closed