Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De mssql-python-driver retourneert rijgegevens als Row objecten uit fetch-operaties. Deze objecten bieden flexibele toegangspatronen:
-
Attribuuttoegang (
row.ColumnName) is de meest leesbare keuze voor benoemde kolommen. Gebruik het wanneer je query een bekende, stabiele kolomlijst heeft. -
String key access (
row['ColumnName']) biedt woordenboekachtige toegang tot kolommen op naam, handig wanneer je programmatische kolomzoekopdracht nodig hebt of wanneer kolomnamen spaties of speciale tekens bevatten. -
Indextoegang (
row[0]) is nuttig voor dynamische queries waarbij kolomnamen niet bekend zijn tijdens de ontwikkeling of bij het verwerkenSELECT *van resultaten. -
Tuple unpacking (
a, b, c = row) is de meest beknopte keuze voor luslichamen met een klein, vast aantal kolommen. -
Mapping access (
row._mapping) levert een alleen-lezen mapping van kolomnamen naar waarden terug. Gebruik het om een rij om te zetten naar een woordenboek of om de rij door te geven aan code die een mapping verwacht.
Attribuuttoegang
Raadpleeg kolomwaarden direct op naam:
import mssql_python
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
print(row.ProductID) # 1
print(row.Name) # 'Adjustable Race'
print(row.ListPrice) # 0.00
Hoofdlettergevoelig
Kolomnaamtoegang is hoofdlettergevoelig en komt overeen met de kolomnamen die door SQL Server worden teruggegeven. Als je database inconsistente casing gebruikt, gebruik dan SQL-aliasen AS om namen te normaliseren, of schakel de lowercase module-instelling in (zie Moduleconfiguratie):
cursor.execute("SELECT FirstName, LastName, EmailPromotion FROM Person.Person WHERE BusinessEntityID < 10")
row = cursor.fetchone()
print(row.FirstName) # Works
print(row.LastName) # Works
print(row.EmailPromotion) # Works
print(row.firstname) # AttributeError - wrong case
Kolomaliasen
Gebruik SQL-aliassen om vriendelijke attribuutnamen te maken:
cursor.execute("""
SELECT
p.ProductID,
p.Name,
c.Name AS Category
FROM Production.Product p
JOIN Production.ProductSubcategory c ON p.ProductSubcategoryID = c.ProductSubcategoryID
WHERE p.ProductSubcategoryID IS NOT NULL
""")
for row in cursor:
print(f"{row.Name} ({row.Category})")
Indextoegang
Toegangswaarden via nul-gebaseerde kolomindex:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(row[0]) # ProductID
print(row[1]) # Name
print(row[2]) # ListPrice
Negatieve indexering
De driver ondersteunt negatieve indexering in Python-stijl:
cursor.execute("""
SELECT Demo.A, Demo.B, Demo.C, Demo.D
FROM (VALUES (1, 2, 3, 4)) AS Demo(A, B, C, D)
""")
row = cursor.fetchone()
print(row[-1]) # Last column (D)
print(row[-2]) # Second to last (C)
Toegang tot de string-sleutel
Raadpleeg kolomwaarden op naam met behulp van woordenboekachtige syntaxis:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
print(row['ProductID']) # 1
print(row['Name']) # 'Adjustable Race'
print(row['ListPrice']) # Decimal('0.00')
Dit is handig wanneer kolomnamen spaties of speciale tekens bevatten, of wanneer je kolommen programmatisch moet benaderen:
column_name = 'ListPrice'
value = row[column_name] # Programmatic column access
Snijden
Haal meerdere waarden uit met slices:
cursor.execute("""
SELECT Demo.A, Demo.B, Demo.C, Demo.D, Demo.E
FROM (VALUES (1, 2, 3, 4, 5)) AS Demo(A, B, C, D, E)
""")
row = cursor.fetchone()
print(row[1:4]) # Columns B, C, D (indices 1, 2, 3)
print(row[:2]) # First two columns (A, B)
print(row[2:]) # From C to end
Tuple uitpakken
Pak rijwaarden direct uit in variabelen:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 10")
for product_id, name, price in cursor:
print(f"#{product_id}: {name} - ${price}")
Gedeeltelijke uitpakken
Gebruik * om de resterende waarden vast te leggen:
cursor.execute("""
SELECT TOP 2 ProductID, Name, ProductNumber, Color, Size, Weight
FROM Production.Product
WHERE ProductNumber IS NOT NULL
ORDER BY ProductID
""")
for product_id, name, *rest in cursor:
print(f"{product_id}: {name}, extra columns: {rest}")
Rijlengte en iteratie
Werk met rijafmetingen en herhaal kolomwaarden:
Krijg kolomaantal
Gebruik len() om het aantal kolommen in een rij te krijgen:
cursor.execute("SELECT * FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(len(row)) # Number of columns
Itereren over waarden
Loop kolomwaarden in volgorde door:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
for value in row:
print(value)
Controleer of er een kolom bestaat
Gebruik hasattr() om te testen op de aanwezigheid van een kolomnaam:
# Use hasattr to check for column name
if hasattr(row, 'DiscountPrice'):
print(f"Discount: {row.DiscountPrice}")
else:
print("No discount available")
Converteer naar ingebouwde types
Rijobjecten kunnen worden omgezet naar standaard Python-types voor integratie met andere bibliotheken en API's:
Converteer naar tuple
Zet een rij om in een tuple met de tuple() constructor:
cursor.execute("SELECT ProductID, Name FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
row_tuple = tuple(row)
print(row_tuple) # (1, 'Adjustable Race')
Omzetten naar lijst
Zet een rij om in een lijst met de list() constructor:
row_list = list(row)
print(row_list) # [1, 'Adjustable Race']
Converteren naar woordenlijst
Converteer een rij naar een woordenboek wanneer je deze moet serialiseren naar JSON, geef hem door aan een template-engine, of voeg hem samen met andere data. De row._mapping eigenschap geeft een alleen-lezen mapping van kolomnamen terug naar waarden in de kolomvolgorde van het resultaat. Geef het door dict() om een regulier woordenboek te krijgen:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
row_dict = dict(row._mapping)
print(row_dict) # {'ProductID': 1, 'Name': 'Adjustable Race', 'ListPrice': Decimal('0.0000')}
Het eigendom vertoont _mapping de volgende gedragingen:
- De mapping is alleen-lezen. Het toewijzen aan een sleutel verhoogt
TypeError. Converteer het eerst metdict()als je waarden moet veranderen. - Sleutels zijn de kolomnamen uit
cursor.description. Belangrijke opzoekopdrachten zijn hoofdlettergevoelig. Als je delowercasemodule-instelling inschakelt, zijn de toetsen kleine letters en komt de mapping alleen overeen met die kleine letters. Attribuut- en string-toetstoegang op de rij zelf wordt hoofdlettergevoelig wanneerlowercaseaan staat, maarrow._mappingopzoekingen niet. - Als de resultaatset dubbele kolomnamen heeft, behoudt de mapping de laatste waarde voor elke naam. Gebruik Transact-SQL (T-SQL)
ASaliassen om elke kolom een unieke naam te geven, of lees de waarden per index. - De eigenschap gaat voor een resultaatkolom met de naam
_mapping, dusrow._mappinggeeft altijd de afbeelding terug. Lees die column metrow['_mapping'].
Hulpfunctie voor dictconversie
Maak een herbruikbare hulpfunctie om alle opgehaalde rijen om te zetten in woordenboeken:
def rows_to_dicts(cursor):
"""Convert fetched rows to list of dictionaries."""
return [dict(row._mapping) for row in cursor.fetchall()]
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 10")
products = rows_to_dicts(cursor)
for p in products:
print(p['Name'])
Werk met nullbare waarden
De driver geeft NULL-waarden terug als PythonNone:
cursor.execute("SELECT FirstName, MiddleName, LastName FROM Person.Person WHERE BusinessEntityID = 1")
row = cursor.fetchone()
if row.MiddleName is None:
full_name = f"{row.FirstName} {row.LastName}"
else:
full_name = f"{row.FirstName} {row.MiddleName} {row.LastName}"
Werk met cursor.description
Toegang tot kolommetadata naast rijgegevens:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
# Column information
for col in cursor.description:
print(f"Name: {col[0]}, Type: {col[1]}")
# Fetch with metadata
row = cursor.fetchone()
for i, col in enumerate(cursor.description):
print(f"{col[0]}: {row[i]}")
Algemene patronen
Hier zijn praktische patronen voor het werken met Row-objecten in toepassingen in de echte wereld:
Procesrijen met benoemde toegang
Procesrijen met attribuuttoegang voor leesbare, onderhoudbare code:
def process_orders(conn):
cursor = conn.cursor()
cursor.execute("""
SELECT SalesOrderID, CustomerID, OrderDate, TotalDue
FROM Sales.SalesOrderHeader
WHERE Status = 5
""")
for order in cursor:
print(f"Order #{order.SalesOrderID}")
print(f" Customer: {order.CustomerID}")
print(f" Date: {order.OrderDate}")
print(f" Total: ${order.TotalDue:.2f}")
Bouw objecten uit rijen
Voor toepassingen met een domeinmodel koppel je rijen aan dataklassen of getypeerde objecten. Deze mapping geeft je IDE-autocompletie, typecontrole en een duidelijke grens tussen databaserijen en applicatielogica.
from dataclasses import dataclass
from datetime import date
from decimal import Decimal
@dataclass
class Product:
id: int
name: str
price: Decimal
created: date
def get_products(conn) -> list[Product]:
cursor = conn.cursor()
cursor.execute("SELECT ProductID, Name, ListPrice, SellStartDate FROM Production.Product WHERE ProductID < 10")
return [
Product(
id=row.ProductID,
name=row.Name,
price=row.ListPrice,
created=row.SellStartDate
)
for row in cursor
]
Export naar JSON
Serialiseer rijobjecten naar JSON met aangepaste typebehandeling voor datetime en decimale waarden:
import json
from datetime import date, datetime
from decimal import Decimal
def json_serializer(obj):
"""Custom serializer for non-JSON types."""
if isinstance(obj, (date, datetime)):
return obj.isoformat()
if isinstance(obj, Decimal):
return float(obj)
raise TypeError(f"Type {type(obj)} not serializable")
def export_to_json(cursor, filename):
rows = [dict(row._mapping) for row in cursor.fetchall()]
with open(filename, 'w') as f:
json.dump(rows, f, default=json_serializer, indent=2)
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 10")
export_to_json(cursor, "products.json")
Samenvoegen in groepen
Groepeer rijen op kolomwaarde en verzamel ze in een woordenboek voor analyse of weergave:
from collections import defaultdict
cursor.execute("""
SELECT c.Name AS CategoryName, p.Name AS ProductName, p.ListPrice
FROM Production.Product p
JOIN Production.ProductSubcategory c ON p.ProductSubcategoryID = c.ProductSubcategoryID
WHERE p.ProductSubcategoryID IS NOT NULL
ORDER BY c.Name
""")
products_by_category = defaultdict(list)
for row in cursor:
products_by_category[row.CategoryName].append({
'name': row.ProductName,
'price': row.ListPrice
})
for category, products in products_by_category.items():
print(f"\n{category}:")
for p in products:
print(f" - {p['name']}: ${p['price']}")