MySQL进阶篇-ORM sqlachemy笔记

ORM sqlachemy简介

orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。

orm的优点:

  1. 隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
  2. ORM使我们构造固化数据结构变得简单易行。

缺点:

  1. 无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。

sqlalchemy安装

在Python中,最有名的ORM框架是SQLAlchemy。用户包括openstack\Dropbox等知名公司或应用,主要用户列表http://www.sqlalchemy.org/organizations.html#openstack

SQLAlchemy本身无法操作数据库,其必须依赖pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

MySQL-Python
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
   
pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
   
MySQL-Connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
   
cx_Oracle
    oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
   
更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
pip3 install SQLAlchemy  # 据说输入两次可以显示安装路径

sqlalchemy基本使用

下面就开始让你见证orm的nb之处,盘古开天劈地之前,我们创建一个表是这样的

CREATE TABLE user (
    id INTEGER NOT NULL AUTO_INCREMENT,
    name VARCHAR(32),
    password VARCHAR(64),
    PRIMARY KEY (id)
)

创建表的方式1:

#!/usr/bin/env python
# Author:uson
# -*- coding:utf-8 -*-
'''创建表School'''
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String

#socket连接到对应的数据库
# engine = create_engine("mysql+pymysql://uson:[email protected]/usondb", encoding="utf-8", echo=True)
# echo=True: 打印所有的创建记录
engine = create_engine("mysql+pymysql://uson:[email protected]/usondb", encoding="utf-8")

#生成orm基类
Base = declarative_base()

#创建一个table:School学校类,是基于上面实例化的父类
class School(Base):#继承父类Base
    '''给学校这张表创建一个id, name和addr三个字段'''
    __tablename__ = 'school' # 表名:school
    id = Column(Integer, primary_key=True) #id列(Column)
    name = Column(String(32))   # nullable=False不能为空
    # password = Column(String(64))
    addr = Column(String(64))

#创建表结构,上面的类只是声明了表字段
Base.metadata.create_all(engine) #父亲调儿子,Base.create_all调用了School类

创建表的方式2:

#!/usr/bin/env python
# Author:uson
# -*- coding:utf-8 -*-
from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
'''我们不用这种方式创建表'''

# '''为什么没创建?还没连接呢!'''
# from sqlalchemy import create_engine
# engine = create_engine("mysql+pymysql://uson:[email protected]/usondb", encoding="utf-8", echo=True)

metadata = MetaData() #实例化MetaData类

#通过实例化Table类,声明表结构
school = Table( #实例化sqlalchemy下面的Table类
    'school_2', metadata, #表名
    Column('id', Integer, primary_key=True),
    Column('name', String(32)),
    Column('fullname', String(64)),
    Column('addr', String(64)),
)
#创建一个类,用于后面通过实例化School类,进行传参,主要后面查询需要用到
class School(object):
    def __init__(self, name, fullname, addr):
        self.name = name
        self.fullname = fullname
        self.addr = addr
#开始建立连接,创建school_2数据表
mapper(School, school)  # tablela metadata、user_defind class、mapper对象三者实现orm对象对表映射(不常用)

详细版建表,创建数据:

#!/usr/bin/env python
# Author:uson
# -*- coding:utf-8 -*-
'''创建数据'''

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String

#socket连接
engine = create_engine("mysql+pymysql://uson:[email protected]/usondb", encoding="utf-8")

#实例化一个orm基类:避免创建mysql原生语句
Base = declarative_base()

#继承Base父类,创建一个学校类:python通过学校类操作orm,orm操作原生语句
class School(Base):
    __tablename__ = 'school'    #创建表名
    
    # 创建表字段
    # id = Column(Integer, autoincrement=True, primary_key=True)
    id = Column(Integer, primary_key=True)     #主键默认自增id,无需传参,效果同上
    name = Column(String(32))
    addr = Column(String(64))
    
#真正创建表
Base.metadata.create_all(engine)
'''上面创建好了表school'''

'''下面创建数据'''
#导入创建数据的会话生成器
from sqlalchemy.orm import sessionmaker

#创建与数据库的会话session_class,这里返回给session的是一个class,而不是一个实例
Session_class = sessionmaker(bind=engine) #bind socket

