SQLAlchemy的orm和core的区别:
SQLAlchemy Core: 基于schema(数据库的组织与结构)的,就有点类似于传统的SQL,在数据仓库,报表分析等方面能够对查询控制的更好。
SQLAlchemy ORM: 但是如果在考虑领域模型的设计时,ORM封装了大量底层的schema和元数据结构,这种封装使得开发人员和数据库的交互变得更加简单
在select的时候指定一个column的值:
UpdateID = case([(Deployment.ActionID.is_(None), updateID), ], else_=updateID).label("UpdateID")
随便指定一个值,不管是什么判定结果,都让他的值等于这个你想要的结果,然后在select的字段中加上这个变量名就行,这个是灵活使用case来达到目的。
check exist:检查是否存在的方法
if session.query(model).filter(some_filter).count():
这样可以使用计数的方式达到目的,只要计数不为0,那么就表示存在
object relational tutorial:
什么是keyedtuple:
>>> k = KeyedTuple([1, 2, 3], labels=["one", "two", "three"])
>>> k.one
1
每一个item都有与之对应的标签
每一次Query返回的结果都是named tuples,也就是keyedTuple:
>>> for row in session.query(User, User.name).all():
... print(row.User, row.name)
也可以对每一个选出来的字段指定想要的名字,也就是加上标签:
User.name.label('name_label')
如果一个对象需要在query中用到多次,就可以命名:
user_alias = aliased(User, name='user_alias')
query中的and和or :
and_(User.name == 'ed', User.fullname == 'Ed Jones')
or_(User.name == 'ed', User.name == 'wendy')
!!!!!!!使用文本sql, Textual SQL:!!!!!!!
文本字符串可以在query中使用,使用text():
>>> from sqlalchemy import text
SQL>>> for user in session.query(User).\
... filter(text("id<224")).\
... order_by(text("id")).all():
... print(user.name)
还可以使用params()
来传递参数
※如果要使用整句文本SQL,可以结合from_statement()
使用:
session.query(User).from_statement(
... text("SELECT * FROM users where name=:name")).\
... params(name='ed').all()
更复杂的使用方法:
>>> stmt = text("SELECT name, id FROM users where name=:name")
>>> stmt = stmt.columns(User.name, User.id)
>>> session.query(User.id, User.name).\
... from_statement(stmt).params(name='ed').all()
很复杂的sql语句可以使用正常的query orm方式结合text()方式一起使用,使用案例:
case_check = case([(Update.DetectoidType != None, Update.DetectoidType), ], else_=session.query(Category).from_statement(text("(SELECT TOP 1 CategoryType FROM tbCategory WHERE tbCategory.CategoryID = tbUpdate.LocalUpdateID)")))
result = session.query(Revision.RevisionID,
Revision.LocalUpdateID,
case_check).\
join(Update, Revision.LocalUpdateID == Update.LocalUpdateID).\
filter(Revision.IsLeaf == 0).all()
这里要注意,有一个容易报错的地方是没有打括号,因为它是直接把这段SQL语句插入进去,所以注意括号的位置。
querying with Joins:
可以直接使用filter()来隐式地join两个对象
如果两个表之间只有一个外键相连接,可以不用指定条件:
session.query(User).join(Address)
如果没有或者有多个外键,那么需要指定条件:
query.join(Address, User.id==Address.user_id)
!!!!!!如果使用query select from多个entities:
query = session.query(User, Address).select_from(Address).join(User)
使用子查询,Subqueries :
示例:
SELECT users.*, adr_count.address_count FROM users LEFT OUTER JOIN
(SELECT user_id, count(*) AS address_count
FROM addresses GROUP BY user_id) AS adr_count
ON users.id=adr_count.user_id
使用query实现:
>>> stmt = session.query(Address.user_id, func.count('*').\
... label('address_count')).\
... group_by(Address.user_id).subquery()
这里需要使用subquery()
来代表一个select语句
这个subquery()生成的结果类似于一个table结构,可以用c
来获取里面的字段:
>>> for u, count in session.query(User, stmt.c.address_count).\
... outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id):
... print(u, count)
Eager Loading:
当需要load一组objects以及他们相关联的collections的时候,用subqueryload()
:
>>> from sqlalchemy.orm import subqueryload
SQL>>> jack = session.query(User).\
... options(subqueryload(User.addresses)).\
... filter_by(name='jack').one()
更常用的方法是joinload()
所以join和load都是一步完成:
>>> jack = session.query(User).\
... options(joinedload(User.addresses)).\
... filter_by(name='jack').one()
Mapper Configuration:
有两种mapper的形式:
一种是Declarative Mapping:这种直接使用class User(Base)
这种方式建立映射表。
另一种是Classical Mappings: 这种方法需要建立Table,然后建立一个与之关联的类,最后用mapper()的方式关联起来。