[SQLAlchemy] sqlAlchemy学习笔记(2): 在orm中使用select
SELECT的作用
select在sql中的作用是选中特定列并以表的形式返回, 是必要的关键字; 在sqlalchemy中, select()方法会返回一个Select对象, 并根据这个对象引入其他方法, 如where(), join(), order_by()等等
from sqlalchemy import select stmt = select(User).where(User.name == "spongebob")
即
SELECT user_account.id, user_account.name, user_account.fullname
FROM user_account
WHERE user_account.name = "spongebob";
注意select()里的参数是orm中映射数据表的类 -> i.e.User类对应user_account表
使用scalars()格式化返回结果
首先来看一看这条
result = session.execute(select(User).order_by(User.id))
如果我们执行上面的语句, execute方法实际上会返回一个含有Row对象的数组(Result对象), 每个Row对象里只有一个元素, 那就是一个User对象
result.all()
返回结果为
[(User(id=1, name='spongebob', fullname='Spongebob Squarepants'),),
(User(id=2, name='sandy', fullname='Sandy Cheeks'),),
(User(id=3, name='patrick', fullname='Patrick Star'),),
(User(id=4, name='squidward', fullname='Squidward Tentacles'),),
(User(id=5, name='ehkrabs', fullname='Eugene H. Krabs'),)]
这时候我们需要scalars方法去掉Row, 这有两种方式, 但她们都使用了同一种方法(名)
- Session.scalars()
session.scalars(select(User).order_by(User.id)).all()
- Result.scalars()
记住Session.execute返回了一个Result对象, 而它的主体类里则定义了一个scalars方法
result = session.execute(select(User).order_by(User.id)) result.scalars().all()
选中复数orm对象
stmt = select(User, Address).join(User.addresses).order_by(User.id, Address.id) for row in session.execute(stmt): print(f"{row.User.name} {row.Address.email_address}")
SELECT user_account.id, user_account.name, user_account.fullname, address.id AS id_1, address.user_id, address.email_address
FROM user_account
JOIN address ON user_account.id = address.user_id
ORDER BY user_account.id, address.id;
选中特定列
stmt = select(User.name, Address.email_address).join(User.addresses).order_by(User.id, Address.id) for row in session.execute(stmt): print(f"{row.name} {row.email_address}")
SELECT user_account.name, address.email_address
FROM user_account JOIN address ON user_account.id = address.user_id
ORDER BY user_account.id, address.id;
使用Bundle进行分组
当我们试图选中列时, 需要使用类名来进行区分, 这是必须的->但是如果被选中的列很多, 像上一种写法必然是繁琐的, 我们可以使用Bundle类来区分它们, 注意使用Bundle类的结果和单纯使用select是一样的, 只是增加了代码的可读性
from sqlalchemy.orm import Bundle # 使用Bundle将来自不同类的属性区分开 stmt = select( Bundle("user", User.name, User.fullname), Bundle("email", Address.email_address), ).join_from(User, Address) # 注意这里引用的路径也不一样了 for row in session.execute(stmt): print(f"{row.user.name} {row.user.fullname} {row.email.email_address}")
使用自定义别名
在写sql语句的时候, 经常需要使用别名来简写表名或是区别相同表, 在sqlalchemy中也有同样的用法
from sqlalchemy.orm import aliased u1 = aliased(User, name="u1") stmt = select(u1).order_by(u1.id) row = session.execute(stmt).first() print(f"{row.u1.name}")
子查询
有时候sql语句可以很复杂, 经常在查询里加查询,在sqlalchemy中我们需要用到subquery方法
# 内查询语句 inner_stmt = select(User).where(User.id < 7).order_by(User.id) # 拿subquery封装一下 subq = inner_stmt.subquery() # 给结果加个别名, 绑定一下对应类(表) aliased_user = aliased(User, subq) # 外部的sql查询 stmt = select(aliased_user) # 执行, 打印结果 for user_obj in session.execute(stmt).scalars(): print(user_obj)
sql查询语句长这样
SELECT anon_1.id, anon_1.name, anon_1.fullname FROM (SELECT user_account.id AS id, user_account.name AS name, user_account.fullname AS fullname FROM user_account WHERE user_account.id < ? ORDER BY user_account.id) AS anon_1;
注意因为没有指定别名, 因此别名anon_1是系统自动给的
实现UNION
UNION也是sql中一个常见的关键字(虽然我不喜欢用)
from sqlalchemy import union_all # sql查询命令的文本, 其实是一个内查询的语句 --> 集合两张结果表, 并将结果以id排序 u = union_all( select(User).where(User.id < 2), select(User).where(User.id == 3) ).order_by(User.id) # 将sql文本(内查询语句)加进最终指令stmt中 stmt = select(User).from_statement(u) # 执行并打印 for user_obj in session.execute(stmt).scalars(): print(user_obj)
注意这个方法没有用到任何子查询⬇️直来直去的
SELECT user_account.id, user_account.name, user_account.fullname FROM user_account WHERE user_account.id < ? UNION ALL SELECT user_account.id, user_account.name, user_account.fullname FROM user_account WHERE user_account.id = ? ORDER BY id;
另一种方法, 使用subquery
subq = union_all( select(User).where(User.id < 2), select(User).where(User.id == 3) ).subquery() user_alias = aliased(User, subq) stmt = select(user_alias).order_by(user_alias.id) for user_obj in session.execute(stmt).scalars(): print(user_obj)
对应的sql是这样⬇️很难懂但很有观赏性
SELECT anon_1.id, anon_1.name, anon_1.fullname FROM (SELECT user_account.id AS id, user_account.name AS name, user_account.fullname AS fullname FROM user_account WHERE user_account.id < ? UNION ALL SELECT user_account.id AS id, user_account.name AS name, user_account.fullname AS fullname FROM user_account WHERE user_account.id = ?) AS anon_1 ORDER BY anon_1.id;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律