#创建一个session实例
Session = Session_class() #cursor游标,实例化会话生成器

#实例化声明的School类,生成你要创建的数据对象
school_obj_1 = School(name='老男孩', addr='上海闵行') #实例化School,传name,addr,id是主键,自增
school_obj_2 = School(name='黑马', addr='上海浦东') #实例化School,传name,addr,id是主键,自增
# school_obj_2 = School('黑马', '上海浦东') #__init__() takes 1 positional argument but 3 were given
print(school_obj_1.name, school_obj_1.addr)  #此时还没创建对象呢,不信你打印一下id发现还是None

#把要创建的数据对象添加到这个session会话生成器里, 一会统一创建
Session.add(school_obj_1) #一次仅能提交一个实例【#复制,粘贴,去数据库梦游一趟】
Session.add(school_obj_2)
print(school_obj_2.name, school_obj_2.addr)#此时也依然还没创建

#现在开始统一提交,创建数据
Session.commit()

单条件、多条件查询:

#!/usr/bin/env python
# Author:uson
# -*- coding:utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
engine = create_engine("mysql+pymysql://uson:[email protected]/usondb", encoding="utf-8")  # .../usondb?charset=utf8支持中文已经失效了,有没有都可以支持中文
Base = declarative_base()

class School(Base):
    __tablename__ = 'student' 
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    addr = Column(String(64))

    '''数据可读'''
    def __repr__(self):
        return "<School(name='%s', addr='%s')>" %(self.name, self.addr)

# Base.metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker 
Session_class = sessionmaker(bind=engine) 
Session = Session_class() 

# my_school = Session.query(School).filter_by(name='老男孩')
#列表里面存放对象地址[<__main__.School object at 0x0364BF50>, <__main__.School object at 0x0364BFB0>]
# my_school = Session.query(School).filter_by(name="老男孩").all()
# print("My_School>>", my_school[0].name) #列表第一个元素数据

#列表第一个'类对象'地址<__main__.School object at 0x04716350>
# my_school = Session.query(School).filter_by(name="老男孩").first()
# print("My_School>>", my_school.name)

'''单条件查询'''
# my_school = Session.query(School).filter_by(id=2).all() #√ 
# my_school = Session.query(School).filter(School.id==2).all() #√ 
# my_school = Session.query(School).filter(School.id>2).all() #√
'''多条件查询'''
my_school = Session.query(School).filter(School.id>14).filter(School.id<16).all() #√
print("My_School>>", my_school[0].name)

# 查询不需要commit()
'''
filter(id > 2)  X                    filter_by(id = 2)   √
filter(School.id > 2)  √            filter_by(School.id = 2)   X
filter(School.id == 2)  √           filter_by(id > 2)   X
                                     filter_by(School.id > 2)   X
'''

修改:

'''修改:本例不支持批量修改'''
my_school = Session.query(School).filter(School.name=='Qi').first() #√ 先查后改
# my_school = Session.query(School).filter(School.name=='Qi').all() #X
my_school.name = 'qi' 
Session.commit()   # 修改数据需要提交才能生效

Alex说:mysql默认大小写一样匹配

