Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Le pilote mssql-python renvoie les données de ligne sous forme Row d’objets issus d’opérations de récupération. Ces objets offrent des schémas d’accès flexibles :
-
L’accès aux attributs (
row.ColumnName) est le choix le plus lisible pour les colonnes nommées. Utilisez-le lorsque votre requête a une liste de colonnes connue et stable. -
L’accès à la clé de chaîne (
row['ColumnName']) permet un accès de type dictionnaire aux colonnes par nom, utile lorsque vous avez besoin d’une recherche programmatique de colonnes ou lorsque les noms de colonnes contiennent des espaces ou des caractères spéciaux. -
L’accès à l’index (
row[0]) est utile pour les requêtes dynamiques où les noms des colonnes ne sont pas connus au moment du développement ou lors du traitementSELECT *des résultats. - Le déballage de tuples (
a, b, c = row) est le choix le plus concis pour les corps de boucles avec un petit nombre fixe de colonnes.
Accès aux attributs
Accéder directement aux valeurs de la colonne par nom :
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
Respect de la casse
L’accès aux noms de colonnes est sensible aux cas majuscules et correspond aux noms de colonnes retournés par SQL Server. Si votre base de données utilise des casiers incohérents, utilisez des alias SQL AS pour normaliser les noms, ou activez le lowercase paramètre du module (voir Configuration du module) :
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
Alias de colonne
Utilisez des alias SQL pour créer des noms d’attributs amicaux :
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})")
Accès à l’index
Valeurs d’accès par indice de colonnes à base de zéros :
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
Indexation négative
Le pilote prend en charge l’indexation négative de style Python :
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)
Accès à la clé de la chaîne
Accéder aux valeurs des colonnes par nom en utilisant une syntaxe de type dictionnaire :
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')
C’est utile lorsque les noms de colonnes contiennent des espaces ou des caractères spéciaux, ou lorsque vous devez accéder aux colonnes de façon programmatique :
column_name = 'ListPrice'
value = row[column_name] # Programmatic column access
Découpage
Extraire plusieurs valeurs à l’aide de tranches :
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
Déballage de tuples
Décompressez directement les valeurs des lignes en variables :
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}")
Déchargement partiel
À utiliser * pour capturer les valeurs restantes :
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}")
Longueur de ligne et itération
Travaillez avec les dimensions de ligne et itérez à travers les valeurs des colonnes :
Obtenir le nombre de colonnes
Utilisez len() pour obtenir le nombre de colonnes consécutives :
cursor.execute("SELECT * FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(len(row)) # Number of columns
Itère sur les valeurs
Bouclez les valeurs des colonnes dans l’ordre :
cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
for value in row:
print(value)
Vérifiez si une colonne existe
À utiliser hasattr() pour vérifier la présence d’un nom de colonne :
# Use hasattr to check for column name
if hasattr(row, 'DiscountPrice'):
print(f"Discount: {row.DiscountPrice}")
else:
print("No discount available")
Convertir en types intégrés
Les objets lignes peuvent être convertis en types Python standards pour une intégration avec d’autres bibliothèques et API :
Convertir en tuple
Convertir une ligne en uplet à l’aide du tuple() constructeur :
cursor.execute("SELECT ProductID, Name FROM Production.Product WHERE ProductID = 1")
row = cursor.fetchone()
row_tuple = tuple(row)
print(row_tuple) # (1, 'Adjustable Race')
Convertir en liste
Convertir une ligne en liste à l’aide du list() constructeur :
row_list = list(row)
print(row_list) # [1, 'Adjustable Race']
Convertir en dictionnaire
Convertissez une ligne en dictionnaire lorsque vous devez la sérialiser en JSON, la transférez à un moteur de templates, ou fusionnez-la avec d’autres données. Construisez le dictionnaire à partir cursor.description de valeurs de ligne :
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')}
Fonction d’aide pour la conversion de dicts
Créez une fonction d’assistance réutilisable pour convertir toutes les lignes récupérées en dictionnaires :
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'])
Travail avec des valeurs nulles
Le pilote retourne les valeurs NULL sous forme de Python None:
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}"
Travail avec cursor.description
Accéder aux métadonnées des colonnes aux côtés des lignes :
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]}")
Modèles courants
Voici des schémas pratiques pour travailler avec des objets Row dans des applications réelles :
Lignes de processus avec accès nommé
Lignes de processus utilisant l’accès aux attributs pour un code lisible et maintenable :
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}")
Construire des objets à partir de lignes
Pour les applications avec un modèle de domaine, mapper les lignes en classes de données ou en objets typés. Cette correspondance vous offre l’autocomplétion de l’IDE, la vérification des types, et une frontière claire entre les lignes de la base de données et la logique applicative.
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
]
Exportation vers JSON
Sérialiser les objets de ligne en JSON avec une gestion personnalisée des types pour les valeurs de date-heure et décimales :
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")
Agréger en groupes
Regroupez les lignes par valeur de colonne et collectez-les dans un dictionnaire pour analyse ou affichage :
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']}")