Pobieranie danych za pomocą mssql-python

Sterownik mssql-python oferuje kilka metod pobierania, wzorców dostępu wierszowego oraz funkcje nawigacji kursorem do pobierania wyników zapytań.

Metody pobierania

Po wykonaniu zapytania SELECT użyj metod pobierania do pobrania wyników.

fetchone()

Zwraca pojedynczy wiersz lub None jeśli nie ma już dostępnych wierszy:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product")

row = cursor.fetchone()
while row:
    print(f"{row.ProductID}: {row.Name} - ${row.ListPrice}")
    row = cursor.fetchone()

fetchmany()

Zwraca listę wierszy. cursor.arraysize kontroluje domyślny rozmiar partii (domyślny: 1):

cursor.execute("SELECT * FROM Production.Product")
cursor.arraysize = 100  # Fetch 100 rows at a time

while True:
    rows = cursor.fetchmany()
    if not rows:
        break
    for row in rows:
        print(row.Name)

Możesz też bezpośrednio określić rozmiar:

rows = cursor.fetchmany(50)  # Fetch up to 50 rows

fetchall()

Zwraca wszystkie pozostałe wiersze jako listę:

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

print(f"Found {len(rows)} products")
for row in rows:
    print(row.Name)

fetchval()

Zwraca pierwszą kolumnę pierwszego wiersza, co jest przydatne do zapytań skalarnych.

count = cursor.execute("SELECT COUNT(*) FROM Production.Product").fetchval()
print(f"Total products: {count}")

max_price = cursor.execute("SELECT MAX(ListPrice) FROM Production.Product").fetchval()
print(f"Highest price: ${max_price}")

Wzorce dostępu do wierszy

Klasa Row obsługuje wiele wzorców dostępu.

Dostęp do indeksu

Uzyskaj dostęp do kolumn według pozycji (indeksowanej od zera):

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

product_id = row[0]
name = row[1]
price = row[2]

Dostęp do atrybutów

Dostęp do kolumn według nazwy:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

product_id = row.ProductID
name = row.Name
price = row.ListPrice

Nazwy kolumn małymi literami

Włącz globalne użycie małych liter w nazwach atrybutów:

import mssql_python

settings = mssql_python.get_settings()
settings.lowercase = True

cursor.execute("SELECT ProductID, Name FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(row.productid, row.name)  # Lowercase access
settings.lowercase = False  # Restore default

Iteracja

Wiersze wspierają iterację nad wartościami:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

for value in row:
    print(value)

Iteracja kursora

Iteruj bezpośrednio po kursorze, aby przetwarzać wiersze:

cursor.execute("SELECT * FROM Production.Product")

for row in cursor:
    print(row.Name)

Ten wzorzec jest równoważny powtarzaniu się wywoływania fetchone() .

Metadane kolumn

Dostęp do informacji o kolumnie poprzez cursor.description:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")

for col in cursor.description:
    name, type_code, display_size, internal_size, precision, scale, null_ok = col
    print(f"Column: {name}, Type: {type_code}, Nullable: {null_ok}")

Liczba wierszy

Atrybut wskazuje cursor.rowcount :

  • Dla instrukcji SELECT: Zwraca -1 po execute() do momentu rozpoczęcia pobierania. Gdy zaczniesz pobierać, pokazuje łączną liczbę dotychczas pobranych wierszy.
  • Dla INSERT/UPDATE/DELETE: Liczba wierszy dotkniętych zmianą.
cursor.execute("SELECT * FROM Production.Product")
print(f"Rows returned: {cursor.rowcount}")

cursor.execute("CREATE TABLE #PriceUpd (Name NVARCHAR(50), Price DECIMAL(10,2), CategoryID INT)")
cursor.execute("INSERT INTO #PriceUpd VALUES ('A',10,1),('B',20,1),('C',30,2)")
cursor.execute("UPDATE #PriceUpd SET Price = Price * 1.1 WHERE CategoryID = 1")
print(f"Rows updated: {cursor.rowcount}")

Nawigacja kursorem

skip()

Pomiń wiersze bez ich pobierania:

cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")
cursor.skip(10)  # Skip first 10 rows
row = cursor.fetchone()  # Returns 11th row

scroll()

Przesuń pozycję kursora do przodu:

cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")

# Move forward 5 rows from current position
cursor.scroll(5, mode='relative')

row = cursor.fetchone()

Note

Sterownik obsługuje tylko dodatnie wartości mode='relative'. Pozycjonowanie bezwzględne i przewijanie do tyłu powodują wystąpienie NotSupportedError, ponieważ sterownik używa kursorów przewijanych tylko do przodu.

numer wiersza

Śledź aktualną sytuację:

cursor.execute("SELECT * FROM Production.Product")

print(f"Initial position: {cursor.rownumber}")  # -1 (before first fetch)

row = cursor.fetchone()
print(f"After fetchone: {cursor.rownumber}")    # 0 (first row fetched)

Wiele zestawów wyników

Wykorzystanie nextset() do przetwarzania wielu zbiorów wyników:

cursor.execute("""
    SELECT * FROM Production.Product WHERE Color = 'Black';
    SELECT * FROM Production.ProductCategory;
    SELECT COUNT(*) FROM Production.Product;
""")

# First result set
products = cursor.fetchall()
print(f"Products: {len(products)}")

# Move to second result set
if cursor.nextset():
    categories = cursor.fetchall()
    print(f"Categories: {len(categories)}")

# Move to third result set
if cursor.nextset():
    count = cursor.fetchval()
    print(f"Total count: {count}")

Duże zbiory wyników

Dla dużych zbiorów wyników przetwarzamy wiersze w partiach do zarządzania pamięcią:

def process_batch(rows):
    # Example: print each row. Replace with your own logic.
    for row in rows:
        print(row)

cursor.execute("SELECT * FROM LargeTable")
cursor.arraysize = 1000

while True:
    rows = cursor.fetchmany()
    if not rows:
        break

    process_batch(rows)
    print(f"Processed {cursor.rownumber} rows so far")

Menedżerowie kontekstu

Używaj menedżerów kontekstu do automatycznego czyszczenia zasobów:

with mssql_python.connect(connection_string) as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM Production.Product")
        for row in cursor:
            print(row.Name)
# Cursor and connection closed automatically

Najlepsze rozwiązania

  • Używaj fetchmany() do dużych wyników , aby uniknąć ładowania wszystkiego do pamięci.
  • Zamykaj kursory, gdy to robisz, aby zwolnić zasoby serwera.
  • Używaj nazw kolumn (dostęp do atrybutów), aby kod był bardziej czytelny.
  • Sprawdź rowcount po instrukcjach modyfikujących dane.
  • Jawnie obsługuj wartości Nonegdy kolumny mogą przyjmować wartość NULL.