查询Session有没有某个方法:dir((Session)

回滚:

#!/usr/bin/env python
# Author:uson
# -*- coding:utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Date, Enum
import datetime

engine = create_engine("mysql+pymysql://uson:[email protected]/usondb", encoding="utf-8")
Base = declarative_base()
class School(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True)
    age = Column(Integer)
    name = Column(String(32))
    job = Column(String(32))
    sex = Column(String(32))
    
    register_date = Column(Date) #日期用date类型,下面实参必须是"2019-1-1"字符串形式,不加字符串引号,会按减法计算
    addr = Column(Enum("Luan", "Beijing", "Shanghai")) #重新定义枚举数据
    born = Column(Enum("Luan", "Beijing", "Shanghai"))

    def __repr__(self):
        return "<%s name='%s', addr='%s'>" %(self.id, self.name, self.addr)
from sqlalchemy.orm import sessionmaker
Session_class = sessionmaker(bind=engine)
Session = Session_class()

'''回滚'''
#实例化一行数据
# data_1 = School(name='智汇部落', age=3, register_date='2019-1-1',
#                 job='Web', sex='www.cohui.top', born='Luan', addr='Beijing') #addr:枚举
# data_1 = School(name='智汇部落', age=3, register_date=2019-1-1, #2017
#                 job='Web', sex='www.cohui.top', born='Luan', addr='Beijing') #addr:枚举
data_1 = School(name='智汇部落', age=3, register_date=datetime.date(year=2018, month=1, day=12),
                job='Web', sex='www.cohui.top', born='Luan', addr='Beijing') #addr:枚举

#添加实例数据到会话生成器
Session.add(data_1)

#查询回滚前数据
#School.name.in_(['智汇部落', 'cohui']:获取列表中的包含这些的条件的所有对象(并集之意)
my_data = Session.query(School).filter(School.name.in_(['智汇部落', 'cohui'])).all()

#打印回滚前数据
print("回滚前:", my_data) #这时看session里有你刚添加和修改的数据

#回滚
Session.rollback()

#查询回滚后数据
my_data = Session.query(School).filter(School.name.in_(['智汇部落', 'cohui'])).all()

#打印回滚前数据
print("回滚后:", my_data)#再查就发现刚才添加的数据没有了。

统计:

#统计所有以(像)Q开头的name的数量
num = Session.query(School).filter(School.name.like("q%")).count() #不区分大小写,q与Q

分组:

from sqlalchemy import func
#按name分组统计所有相同name的数量
num_g = Session.query(func.count(School.name), School.name).group_by(School.name).all()
# query参数的顺序无关  [(1, 'Hong'), (1, 'qi'), (1, 'QiYu')]

join连表查询:

#!/usr/bin/env python
# Author:uson
# -*- coding:utf-8 -*-
'''外键关联'''
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship

engine = create_engine("mysql+pymysql://uson:[email protected]/cohuidb", encoding="utf-8")
Base = declarative_base()

class Student(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True)
    name = Column(String(32), nullable=False)
    register_date = Column(String(64), nullable=False)
    def __repr__(self):
        return "id:%s name:%s" %(self.id, self.name)

class Study_Record(Base):
    __tablename__ = 'study_record'
    id = Column(Integer, primary_key=True)
    day = Column(Integer, nullable=False)
    status = Column(String(32), nullable=False)

    stu_id = Column(Integer, ForeignKey('Student.id'))
    students = relationship('Student', backref='my_study_record')
    def __repr__(self):
        return "id:%s stu_id:%s name:%s " %(
            self.id, self.stu_id ,self.students.name)

# Base.metadata.create_all(engine)

from sqlalchemy.orm import sessionmaker
Session_class = sessionmaker(bind=engine)
Session = Session_class()
# stu_1 = Student(name='周波', register_date="2018-6-23")
# stu_2 = Student(name='韩斌', register_date="2018-6-24")
# stu_3 = Student(name='方雾', register_date="2018-6-23")
# stu_4 = Student(name='魏志强', register_date="2018-9-20")
# stu_5 = Student(name='何正刚', register_date="2018-8-8")
# stu_6 = Student(name='马远剑', register_date="2019-4-1")
# stu_7 = Student(name='陈秋莲', register_date="2019-3-20")
# stu_8 = Student(name='任揽', register_date="2019-3-20")
# stu_9 = Student(name='李宏宇', register_date="2019-4-20")
# stu_rec1 = Study_Record(day=1, status='yes', stu_id=1)
# stu_rec2 = Study_Record(day=5, status='yes', stu_id=2)
# stu_rec3 = Study_Record(day=4, status='yes', stu_id=3)
# stu_rec4 = Study_Record(day=12, status='yes', stu_id=4)
# stu_rec5 = Study_Record(day=6, status='no', stu_id=5)
# stu_rec6 = Study_Record(day=4, status='no', stu_id=6)
# stu_rec7 = Study_Record(day=5, status='yes', stu_id=7)
# stu_rec8 = Study_Record(day=5, status='yes', stu_id=8)
# stu_rec9 = Study_Record(day=9, status='no', stu_id=9)
# Session.add_all([stu_1, stu_2, stu_3, stu_4, stu_5, stu_6, stu_7, stu_8, stu_9,
#                  stu_rec1, stu_rec2, stu_rec3, stu_rec4, stu_rec5, stu_rec6, stu_rec7, stu_rec8, stu_rec9])
# stu_data = Session.query(Student).filter(Student.name=='周波').all()[0]
# print("stu_data:", stu_data.my_study_record)
# Session.commit()

'''join连表'''
#返回两张表中主键交集的所有数据
print(Session.query(Student, Study_Record).filter(Student.id == Study_Record.id).all())
# [(id:1 name:cohui, id:1 stu_id:1 name:cohui ), (id:2 name:Uson, id:2 stu_id:2 name:Uson ),
#  (id:3 name:Uson, id:3 stu_id:3 name:Uson ), (id:12 name:李宏宇, id:12 stu_id:1 name:cohui )]

'''必要两表之间有外键关联才能使用,且用法不同上面的join'''
# 返回Student表中所有已经外键关联Study_Record的Student数据
print(Session.query(Student).join(Study_Record).all())
# [id:1 name:cohui, id:2 name:Uson, id:3 name:Uson, id:4 name:周波, id:5 name:韩斌]

# 返回Study_Record表中所有已经外键关联Student的Study_Record数据
print(Session.query(Study_Record).join(Student).all())
# [id:1 stu_id:1 name:cohui , id:2 stu_id:2 name:Uson , id:3 stu_id:3 name:Uson , id:12 stu_id:1 name:cohui ,
# id:13 stu_id:2 name:Uson , id:14 stu_id:3 name:Uson , id:15 stu_id:4 name:周波 , id:16 stu_id:5 name:韩斌 ]

# 返回Student外键关联的Student整张表的数据
print(Session.query(Student).join(Study_Record, isouter=True).all())
# [id:1 name:cohui, id:2 name:Uson, id:3 name:Uson, id:4 name:周波, id:5 name:韩斌, id:6 name:方雾, id:7 name:魏志强,
#  id:8 name:何正刚, id:9 name:马远剑, id:10 name:陈秋莲, id:11 name:任揽, id:12 name:李宏宇]

# 返回Study_Record外键关联的Study_Record整张表的数据
print(Session.query(Study_Record).join(Student, isouter=True).all())
# [id:1 stu_id:1 name:cohui , id:2 stu_id:2 name:Uson , id:3 stu_id:3 name:Uson , id:12 stu_id:1 name:cohui ,
# id:13 stu_id:2 name:Uson , id:14 stu_id:3 name:Uson , id:15 stu_id:4 name:周波 , id:16 stu_id:5 name:韩斌 ]

ORM操作表要点整理:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Uson

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine

# 连接池最大连接数为5
engine = create_engine("mysql+pymysql://uson:[email protected]/cohuidb", max_overflow=5)

Base = declarative_base()

# 创建单表
class Users(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    extra = Column(String(16))

    __table_args__ = (   # 联合唯一键:UniqueConstraint,name:是存入数据库的名字
        # UniqueConstraint('name', name='uix_id_name'), # name是唯一
        UniqueConstraint('id', 'name', name='uix_id_name'), # name是外键且唯一  
        Index('ix_id_name', 'name', 'extra'), # 建立索引
    )

    def __repr__(self):
        return "%s-%s" %(self.id, self.name)
Base.metadata.create_all(engine)

# 单外键关联
class Student(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True) #主键
    name = Column(String(32), index=True, nullable=False)
    register_date = Column(String(64), nullable=False) #不为null

    def __repr__(self):
        return "<%s name: %s>" %(self.id, self.name)

class Study_Record(Base):
    __tablename__ = 'study_record'
    id = Column(Integer, primary_key=True)  # 主键
    day = Column(Integer, nullable=False)
    status = Column(String(32),  default='Yes', unique=True)

    stu_id = Column(Integer, ForeignKey('student.id')) #外键关联 表的id
    # 与生成表结构无关,仅用于查询方便,存在内存中,实现对象关联的映射
    students = relationship('Student', backref='my_study_record') # 该字段不能用于条件查询, 只能是查询结果后的反查询
    # 用students可查Student里面的所有字段
    # 用my_study_record可反查Study_Record里面的所有字段

    def __repr__(self):
        return "<%s day: %s status: %s>" %(self.students.name, self.day, self.status)

# 多外键关联
class Customer(Base):
    __tablename__ = 'customer'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))

    '''一个人多个地址'''
    billing_address_id = Column(Integer, ForeignKey('address.id'))
    shipping_address_id = Column(Integer, ForeignKey('address.id'))

    '''relationship多表之间建立关系:foreign_keys与relationship相对应————多映射'''
    billing_address = relationship('Address', foreign_keys=[billing_address_id])
    shipping_address = relationship('Address', foreign_keys=[shipping_address_id])
    # sqlachemy就能分清哪个外键是对应哪个字段了

    def __repr__(self):
        return "<state:%s city:%s street:%s\nstate:%s city:%s street:%s\>" %(
            self.billing_address.state, self.billing_address.city, self.billing_address.street,
            self.shipping_address.state, self.shipping_address.city, self.shipping_address.street)

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    street = Column(String(32))
    city = Column(String(32))
    state = Column(String(32)) #省,洲

