Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
mssql-python-drivrutinen returnerar raddata som Row objekt från hämtaoperationer. Dessa objekt erbjuder flexibla åtkomstmönster:
-
Attributåtkomst (
row.ColumnName) är det mest läsbara valet för namngivna kolumner. Använd den när din fråga har en känd, stabil kolumnlista. -
Strängnyckelåtkomst (
row['ColumnName']) ger lexikonliknande åtkomst till kolumner efter namn, användbart när du behöver programmatisk kolumnuppslagning eller när kolumnnamn innehåller mellanslag eller specialtecken. -
Indexåtkomst (
row[0]) är användbar för dynamiska frågor där kolumnnamn inte är kända vid utvecklingstillfället, eller vid bearbetningSELECT *av resultat. -
Tuple unpacking (
a, b, c = row) är det mest koncisa valet för loopkroppar med ett litet, fast antal kolumner.
Attributåtkomst
Åtkomst till kolumnvärden direkt efter namn:
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
Skiftlägesberoende
Åtkomst till kolumnnamn är kasuskänslig och matchar kolumnnamnen som returneras av SQL Server. Om din databas använder inkonsekvent casing, använd SQL-aliaser AS för att normalisera namn, eller aktivera modulinställningen lowercase (se Modulkonfiguration):
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
Kolumnaliaser
Använd SQL-alias för att skapa vänliga attributnamn:
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})")
Indexåtkomst
Åtkomstvärden efter nollbaserat kolumnindex:
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
Negativ indexering
Drivrutinen stödjer negativ indexering i Python-stil:
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)
Strängnyckelåtkomst
Åtkomst till kolumnvärden efter namn med hjälp av ordboksliknande syntax:
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')
Detta är användbart när kolumnnamn innehåller mellanslag eller specialtecken, eller när du behöver komma åt kolumner programmatiskt:
column_name = 'ListPrice'
value = row[column_name] # Programmatic column access
Skivning
Extrahera flera värden med hjälp av skivor:
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-uppackning
Packa upp radvärden direkt till variabler:
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}")
Delvis upppackning
Använd * för att fånga återstående värden:
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}")
Radlängd och iteration
Arbeta med raddimensioner och iterera genom kolumnvärden:
Få kolumnräkning
Använd len() för att få antalet kolumner i rad:
cursor.execute("SELECT * FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(len(row)) # Number of columns
Iterera över värden
Loop genom kolumnvärden i ordning:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
for value in row:
print(value)
Kontrollera om kolumnen finns
Använd hasattr() för att testa förekomsten av ett kolumnnamn:
# Use hasattr to check for column name
if hasattr(row, 'DiscountPrice'):
print(f"Discount: {row.DiscountPrice}")
else:
print("No discount available")
Konvertera till inbyggda typer
Radobjekt kan konverteras till standardtyper i Python för integration med andra bibliotek och API:er:
Konvertera till tupel
Konvertera en rad till en tuple med konstruktorn tuple() :
cursor.execute("SELECT ProductID, Name FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
row_tuple = tuple(row)
print(row_tuple) # (1, 'Adjustable Race')
Konvertera till lista
Konvertera en rad till en lista med konstruktören list() :
row_list = list(row)
print(row_list) # [1, 'Adjustable Race']
Konvertera till ordlista
Konvertera en rad till en ordbok när du behöver serialisera den till JSON, skicka den till en mallmotor eller slå ihop den med annan data. Bygg ordboken från cursor.description och radvärden:
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
# Create dict from description and values
columns = [col[0] for col in cursor.description]
row_dict = dict(zip(columns, row))
print(row_dict) # {'ProductID': 1, 'Name': 'Adjustable Race', 'ListPrice': Decimal('0.00')}
Hjälpfunktion för diktomvandling
Skapa en återanvändbar hjälpfunktion för att konvertera alla hämtade rader till ordböcker:
def rows_to_dicts(cursor):
"""Convert fetched rows to list of dictionaries."""
columns = [col[0] for col in cursor.description]
return [dict(zip(columns, row)) 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'])
Arbete med nullbara värden
Drivrutinen returnerar NULL-värden som 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}"
Arbeta med cursor.description
Åtkomst till kolumnmetadata tillsammans med raddata:
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]}")
Vanliga mönster
Här är praktiska mönster för att arbeta med radobjekt i verkliga tillämpningar:
Processrader med namngiven åtkomst
Processrader med attributåtkomst för läsbar, underhållbar kod:
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}")
Bygg objekt från rader
För applikationer med en domänmodell, mappa rader till dataklasser eller typade objekt. Denna mappning ger dig IDE-autokomplettering, typkontroll och en tydlig gräns mellan databasrader och applikationslogik.
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 till JSON
Serialisera radobjekt till JSON med anpassad typhantering för datetime och decimalvärden:
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):
columns = [col[0] for col in cursor.description]
rows = [dict(zip(columns, row)) 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")
Aggregera i grupper
Gruppera rader efter ett kolumnvärde och samla dem i en ordbok för analys eller visning:
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']}")