Gegevens ophalen met mssql-python

De mssql-python-driver biedt verschillende fetch-methoden, rijtoegangspatronen en cursornavigatiefuncties om queryresultaten op te halen.

Ophaalmethodes

Na het uitvoeren van een SELECT-query gebruik je fetch-methoden om resultaten op te halen.

fetchone()

Geeft één enkele rij terug of None als er geen rijen meer beschikbaar zijn:

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

Geeft een lijst met rijen terug. cursor.arraysize Regelt de standaard batchgrootte (standaard: 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)

Je kunt ook direct de grootte specificeren:

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

Fetchall()

Retourneert alle resterende rijen als een lijst:

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

Geeft de eerste kolom van de eerste rij terug, wat nuttig is voor scalaire zoekopdrachten.

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

Rijtoegangspatronen

De Row klasse ondersteunt meerdere toegangspatronen.

Indextoegang

Kolommen benaderen op positie (nulgebaseerd):

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]

Toegang tot attributen

Toegang tot kolommen op naam:

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

Kolomnamen met kleine letters

Schakel attribuutnamen in kleine letters globaal in:

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

Iteration

Rijen ondersteunen iteratie over waarden:

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

for value in row:
    print(value)

Iteratie van de cursor

Direct over de cursor itereren om rijen te verwerken:

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

for row in cursor:
    print(row.Name)

Dit patroon is gelijk aan herhaaldelijk bellen fetchone() .

Kolommetadata

Toegang tot kolominformatie via 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}")

Aantal rijen

Het cursor.rowcount attribuut geeft aan:

  • Voor SELECT: Retourneert -1 daarna execute() totdat het ophalen begint. Zodra je begint met ophalen, weerspiegelt het het cumulatieve aantal tot nu toe opgehaalde rijen.
  • Voor INSERT/UPDATE/DELETE: Aantal getroffen rijen.
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}")

Cursornavigatie

skip()

Sla rijen over zonder ze te halen:

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

scroll()

Verplaats de cursorpositie naar voren:

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

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

row = cursor.fetchone()

Opmerking

De driver ondersteunt alleen mode='relative' met positieve waarden. Absolute positionering en achterwaarts scrollen veroorzaken NotSupportedError, omdat het stuurprogramma cursors gebruikt die alleen vooruit kunnen.

rijnummer

Houd de huidige positie bij:

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)

Meerdere resultaatsets

Gebruik nextset() om meerdere resultaatsets te verwerken:

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

Grote resultaatverzamelingen

Voor grote resultaatsets verwerk je rijen in batches om het geheugen te beheren:

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

Contextbeheerders

Gebruik contextmanagers voor het automatisch opschonen van resources:

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

Beste praktijken

  • Gebruik fetchmany() het voor grote resultaten om te voorkomen dat alles in het geheugen wordt geladen.
  • Sluit cursors als je klaar bent om serverbronnen vrij te geven.
  • Gebruik kolomnamen (attribuuttoegang) voor beter leesbare code.
  • Controle rowcount na gegevenswijzigingsinstructies.
  • Handel None expliciet met waarden wanneer kolommen nul zijn.