# Base.metadata.create_all(engine) #创建表结构

Session_class = sessionmaker(bind=engine)
Session = Session_class()
# 注意:(两张表数据要分2次插入)先实例Address,再实例Customer,否则第一次失败,Customer的id要重新修改
'''Address实例化'''
addr_1 = Address(street='金阳路', city='闵行', state='上海')
addr_2 = Address(street='向阳路', city='松江', state='上海')
addr_3 = Address(street='都会路', city='青浦', state='上海')
addr_4 = Address(street='都市路', city='浦东', state='上海')
addr_5 = Address(street='dushi', city='dong', state='SH')
# Session.add_all([addr_1, addr_2, addr_3, addr_4, addr_5])
'''Customer实例化'''
# 哎,2017年的时候,还可以直接将add_1传过去,现在只能传数字,这样,id也获取不到,必须查数据库
cus_1 = Customer(name='Alex', billing_address_id=1, shipping_address_id=2)
cus_2 = Customer(name='Jack', billing_address_id=2, shipping_address_id=3)
cus_3 = Customer(name='Uson', billing_address_id=3, shipping_address_id=4)
cus_4 = Customer(name='Cohui',billing_address_id=4, shipping_address_id=4)
Session.add_all([cus_1, cus_2, cus_3, cus_4])
cus_data = Session.query(Customer).filter(Customer.name=='Alex').first()
print("Cus_data:", cus_data)
# Session.commit()

