SQLAlchemy 中的 func 函数使用指南

func 是 SQLAlchemy 中用于调用 SQL 函数的关键工具,它允许你在查询中使用数据库的各种内置函数。

基本介绍

funcsqlalchemy.sql.functions 模块中的一个特殊对象,它作为 SQL 函数的命名空间使用。当你访问 func 的属性时,SQLAlchemy 会创建一个对应的 SQL 函数调用。

常用函数示例

1. 聚合函数

python 复制代码
from sqlalchemy import func
from models import User, Session

session = Session()

# 计数
total_users = session.query(func.count(User.id)).scalar()

# 求和
total_salary = session.query(func.sum(User.salary)).filter(User.department == 'IT').scalar()

# 平均值
avg_age = session.query(func.avg(User.age)).scalar()

# 最大值/最小值
max_salary = session.query(func.max(User.salary)).scalar()
min_age = session.query(func.min(User.age)).scalar()

2. 字符串函数

python 复制代码
# 字符串连接
session.query(func.concat(User.first_name, ' ', User.last_name).label('full_name')).all()

# 小写转换
session.query(func.lower(User.username)).all()

# 子字符串
session.query(func.substr(User.email, 1, 5)).all()

# 字符串长度
session.query(func.length(User.address)).all()

3. 日期时间函数

python 复制代码
from datetime import datetime

# 当前日期时间
session.query(func.now()).scalar()

# 提取年份
session.query(func.extract('year', User.created_at)).all()

# 日期格式化
session.query(func.strftime('%Y-%m-%d', User.birth_date)).all()

# 日期差
session.query(func.datediff('day', User.start_date, User.end_date)).all()

4. 数学函数

python 复制代码
# 随机数
session.query(User).order_by(func.random()).first()  # PostgreSQL/SQLite
session.query(User).order_by(func.rand()).first()    # MySQL

# 绝对值
session.query(func.abs(User.balance)).all()

# 四舍五入
session.query(func.round(User.score, 2)).all()

# 平方根
session.query(func.sqrt(User.area)).all()

5. 条件表达式

python 复制代码
# CASE WHEN 表达式
session.query(
    func.case(
        [(User.age < 18, 'minor'),
         (User.age >= 18, 'adult')],
        else_='unknown'
    ).label('age_group')
).all()

# COALESCE (返回第一个非NULL值)
session.query(func.coalesce(User.nickname, User.first_name)).all()

# NULLIF (两值相等返回NULL)
session.query(func.nullif(User.salary, 0)).all()

高级用法

1. 函数组合

python 复制代码
# 计算每个用户邮箱域名的长度
session.query(
    func.length(
        func.substr(
            User.email,
            func.instr(User.email, '@') + 1
        )
    )
).all()

2. 自定义函数标签

python 复制代码
# 为函数结果指定列名
session.query(
    func.upper(User.last_name).label('last_name_upper'),
    func.lower(User.first_name).label('first_name_lower')
).all()

3. 分组中使用函数

python 复制代码
# 按年份统计用户数量
session.query(
    func.extract('year', User.created_at).label('year'),
    func.count(User.id).label('user_count')
).group_by('year').all()

4. 窗口函数

python 复制代码
from sqlalchemy import over

# 计算每个部门的薪资排名
session.query(
    User.name,
    User.salary,
    func.rank().over(
        order_by=User.salary.desc(),
        partition_by=User.department
    ).label('rank')
).all()

数据库特定函数

SQLAlchemy 可以透明地处理不同数据库的函数差异:

python 复制代码
# 处理不同数据库的日期差异计算
if dialect.name == 'postgresql':
    age_expr = func.age(User.end_date, User.start_date)
elif dialect.name == 'mysql':
    age_expr = func.timestampdiff('day', User.start_date, User.end_date)
else:
    age_expr = func.julianday(User.end_date) - func.julianday(User.start_date)

自定义函数

你还可以注册和使用自定义SQL函数:

python 复制代码
from sqlalchemy import create_engine
from sqlalchemy.sql.expression import FunctionElement
from sqlalchemy.ext.compiler import compiles

# 定义自定义函数类
class my_random(FunctionElement):
    type = Numeric()
    name = 'my_random'

# 定义编译规则
@compiles(my_random, 'postgresql')
def compile_my_random_postgresql(element, compiler, **kw):
    return "my_random()"  # 调用PostgreSQL中的自定义函数

# 使用自定义函数
session.query(User).order_by(my_random()).limit(5).all()

注意事项

  1. func 生成的是 SQL 函数表达式,不是 Python 函数调用
  2. 不同数据库支持的函数可能不同,SQLAlchemy 会尽量处理这些差异
  3. 复杂的函数组合可能会影响查询性能
  4. 在可能的情况下,考虑使用 SQLAlchemy 的核心表达式而不是原始 SQL 函数

通过 func,可以充分利用数据库的强大功能,同时保持代码的数据库无关性。

相关推荐
曲幽1 分钟前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict
荣码19 分钟前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python
兵慌码乱10 小时前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·sqlite·信号与槽·pyqt5·数据库设计·桌面应用开发·事务处理
金銀銅鐵11 小时前
[Python] 体验用欧几里得算法计算最大公约数的过程
python·数学
FreakStudio15 小时前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
用户03321266636716 小时前
使用 Python 从零创建 Word 文档
python
Csvn21 小时前
Python 两大经典坑点 —— 可变默认参数 & 闭包延迟绑定
后端·python
曲幽1 天前
别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了
python·docker·web·pot·translate·libretranslate·arogstranslate
用户556918817531 天前
#从脚本到独立程序:Python + Playwright 批量抓取的完整踩坑记录
python·自动化运维
兵慌码乱2 天前
基于 MediaPipe 与 PySide2 的手势交互音乐控制系统实现:轻量化视觉交互全流程解析
python·opencv·计算机视觉·人机交互·手势识别·mediapipe·pyside2