zoukankan      html  css  js  c++  java
  • SQLAlchemy-ORM框架


    一、ORM 框架简介
      对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,
    关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。
    内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,
    主要实现程序对象到关系数据库数据的映射。简单的说:ORM相当于中继数据,操作数据、

    1.ORM方法论基于三个核心原则:

    简单性:以最基本的形式建模数据。
    传达性:数据库结构被任何人都能理解的语言文档化。
    精确性:基于数据模型创建正确标准化了的结构。

      面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,
    对象关系映射技术应运而生。O/R中字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,
    我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
    当开发一个应用程序的时候(不使用O/R Mapping),可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。在DAL中写了很多的方法来读取对象数据,
    改变状态对象等等任务。而这些代码写起来总是重复的。如果开你最近的程序,看看DAL代码,肯定会看到很多近似的通用的模式。我们以保存对象的方法为例,传入一个对象,
    为SqlCommand对象添加SqlParameter,把所有属性和对象对应,设置SqlCommand的CommandText属性为存储过程,然后运行SqlCommand。对于每个对象都要重复的写这些代码。  
    除此之外,还有更好的办法吗?有,引入一个O/R Mapping。实质上,一个O/R Mapping会为你生成DAL。与其自己写DAL代码,不如用O/R Mapping。用O/R Mapping保存,删除,读取对象,
    O/R Mapping负责生成SQL,你只需要关心对象就好。对象关系映射成功运用在不同的面向对象持久层产品中,

    2. 一般的ORM包括以下四部分:

    一个对持久类对象进行CRUD操作的API;
    一个语言或API用来规定与类和类属性相关的查询;
    一个规定mapping metadata的工具;
    一种技术可以让ORM的实现同事务对象一起进行dirty checking, lazy association fetching以及其他的优化操作。

    •ORM:及Object-Relational Mapping,把关系数据库的表结构映射到对象上


    二、SQLAlchemy介绍
      SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

    1.安装SQLAlchemy()

    pip install SQLAlchemy
    

     

    2.各种数据库使用SQLALchemy方法
      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...]
    

     

    3.初始化连接

    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index,CHAR ,VARCHAR
    from sqlalchemy.orm import sessionmaker, relationship
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/hjx?charset=utf8", max_overflow=5,echo=True)
    
    参数说明:
    max_overflow 设置最大连接数
    echo参数为True时,会显示每条执行的SQL语句,可以关闭,
    "mysql+pymysql://root:@127.0.0.1:3306/sqlalchemy?charset=utf8"  设定数据库地址、用户名、密码、端口、数据库名称和字符编码
    create_engine()返回一个Engine的实例,并且它表示通过数据库语法处理细节的核心接口,在这种情况下,数据库语法将会被解释成python的类方法。
    

     

    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/hjx?charset=utf8", max_overflow=5,echo=True)
    
    #执行SQL---增
    cur = engine.execute(
        "INSERT INTO equipment (equ_id, equ_sn,supplier,cname,location,ipadd) VALUES ('CQ66','CQMT206','重庆银河','12m³环境箱2','一楼','10.127.1.123')"
        )
    
    #新插入行自增ID
    cur.lastrowid
    
    #插入多条记录
    cur = engine.execute(
        "INSERT INTO host (ip, name) VALUES(%s, %s)",[('1.1.1.22', 'sever1'),('1.1.1.221', 'server2'),]
        )
    
    
    执行SQL
    cur = engine.execute(
        "INSERT INTO hosts (host, color_id) VALUES (%(host)s, %(color_id)s)",
        host='1.1.1.99', color_id=3
        )
    
    #执行SQL---查
    cur = engine.execute('select * from hosts')
    
    #获取第一行数据
    cur.fetchone()
    #获取第n行数据
    cur.fetchmany(3)
    #获取所有数据
    cur.fetchall()
    sqlalchemy执行原生SQL

    三、ORM功能使用
    使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。根据类创建对象,对象转换成SQL,执行SQL。

    1.创建表
    a.通过sql语句来创建表:

    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/hjx?charset=utf8", max_overflow=5,echo=True)
    
    sql = "create table student(id int not null primary key,name varchar(50),age int,address varchar(100));"
    
    cursor = engine.execute(sql)
    

      

    b.通过ORM创建表

    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
    
    engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", 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('id', 'name', name='uix_id_name'),
            Index('ix_id_name', 'name', 'extra'),
        )
    
    
    # 一对多
    class Favor(Base):
        __tablename__ = 'favor'
        nid = Column(Integer, primary_key=True)
        caption = Column(String(50), default='red', unique=True)
    
    
    class Person(Base):
        __tablename__ = 'person'
        nid = Column(Integer, primary_key=True)
        name = Column(String(32), index=True, nullable=True)
        favor_id = Column(Integer, ForeignKey("favor.nid"))
    
    
    # 多对多
    class Group(Base):
        __tablename__ = 'group'
        id = Column(Integer, primary_key=True)
        name = Column(String(64), unique=True, nullable=False)
        port = Column(Integer, default=22)
    
    
    class Server(Base):
        __tablename__ = 'server'
    
        id = Column(Integer, primary_key=True, autoincrement=True)
        hostname = Column(String(64), unique=True, nullable=False)
    
    
    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'))
    
    
    def init_db():
        Base.metadata.create_all(engine)
    
    def drop_db():
        Base.metadata.drop_all(engine)
    
    init_db()   #创建表
    drop_db()   #删除表
    

     

    2.操作表

    #导入相关模块
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index,CHAR ,VARCHAR
    from sqlalchemy.orm import sessionmaker, relationship
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/test?charset=utf8", max_overflow=5)
    Base = declarative_base()
    
    #创建数据表 type
    class Type(Base):
        __tablename__ = 'type'
        tid = Column(Integer,primary_key=True,autoincrement=True)
        tname = Column(VARCHAR(25),nullable=False,unique=True)
    
    #创建数据表 host
    class Host(Base):
        __tablename__ = 'host'
        hid = Column(Integer,primary_key=True)
        hostname = Column(String(25),nullable=None)
        ipadd = Column(String(32),unique=True)
        type_id = Column(Integer,ForeignKey('type.tid'))
    
        # 增加relationship不会增加到数据表里,只是在ORM里表示一种关系,参数backref表示反向查询
        host_type = relationship('Type',backref = 'fff')
    
        __table_args__ = (
            Index('Idx_hostname','hostname'),    #创建普通索引,索引名称必须写在前面
        )
    
    #创建数据表 user
    class User(Base):
        __tablename__ = 'user'
        uid = Column(Integer,primary_key=True,autoincrement=True)
        uname = Column(VARCHAR(25),nullable=False)
        host_id = Column(Integer,ForeignKey('host.hid'))
    
        __table_args__ = (
            UniqueConstraint('uname','host_id',name='uix_uname_host_id'),   #创建联合唯一索引
        )
    
    
    Base.metadata.create_all(engine)   #创建数据表
    Base.metadata.drop_all(engine)    #删除数据表
    
    #创建session会话
    说到数据库,就离不开Session。Session的主要目的是建立与数据库的会话,它维护你加载和关联的所有数据库对象。它是数据库查询(Query)的一个入口。
    在Sqlalchemy中,数据库的查询操作是通过Query对象来实现的。而Session提供了创建Query对象的接口。
    Query对象返回的结果是一组同一映射(Identity Map)对象组成的集合。事实上,集合中的一个对象,对应于数据库表中的一行(即一条记录)。所谓同一映射,
    是指每个对象有一个唯一的ID。如果两个对象(的引用)ID相同,则认为它们对应的是相同的对象。
    要完成数据库查询,就需要建立与数据库的连接。这就需要用到Engine对象。一个Engine可能是关联一个Session对象,也可能关联一个数据库表。
    当然Session最重要的功能还是实现原子操作。
    
    DBsession = sessionmaker(bind=engine)
    session = DBsession()
    
    
    #插入数据
    type1 = Type(tname='HP')
    type2 = Type(tname='IBM')
    type3 = Type(tname='Dell')
    type4 = Type(tname='联想')
    
    type_lst = [type1,type2,type3,type4]
    for i in type_lst:
        session.add(i)
    session.commit()
    
    host1 = Host(hostname='linux1',ipadd='10.127.55.1',type_id=1)
    host2 = Host(hostname='linux2',ipadd='10.127.55.2',type_id=2)
    host3 = Host(hostname='webserver',ipadd='10.127.55.3',type_id=3)
    host4 = Host(hostname='mysqlserver',ipadd='10.127.55.4',type_id=2)
    host5 = Host(hostname='windows server 2008',ipadd='10.127.55.5',type_id=4)
    
    host_lst = [host1,host2,host3,host4,host5]
    ret = session.add_all(host_lst)
    session.commit()
    
    User1 = User(uname='felix',host_id=1)
    User2 = User(uname='allan',host_id=2)
    User3 = User(uname='skye',host_id=3)
    User4 = User(uname='luke',host_id=4)
    User5 = User(uname='afred',host_id=5)
    
    user_lst = [User1,User2,User3,User4,User5]
    for i in user_lst:
        session.add(i)
    session.commit()
    创建增删改查数据表和插入数据
    #导入相关模块
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index,CHAR ,VARCHAR
    from sqlalchemy.orm import sessionmaker, relationship
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/test?charset=utf8", max_overflow=5)
    Base = declarative_base()
    
    #创建数据表 type
    class Type(Base):
        __tablename__ = 'type'
        tid = Column(Integer,primary_key=True,autoincrement=True)
        tname = Column(VARCHAR(25),nullable=False,unique=True)
    
    #创建数据表 host
    class Host(Base):
        __tablename__ = 'host'
        hid = Column(Integer,primary_key=True)
        hostname = Column(String(25),nullable=None)
        ipadd = Column(String(32),unique=True)
        type_id = Column(Integer,ForeignKey('type.tid'))
    
        # 增加relationship不会增加到数据表里,只是在ORM里表示一种关系,参数backref表示反向查询
        host_type = relationship('Type',backref = 'fff')
    
        __table_args__ = (
            Index('Idx_hostname','hostname'),    #创建普通索引,索引名称必须写在前面
        )
    
    #创建数据表 user
    class User(Base):
        __tablename__ = 'user'
        uid = Column(Integer,primary_key=True,autoincrement=True)
        uname = Column(VARCHAR(25),nullable=False)
        host_id = Column(Integer,ForeignKey('host.hid'))
    
        __table_args__ = (
            UniqueConstraint('uname','host_id',name='uix_uname_host_id'),   #创建联合唯一索引
        )
    
    
    Base.metadata.create_all(engine)   #创建数据表
    Base.metadata.drop_all(engine)    #删除数据表
    
    #创建session会话
    说到数据库,就离不开Session。Session的主要目的是建立与数据库的会话,它维护你加载和关联的所有数据库对象。它是数据库查询(Query)的一个入口。
    在Sqlalchemy中,数据库的查询操作是通过Query对象来实现的。而Session提供了创建Query对象的接口。
    Query对象返回的结果是一组同一映射(Identity Map)对象组成的集合。事实上,集合中的一个对象,对应于数据库表中的一行(即一条记录)。所谓同一映射,
    是指每个对象有一个唯一的ID。如果两个对象(的引用)ID相同,则认为它们对应的是相同的对象。
    要完成数据库查询,就需要建立与数据库的连接。这就需要用到Engine对象。一个Engine可能是关联一个Session对象,也可能关联一个数据库表。
    当然Session最重要的功能还是实现原子操作。
    
    DBsession = sessionmaker(bind=engine)
    session = DBsession()
    创建增删改查数据表

    (1)增

    session.add()    增加单条记录
    session.add_all()    增加多个记录
    

      

    type1 = Type(tname='HP')
    type2 = Type(tname='IBM')
    type3 = Type(tname='Dell')
    type4 = Type(tname='联想')
    
    type_lst = [type1,type2,type3,type4]
    for i in type_lst:
        session.add(i)
    session.commit()
    
    host1 = Host(hostname='linux1',ipadd='10.127.55.1',type_id=1)
    host2 = Host(hostname='linux2',ipadd='10.127.55.2',type_id=2)
    host3 = Host(hostname='webserver',ipadd='10.127.55.3',type_id=3)
    host4 = Host(hostname='mysqlserver',ipadd='10.127.55.4',type_id=2)
    host5 = Host(hostname='windows server 2008',ipadd='10.127.55.5',type_id=4)
    
    host_lst = [host1,host2,host3,host4,host5]
    ret = session.add_all(host_lst)
    session.commit()
    
    User1 = User(uname='felix',host_id=1)
    User2 = User(uname='allan',host_id=2)
    User3 = User(uname='skye',host_id=3)
    User4 = User(uname='luke',host_id=4)
    User5 = User(uname='afred',host_id=5)
    
    user_lst = [User1,User2,User3,User4,User5]
    for i in user_lst:
        session.add(i)
    session.commit()
    增加数据

    (2)删

    ret = session.query(Host).filter(Host.hid == 2 ).delete()
    print(ret)
    session.commit()
    执行结果
    1
    

      

    (3)改

    session.query(Host).filter(Host.hid > 4 ).update({'hostname':'TestServer'})
    session.commit()
    
    session.query(Host).filter(Host.hid > 4).update({Host.hostname:Host.hostname + '001'}, synchronize_session=False)
    session.commit()
    
    session.query(Host).filter(Host.hid == 4).update( {'hostname': Host.hostname + '002'}, synchronize_session="fetch")
    # #指定synchronize_session=False也可以
    session.commit()
    
    ret = session.query(Host).filter(Host.hid > 4).all()
    print(ret[0].hid,ret[0].hostname,ret[0].type_id)
    ret[0].hostname = 'TestServer'
    session.commit()

    (4)查

    • one() 返回且仅返回一个查询结果。当结果的数量不足一个或者多于一个时会报错。
    • first() 返回至多一个结果,而且以单项形式,而不是只有一个元素的tuple形式返回这个结果.
    • all()  返回多个结果,组成一个列表

    a.查询表里的所有数据,不带任何条件查询

    #查询所有结果
    ret = session.query(Host).all()
    for i in ret:
        print(i.hid,i.hostname,i.type_id)
    
    执行结果
    1 linux1 1
    2 linux2 2
    3 webserver 3
    4 mysqlserver 2
    5 windows server 2008 4
    
    注意:如果想知道SQLAlchemy生成的SQL语句则
    
    ret = session.query(Host)
    print(ret)
    执行结果:
    
    SELECT host.hid AS host_hid, host.hostname AS host_hostname, host.ipadd AS host_ipadd, host.type_id AS host_type_id FROM host
    

      

    b.带条件查询 

    • filter() 可以像写 sql 的 where 条件那样写 > < 等条件,但引用列名时,需要通过 类名.属性名 的方式。
    • filter_by() 可以使用 python 的正常参数传递方法传递条件,指定列名时,不需要额外指定类名。参数名对应名类中的属性名,但不能使用 > < 等条件。

      当使用filter的时候条件之间是使用“==",fitler_by使用的是"="。
      filter不支持组合查询,只能连续调用filter来变相实现。而filter_by的参数是**kwargs,直接支持组合查询。

    # 带条件查询
    ret = session.query(Host).filter(Host.hid > 3).all()
    for i in ret:
        print(i.hid,i.hostname,i.type_id)
    
    执行结果
    4 mysqlserver 2
    5 windows server 2008 4
    
    # 带条件查询某一列 filter
    ret = session.query(Host.hostname).filter(Host.hid == 5).all()
    for i in ret:
        print(i.hostname)
    执行结果
    windows server 2008
    
    #带条件查询某一列 filter_by   all()查询所有满足条件的
    ret = session.query(Host).filter_by(hid = 5).all()
    for i in ret:
        print(i.hid,i.hostname,i.type_id)
    执行结果
    5 windows server 2008 4
    
    
    #带条件查询某一列 filter_by   first()满足条件的第一个
    ret = session.query(Host).filter_by(hid = 1).first()
    print(ret.hid,ret.hostname,ret.type_id)
    执行结果
    1 linux1 1
    
    
    #等于条件查询
    ret = session.query(Host).filter_by(hostname='mysqlserver').all()
    print(ret[0].hid,ret[0].hostname)
    执行结果
    4 mysqlserver
    
    #使用原生SQL语句带条件查询
    ret = session.query(Host).from_statement("SELECT * FROM host where hostname=:hostname").params(hostname='mysqlserver').all()
    print(ret[0].hid,ret[0].hostname,ret[0].ipadd,ret[0].type_id)
    执行结果
    4 mysqlserver 10.127.55.4 2
    

    c.and、or查询,SQLAlchemy默认使用and条件,如果需要使用or查询时,需要导入or_ ,也可以导入and_进行and查询。from sqlalchemy import and_, or_

     

    #and查询
    from sqlalchemy import and_, or_
    ret = session.query(Host).filter(and_(Host.hid > 1, Host.hostname == 'webserver')).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    [<__main__.Host object at 0x000000000AFA57B8>]
    3 webserver
    
    #or条件查询
    ret = session.query(Host).filter(or_(Host.hid < 2, Host.hostname == 'webserver')).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    [<__main__.Host object at 0x000000000AFA5128>, <__main__.Host object at 0x000000000AFA5978>]
    1 linux1
    3 webserver
    
    #and or 混合查询
    ret = session.query(Host).filter(
        or_(
            Host.hid < 2,
            and_(Host.hostname == 'webserver', Host.hid > 2),
            Host.hostname == "windows server 2008"
        )).all()
    
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    [<__main__.Host object at 0x000000000AFA3208>, <__main__.Host object at 0x000000000AFA3A58>, <__main__.Host object at 0x000000000AFA39E8>]
    1 linux1
    3 webserver
    5 windows server 2008
    

      

    d.between...and...查询

    #between...and...
    ret = session.query(Host).filter(Host.hid.between(1, 3)).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    # 执行结果
    1 linux1
    2 linux2
    3 webserver
    

      

    e.in和not in 查询,not in方法为 在 类名.字段.in_  前加 ~  取反(波浪线)

    #in
    ret = session.query(Host).filter(Host.hid.in_([1,3,4])).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    [<__main__.Host object at 0x000000000AFA9748>, <__main__.Host object at 0x000000000AFA96D8>, <__main__.Host object at 0x000000000AFA97B8>]
    1 linux1
    3 webserver
    4 mysqlserver
    
    #not in
    ret = session.query(Host).filter(~Host.hid.in_([1,3,4])).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    
    [<__main__.Host object at 0x000000000AFB77B8>, <__main__.Host object at 0x000000000AFB7748>]
    2 linux2
    5 windows server 2008
    
    #带子查询
    ret = session.query(Host).filter(Host.hid.in_(session.query(Host.hid).filter(Host.hid > 2))).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    [<__main__.Host object at 0x000000000B05A6D8>, <__main__.Host object at 0x000000000B05A2B0>, <__main__.Host object at 0x000000000B05A780>]
    3 webserver
    4 mysqlserver
    5 windows server 2008
    

      

    f.通配符 like

    # 通配符 like
    ret = session.query(Host).filter(Host.hostname.like('w%')).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    ret = session.query(Host).filter(~Host.hostname.like('%server')).all()
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    
    [<__main__.Host object at 0x000000000AFA3128>, <__main__.Host object at 0x000000000AFA3588>]
    3 webserver
    5 windows server 2008
    [<__main__.Host object at 0x000000000AFA37F0>, <__main__.Host object at 0x000000000AFA3860>, <__main__.Host object at 0x000000000AFA3588>]
    1 linux1
    2 linux2
    5 windows server 2008
    

      

    g.限制查询的结果数目 limit

    # 限制 类似limit
    ret = session.query(Host)[0:3]  #左闭右开
    print(ret)
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    [<__main__.Host object at 0x000000000AFA56A0>, <__main__.Host object at 0x000000000AFA5630>, <__main__.Host object at 0x000000000AFA5710>]
    1 linux1
    2 linux2
    3 webserver
    

      

    h.排序

    # 排序
    #单字段排序
    ret = session.query(Host).order_by(Host.hostname.desc()).all()
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    5 windows server 2008
    3 webserver
    4 mysqlserver
    2 linux2
    1 linux1
    
    #多字段排序
    ret = session.query(Host).order_by(Host.hostname.desc(), Host.hid.asc()).all()
    for i in ret:
        print(i.hid,i.hostname)
    执行结果
    5 windows server 2008
    3 webserver
    4 mysqlserver
    2 linux2
    1 linux1
    

      

    i.统计 count

    #统计count
    ret = session.query(Host).filter(Host.type_id == 2).count()
    print(ret)
    执行结果
    2
    

      

    j.分组加聚合函数,分组后having。使用聚合需要导入func模块

      from sqlalchemy.sql import func

    # 分组后count
    from sqlalchemy.sql import func
    ret = session.query(Host.type_id,func.count(Host.hid)).group_by(Host.type_id).all()
    print(ret)
    for i in ret:
        print(i)
    执行结果:
    [(1, 1), (2, 2), (3, 1), (4, 1)]
    (1, 1)
    (2, 2)
    (3, 1)
    (4, 1)
    
    # 分组-summaxmin
    ret = session.query(Host.type_id,
        func.max(Host.hid),
        func.sum(Host.hid),
        func.min(Host.hid)).group_by(Host.type_id).all()
    print(ret)
    for i in ret:
        print(i)
    执行结果
    [(1, 1, Decimal('1'), 1), (2, 4, Decimal('6'), 2), (3, 5, Decimal('5'), 5), (4, 3, Decimal('3'), 3)]
    (1, 1, Decimal('1'), 1)
    (2, 4, Decimal('6'), 2)
    (3, 5, Decimal('5'), 5)
    (4, 3, Decimal('3'), 3)
    
    #分组后 having
    ret = session.query(
        Host.type_id,
        func.max(Host.hid),
        func.sum(Host.hid),
        func.min(Host.hid)).group_by(Host.type_id).having(Host.type_id > 3).all()
    print(ret)
    for i in ret:
        print(i)
    执行结果
    [(4, 3, Decimal('3'), 3)]
    (4, 3, Decimal('3'), 3)
    

      

    k.连表查询

     不使用relationship进行连表查询

    # 连表 默认使用inner join
    #不使用join
    ret = session.query(Host, Type).filter(Host.type_id == Type.tid).all()
    for i in ret:
        print(i[0].hostname,i[0].ipadd,i[1].tid,i[1].tname)
    执行结果
    linux1 10.127.55.1 1 HP
    linux2 10.127.55.2 2 IBM
    webserver 10.127.55.3 4 联想
    mysqlserver 10.127.55.4 2 IBM
    windows server 2008 10.127.55.5 3 Dell
    
    #使用join,默认方法为inner join,在join里增加isouter=True参数,则使用left join
    ret = session.query(Host,Type).join(Type,isouter=True).all()
    ret = session.query(Host,Type).join(Type).all()
    print(ret)
    for i in ret:
        print(i[0].hostname,i[0].ipadd,i[0].type_id,i[1].tname)
    执行结果
    linux1 10.127.55.1 1 HP
    linux2 10.127.55.2 2 IBM
    webserver 10.127.55.3 4 联想
    mysqlserver 10.127.55.4 2 IBM
    windows server 2008 10.127.55.5 2 IBM
    
    ret = session.query(Host.hostname,Type.tname).join(Type).all()
    print(ret)
    for i in ret:
        print(i[0],i[1])
        print(i.hostname,i.tname)
    执行结果
    [('linux1', 'HP'), ('linux2', 'IBM'), ('webserver', '联想'), ('mysqlserver', 'IBM'), ('windows server 2008', 'IBM')]
    linux1 HP
    linux1 HP
    linux2 IBM
    linux2 IBM
    webserver 联想
    webserver 联想
    mysqlserver IBM
    mysqlserver IBM
    windows server 2008 IBM
    windows server 2008 IBM
    

      

      使用relationship参数进行连表查询,在创建表(类)且与在增加外键的下面增加 

      字段名 = relationship('类名称',backref='关系名称')   #增加backref参数可进行反向查询。

    #relationship 正向查询
    
    class Host(Base):
        __tablename__ = 'host'
        hid = Column(Integer,primary_key=True)
        hostname = Column(String(25),nullable=None)
        ipadd = Column(String(32),unique=True)
        type_id = Column(Integer,ForeignKey('type.tid'))
    
        # 增加relationship不会增加到数据表里,只是在ORM里表示一种关系,参数backref表示反向查询
        host_type = relationship('Type',backref = 'fff')
    
        __table_args__ = (
            Index('Idx_hostname','hostname'),    #创建普通索引,索引名称必须写在前面
        )
    
    host_type不会增加此字段进数据表,只是在ORM里表名两个表的关系,只能加在有外键ForeignKey的地方
    
    
    #查询每台服务器的名称和类型
    ret = session.query(Host).all()
    for i in ret:
        print(i.hid,i.hostname,i.ipadd,i.host_type.tname)
    
    执行结果
    1 linux1 10.127.55.1 HP
    2 linux2 10.127.55.2 IBM
    3 webserver 10.127.55.3 Dell
    4 mysqlserver 10.127.55.4 IBM
    5 windows server 2008 10.127.55.5 联想
    
    
    #relationship 反向查询,需要加backref='名称'参数
    #查询每一种类型所有的host
    #不加relationship且不加backref='fff'参数
    type_lst = session.query(Type)
    for i in type_lst:
        print(i.tid,i.tname,session.query(Host).filter(Host.type_id == i.tid).all())
    执行结果
    3 Dell [<__main__.Host object at 0x000000000AFD19B0>]
    1 HP [<__main__.Host object at 0x000000000AFD1B38>]
    2 IBM [<__main__.Host object at 0x000000000AFD1C50>, <__main__.Host object at 0x000000000AFD1CC0>]
    4 联想 [<__main__.Host object at 0x000000000AFD1D30>]
    
    #加relationship参数且加入 backref='fff'参数,fff为名称,即反向查询
    type_lst = session.query(Type).all()
    for i in type_lst:
        print(i.tid,i.tname,i.fff)
    
    执行结果
    3 Dell [<__main__.Host object at 0x000000000AFE6160>]
    1 HP [<__main__.Host object at 0x000000000AFE6208>]
    2 IBM [<__main__.Host object at 0x000000000AFE62B0>, <__main__.Host object at 0x000000000AFE6320>]
    4 联想 [<__main__.Host object at 0x000000000AFE6390>]
    
    #说明 每一种类型可能有一个或多个主机,因此print(i.fff)就表示主机的对象,因此可以使用两层for循环取到主机信息
    
    type_lst = session.query(Type).all()
    for i in type_lst:
        for j in i.fff:
            print(i.tid, i.tname, j.hostname)
    执行结果:
    3 Dell webserver
    1 HP linux1
    2 IBM linux2
    2 IBM mysqlserver
    4 联想 windows server 2008
    

      

    l.组合 union

    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()
    

      

  • 相关阅读:
    左旋一个字符串和手摇反转法
    LCS
    游戏服务器学习_1
    面试题_带答案_2
    面试题_带答案
    安卓_13
    安卓_12activity
    安卓_12
    多盟_1
    安卓没删干净导致报错
  • 原文地址:https://www.cnblogs.com/Felix-DoubleKing/p/10169368.html
Copyright © 2011-2022 走看看