# 多对多关联(双向一对多,就是多对多)一
Book_To_Author = Table(
    'book_to_author', Base.metadata,   # 表名:book_to_author  实例名:Book_To_Author
    Column('books_id', Integer, ForeignKey('book.id')),
    Column('authors_id', Integer, ForeignKey('author.id')),
)
class Author(Base):
    __tablename__ = 'author'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
class Book(Base):
    __tablename__ = 'book'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    pub_date = Column(Date)
    #authors是第三张表字段 赋值后的列表;My_Books:列表类[类的实例化]
    authors = relationship('Author', secondary=Book_To_Author, backref='My_Books') #[]  或者:secondary='book_to_author'
    def __repr__(self):
        return "<book_name:%s book_pubdate:%s>" %(self.name, self.pub_date) 

bk_1 = Book(name="Python_senior_book", pub_date='2019-5-3')
bk_2 = Book(name="Linux_base_book", pub_date='2013-10-16')
bk_3 = Book(name="Python_base_book", pub_date='2018-11-3')
bk_4 = Book(name="Linux_senior_book", pub_date='2014-6-12')
ah_1 = Author(name='Alex')
ah_2 = Author(name='Uson')
ah_3 = Author(name='Cohui')
ah_4 = Author(name='Qiyu')

#这里的authors是以列表形式关联着Author类和自己Book类
bk_1.authors = [ah_1, ah_2]
bk_2.authors = [ah_1, ah_3]
bk_3.authors = [ah_2, ah_4]
bk_4.authors = [ah_3]

Session.add_all([bk_1, bk_2, bk_3, bk_4,
                 ah_1, ah_2, ah_3, ah_4])


# 多对多关联(双向一对多,就是多对多)二
class ServerToGroup(Base):
    __tablename__ = 'servertogroup'
    nid = Column(Integer, primary_key=True, autoincrement=True)
    server_id = Column(Integer, ForeignKey('server.id'))
    group_id = Column(Integer, ForeignKey('group.id'))
    group = relationship("Group", backref='s2g')
    server = relationship("Server", backref='s2g')

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer, primary_key=True)
    name = Column(String(64), unique=True, nullable=False)
    port = Column(Integer, default=22)
    # group = relationship('Group',secondary=ServerToGroup,backref='host_list')

