SQLAlchemy的使用(四)--使用方法进阶

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()的方式关联起来。

猜你喜欢

转载自blog.csdn.net/qq_43355223/article/details/83542739