Of course! Here’s a comprehensive guide to using Python ORMs with SQL Server, covering the most popular libraries: SQLAlchemy and Django ORM.
Introduction: What is an ORM?
An Object-Relational Mapper (ORM) is a library that automates the transfer of data between a relational database (like SQL Server) and Python objects. Instead of writing raw SQL queries, you interact with Python classes and objects, which the ORM then translates into efficient SQL.
Key Benefits:
- Database Agnostic: Switching databases (e.g., from SQL Server to PostgreSQL) often requires minimal code changes.
- Increased Productivity: Focus on your Python application logic, not SQL syntax.
- Security: Automatically helps prevent SQL injection attacks.
- Maintainability: Code is often cleaner and easier to read, especially for complex queries.
SQLAlchemy: The King of Flexibility
SQLAlchemy is the most popular and powerful ORM for Python. It's not just an ORM; it's a complete SQL toolkit and Object-Relational Mapping library. It comes in two main flavors:
- Core (SQL Expression Language): A schema-centric, "imperative" style of building SQL queries. It's like building SQL queries with Python objects. Great for writing complex, dynamic queries.
- ORM: An extension of the Core that maps database tables to Python classes. You work with instances of these classes (objects) instead of table rows.
For most use cases, you'll use the ORM, which still gives you access to the underlying Core when needed.
Installation
First, you need to install SQLAlchemy and a database driver for SQL Server. The standard and recommended driver is pyodbc.
pip install sqlalchemy pyodbc
Step-by-Step SQLAlchemy ORM Example
Let's build a simple application to manage users.

Step 1: Import and Create the Engine
The Engine is the core interface to the database. It manages the connection pool and handles the translation of SQL queries.
import sqlalchemy from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base # --- Connection String --- # Format: mssql+pyodbc://username:password@server_name/database_name?driver=ODBC+Driver+17+for+SQL+Server # - Replace with your actual credentials and server details. # - The driver name might vary (e.g., "ODBC Driver 18 for SQL Server"). # - For Windows Authentication, use: mssql+pyodbc://@server_name/database_name?driver=ODBC+Driver+17+for+SQL+Server&trusted_connection=yes # Example using Windows Authentication # For SQL Server Express LocalDB, the server is often '(localdb)\MSSQLLocalDB' CONNECTION_STRING = "mssql+pyodbc://@localhost/mydatabase?driver=ODBC+Driver+17+for+SQL+Server&trusted_connection=yes" # Create the engine engine = create_engine(CONNECTION_STRING, echo=True) # echo=True will print the generated SQL
Step 2: Define the Mapping (Create the Table Model)
We define a Python class that represents our users table. This class will inherit from declarative_base.
Base = declarative_base()
class User(Base):
__tablename__ = 'users' # The name of the table in the database
id = Column(Integer, primary_key=True)
name = Column(String(50))
email = Column(String(120), unique=True)
def __repr__(self):
return f"<User(name='{self.name}', email='{self.email}')>"
# This will create the 'users' table if it doesn't exist
# Base.metadata.create_all(engine)
Step 3: Create a Session
The Session is the primary interface for interacting with the database. It's like a "workspace" for your operations.
# Create a configured "Session" class Session = sessionmaker(bind=engine) # Create a new Session instance session = Session()
Step 4: Perform CRUD Operations

Now you can interact with the database using your User objects.
Create (Insert)
# Create new user objects
new_user1 = User(name='Alice', email='alice@example.com')
new_user2 = User(name='Bob', email='bob@example.com')
# Add them to the session
session.add(new_user1)
session.add(new_user2)
# Commit the session to persist the objects to the database
session.commit()
print(f"Added user with ID: {new_user1.id}")
Read (Select)
# Query all users
print("\n--- All Users ---")
all_users = session.query(User).all()
for user in all_users:
print(user)
# Query a specific user by email
print("\n--- User with email 'bob@example.com' ---")
bob = session.query(User).filter_by(email='bob@example.com').first()
if bob:
print(f"Found: {bob}")
# Query with a filter
print("\n--- Users whose name starts with 'A' ---")
a_users = session.query(User).filter(User.name.like('A%')).all()
for user in a_users:
print(user)
Update
# Find the user to update
user_to_update = session.query(User).filter_by(name='Bob').first()
if user_to_update:
print(f"\nUpdating {user_to_update.name}'s email...")
user_to_update.email = 'bob.new@example.com'
session.commit()
print("Updated successfully!")
Delete
# Find the user to delete
user_to_delete = session.query(User).filter_by(name='Alice').first()
if user_to_delete:
print(f"\nDeleting {user_to_delete.name}...")
session.delete(user_to_delete)
session.commit()
print("Deleted successfully!")
Step 5: Close the Session
Always close your session when you're done.

session.close()
Django ORM: The Integrated Choice
If you are using the Django web framework, the ORM is built-in and tightly integrated. It's less flexible than SQLAlchemy but incredibly fast for standard web application development.
Prerequisites
- Install Django:
pip install django - Set up a Django project:
django-admin startproject myproject - Add
pyodbcto your project's requirements.
Step-by-Step Django ORM Example
Step 1: Configure settings.py
Tell Django to use SQL Server and provide the connection details.
# myproject/settings.py
DATABASES = {
'default': {
'ENGINE': 'sql_server.pyodbc', # The Django backend for SQL Server
'NAME': 'mydatabase',
'USER': '', # For Windows Auth, leave empty
'PASSWORD': '', # For Windows Auth, leave empty
'HOST': 'localhost', # or your server name
'PORT': '',
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server', # IMPORTANT: Must match your system
'trusted_connection': 'yes', # For Windows Authentication
# 'MARS_Connection': 'yes', # Enable Multiple Active Result Sets if needed
},
}
}
Step 2: Define the Model
In one of your Django apps, create a models.py file.
# myapp/models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField(unique=True)
def __str__(self):
return self.name
Step 3: Create and Apply Migrations
This step creates the actual table in your database.
# Generate the migration file based on your model python manage.py makemigrations myapp # Apply the migration to the database python manage.py migrate
Step 4: Use the ORM in your Django Views or Shell
You can now use the Django ORM anywhere in your project.
# In a view, shell, or management command
# Create
User.objects.create(name='Charlie', email='charlie@example.com')
User.objects.bulk_create([
User(name='David', email='david@example.com'),
User(name='Eve', email='eve@example.com')
])
# Read
print("\n--- All Users ---")
all_users = User.objects.all()
for user in all_users:
print(user)
print("\n--- User with email 'charlie@example.com' ---")
charlie = User.objects.get(email='charlie@example.com')
print(charlie)
# Filter
print("\n--- Users whose name starts with 'D' ---")
d_users = User.objects.filter(name__startswith='D')
for user in d_users:
print(user)
# Update
print("\nUpdating Charlie's email...")
charlie.email = 'charlie.updated@example.com'
charlie.save() # save() triggers an UPDATE statement
print("Updated!")
# Delete
print("\nDeleting Eve...")
User.objects.filter(name='Eve').delete() # delete() can be called on a queryset
print("Deleted!")
Comparison: SQLAlchemy vs. Django ORM
| Feature | SQLAlchemy ORM | Django ORM |