class Server(Base):
    __tablename__ = 'server'

    id = Column(Integer, primary_key=True, autoincrement=True)
    hostname = Column(String(64), unique=True, nullable=False)

# 删除
'''通过书删除作者:将这本书的作者删除一个'''
#1)找到要删除的作者
author_data = Session.query(orm_many_fk_many.Author).filter(
    orm_many_fk_many.Author.name=='Alex').first()
print("--------Alex---------", author_data) #列表类
#2)找到书Linux_base_book对应的作者列表:[Alex, Cohui]
book_data = Session.query(orm_many_fk_many.Book).filter(
    orm_many_fk_many.Book.name=='Linux_base_book').first()
# print("--------Linux_base_book---------", book_data) #列表类
print("--------Linux_base_book---------", book_data.authors) #列表类
#开始删除
# book_data.authors.remove('alex') #只能是对象,不能是字符串
book_data.authors.remove(author_data)
Session.commit()

'''直接删除作者'''
author_data = Session.query(orm_many_fk_many.Author).filter(
    orm_many_fk_many.Author.name=='Alex').first()
print("--------单独查询---------", author_data.name, author_data.My_Books[0].name) #列表类
print("-----------------", author_data) #列表类
Session.delete(author_data)
Session.commit()

# 创建表
def init_db():
    Base.metadata.create_all(engine)

# 删除表
def drop_db():
    Base.metadata.drop_all(engine)

增:

obj = Users(name="alex0", extra='sb')
session.add(obj)
session.add_all([
    Users(name="alex1", extra='sb'),
    Users(name="alex2", extra='sb'),
])
session.commit()

删:

session.query(Users).filter(Users.id > 2).delete()
session.commit()

改:

session.query(Users).filter(Users.id > 2).update({"name" : "099"})
session.query(Users).filter(Users.id > 2).update({Users.name: Users.name + "099"}, synchronize_session=False)
session.query(Users).filter(Users.id > 2).update({"num": Users.num + 1}, synchronize_session="evaluate")
session.commit()

查:

ret = session.query(Users).all()
ret = session.query(Users.name, Users.extra).all()
ret = session.query(Users).filter_by(name='alex').all()
ret = session.query(Users).filter_by(name='alex').first()

ret = session.query(Users).filter(text("id<:value and name=:name")).params(value=224, name='fred').order_by(User.id).all()

ret = session.query(Users).from_statement(text("SELECT * FROM users where name=:name")).params(name='ed').all()

其他:

# 条件
ret = session.query(Users).filter_by(name='alex').all()
ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.between(1, 3), Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()
from sqlalchemy import and_, or_
ret = session.query(Users).filter(and_(Users.id > 3, Users.name == 'eric')).all()
ret = session.query(Users).filter(or_(Users.id < 2, Users.name == 'eric')).all()
ret = session.query(Users).filter(
    or_(
        Users.id < 2,
        and_(Users.name == 'eric', Users.id > 3),
        Users.extra != ""
    )).all()


# 通配符
ret = session.query(Users).filter(Users.name.like('e%')).all()
ret = session.query(Users).filter(~Users.name.like('e%')).all()

# 限制
ret = session.query(Users)[1:2]

# 排序
ret = session.query(Users).order_by(Users.name.desc()).all()
ret = session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all()

# 分组
from sqlalchemy.sql import func

ret = session.query(Users).group_by(Users.extra).all()
ret = session.query(
    func.max(Users.id),
    func.sum(Users.id),
    func.min(Users.id)).group_by(Users.name).all()

ret = session.query(
    func.max(Users.id),
    func.sum(Users.id),
    func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all()

# 连表

ret = session.query(Users, Favor).filter(Users.id == Favor.nid).all()

ret = session.query(Person).join(Favor).all()

ret = session.query(Person).join(Favor, isouter=True).all()


# 组合
q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union(q2).all()

q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union_all(q2).all()

猜你喜欢

转载自www.cnblogs.com/uson/p/11567222.html