使用 SQLAlchemy 连接数据库
为 SQLite 和 PostgreSQL 创建 SQLAlchemy 引擎,并将其传递给 pd.read_sql,将表加载到 DataFrame 中。
使用 SQLAlchemy 连接数据库 是 CoddyKit 上的免费 Pandas & NumPy Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Pandas & NumPy Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Pandas & NumPy Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Connect Pandas to Databases?
Most production data lives in relational databases — PostgreSQL, MySQL, SQLite, or SQL Server — not CSV files. Connecting Pandas directly to a database lets you query data into a DataFrame without exporting to CSV first, push cleaned DataFrames back into tables, and combine Python's analytical power with the database's indexing and joining capabilities. The bridge between Pandas and databases is SQLAlchemy, Python's standard database abstraction library.
Installing SQLAlchemy
SQLAlchemy is a Python SQL toolkit and ORM. For Pandas integration you only need the Core layer — not the ORM. Install with pip install sqlalchemy. You also need the specific database driver: psycopg2 for PostgreSQL, pymysql for MySQL, or sqlite3 (built into Python) for SQLite. SQLAlchemy acts as an abstraction layer: the same Pandas code works with any supported database by changing only the connection string.
# Install dependencies
# pip install sqlalchemy psycopg2-binary # for PostgreSQL
# pip install sqlalchemy pymysql # for MySQL
# sqlite3 is built into Python
import sqlalchemy as sa
import pandas as pd
print('SQLAlchemy version:', sa.__version__)Creating a Connection Engine
The first step is creating a SQLAlchemy engine using a connection URL that encodes the database type, credentials, host, port, and database name. The engine is a factory for database connections — it does not open a connection until you actually need one. Pass the engine to Pandas' pd.read_sql() and df.to_sql() functions. Never hardcode credentials; read them from environment variables or a secrets manager.
import sqlalchemy as sa
import os
# SQLite (file-based, no server needed)
sqlite_engine = sa.create_engine('sqlite:///mydata.db')
# PostgreSQL
# pg_url = 'postgresql://user:pass@localhost:5432/mydb'
# pg_engine = sa.create_engine(pg_url)
# From environment variable (safer)
# pg_engine = sa.create_engine(os.environ['DATABASE_URL'])
print(sqlite_engine)
print(type(sqlite_engine))Reading a Table with pd.read_sql_table()
pd.read_sql_table('table_name', con=engine) reads an entire database table into a DataFrame. It automatically infers column dtypes from the database schema — integers stay as integers, timestamps as datetime, etc. This is more precise than CSV inference. You can also limit columns with the columns argument and filter rows with schema for non-default database schemas. Be cautious with very large tables: this loads everything into RAM.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///sales.db')
# Read a full table
df = pd.read_sql_table('orders', con=engine)
print(df.shape)
print(df.dtypes)
print(df.head())Running Queries with pd.read_sql_query()
pd.read_sql_query('SELECT ...', con=engine) executes an arbitrary SQL SELECT statement and returns the results as a DataFrame. This is the most flexible approach: you can filter, join, and aggregate in SQL before loading into Pandas, loading only the rows and columns you need. Write the query as a plain Python string. Never concatenate user input into queries — use parameterised queries to prevent SQL injection.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///sales.db')
query = '''
SELECT customer_id, SUM(amount) AS total_spent,
COUNT(*) AS num_orders
FROM orders
WHERE status = 'completed'
GROUP BY customer_id
ORDER BY total_spent DESC
LIMIT 100
'''
top_customers = pd.read_sql_query(query, con=engine)
print(top_customers.head())Parameterised Queries for Safety
Never build SQL queries by string concatenation with user-provided values — this opens SQL injection vulnerabilities. Instead, use parameterised queries: pass parameters as a dictionary with named placeholders. SQLAlchemy handles escaping. The syntax for placeholders is :name in SQLAlchemy text queries or %(name)s for psycopg2-style queries. Always use parameterisation even for internal scripts to build good habits.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///sales.db')
# Safe: parameterised query
params = {'status': 'completed', 'min_amount': 500.0}
query = sa.text(
'SELECT * FROM orders WHERE status = :status AND amount > :min_amount'
)
with engine.connect() as conn:
df = pd.read_sql_query(query, con=conn, params=params)
print(f'Loaded {len(df)} rows')Handling Large Query Results in Chunks
For large query results, use chunksize in pd.read_sql_query() to receive an iterator of DataFrames rather than loading everything at once. This mirrors the behaviour of pd.read_csv(chunksize=...) but fetches rows from the database in batches. Combine this with a running accumulator pattern to aggregate results from million-row queries without exhausting RAM.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('postgresql://user:pass@host/db')
total = 0.0
count = 0
for chunk in pd.read_sql_query(
'SELECT amount FROM orders',
con=engine,
chunksize=50000
):
total += chunk['amount'].sum()
count += len(chunk)
print(f'Mean amount: {total/count:.2f}')Connection Context Managers
Always open database connections inside a context manager (with engine.connect() as conn:) to ensure the connection is properly closed even if an exception occurs. Forgetting to close connections leads to connection pool exhaustion in production, causing new queries to hang waiting for a free slot. SQLAlchemy's connection pool manages a fixed number of connections and recycles them automatically when context managers are used.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///sales.db')
# Using context manager — connection always closed properly
with engine.connect() as conn:
df = pd.read_sql_query(
'SELECT * FROM products WHERE category = "Electronics"',
con=conn
)
print(f'Products loaded: {len(df)}')
# Connection is automatically returned to the pool hereInspecting Database Schema
Before writing queries, you need to know what tables and columns exist. SQLAlchemy's Inspector lets you reflect the database schema without writing raw SQL. inspector.get_table_names() lists all tables; inspector.get_columns('table') returns column names and types. This is useful when working with unfamiliar databases and is cleaner than running PRAGMA table_info() or \d tablename manually.
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///sales.db')
inspector = sa.inspect(engine)
# List all tables
tables = inspector.get_table_names()
print('Tables:', tables)
# Get columns for the 'orders' table
for col in inspector.get_columns('orders'):
print(f' {col["name"]}: {col["type"]}')Closing Engines and Best Practices
In long-running scripts or web applications, call engine.dispose() when you are done to close all connections in the pool. For short scripts, Python's garbage collector handles cleanup. Best practices for database connections in data pipelines: create the engine once at the top of the script and reuse it, use connection pooling defaults (pool_size=5), enable pool_pre_ping=True to automatically reconnect if the database server restarts between queries.
import sqlalchemy as sa
# Production-grade engine creation
engine = sa.create_engine(
'postgresql://user:pass@host:5432/mydb',
pool_size=5, # max 5 persistent connections
max_overflow=10, # allow 10 temporary extra connections
pool_pre_ping=True, # verify connection before use
connect_args={'connect_timeout': 10}
)
# ... run all your queries ...
# At the end of the application/script
engine.dispose()
print('Engine disposed')Comparing read_sql vs read_csv Speed
For data already in a database with proper indexes, pd.read_sql_query with a filtered query is often faster than exporting to CSV and reading that. The database server applies filters before sending data, reducing network transfer and parse overhead. For very wide tables, the database can also project only needed columns. However, reading from a remote database over a slow network may be slower than reading a local Parquet file — always profile both options for your specific setup.
import pandas as pd
import sqlalchemy as sa
import time
engine = sa.create_engine('sqlite:///data.db')
# Database read with server-side filter
start = time.time()
df_sql = pd.read_sql_query(
'SELECT * FROM transactions WHERE amount > 100 AND year = 2024',
con=engine
)
print(f'SQL read: {time.time()-start:.3f}s, {len(df_sql):,} rows')Quick Check
Test your understanding of Data Analysis concepts from this lesson.
Lesson Recap
In this lesson you learned: sa.create_engine() creates a reusable connection factory from a URL string, pd.read_sql_query() executes arbitrary SQL and returns a DataFrame, and parameterised queries with sa.text() and params prevent SQL injection vulnerabilities. Next up we look at running more complex SQL queries from Pandas and combining SQL with Python logic.
常见问题解答
「使用 SQLAlchemy 连接数据库」课时是免费的吗?
是的 — 「使用 SQLAlchemy 连接数据库」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Pandas & NumPy Academy 课程的其余内容,请升级到 CoddyKit PRO。 Pandas & NumPy Academy 课程共包含 4 节课。
「使用 SQLAlchemy 连接数据库」这节课中我会学到什么?
为 SQLite 和 PostgreSQL 创建 SQLAlchemy 引擎,并将其传递给 pd.read_sql,将表加载到 DataFrame 中。 你通过在浏览器中直接运行的动手代码来练习 Pandas & NumPy Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Pandas & NumPy Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Pandas & NumPy Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「使用 SQLAlchemy 连接数据库」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Pandas & NumPy Academy 课中编写并运行代码吗?
能。每节 Pandas & NumPy Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 SQLAlchemy 连接数据库
- 从 Pandas 运行 SQL 查询
- 将 DataFrames 写入数据库表
- Pandas 与 SQL:选择合适的工具