zoukankan      html  css  js  c++  java
  • SQLAlchemy,python的orm框架

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

    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

    一、底层处理

    使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from sqlalchemy import create_engine
      
      
    engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5)
      
    # 执行SQL
    # cur = engine.execute(
    #     "INSERT INTO hosts (host, color_id) VALUES ('1.1.1.22', 3)"
    # )
      
    # 新插入行自增ID
    # cur.lastrowid
      
    # 执行SQL
    # cur = engine.execute(
    #     "INSERT INTO hosts (host, color_id) VALUES(%s, %s)",[('1.1.1.22', 3),('1.1.1.221', 3),]
    # )
      
      
    # 执行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()

    二、ORM功能使用

    ORM框架的作用就是把数据库表的一行记录与一个对象互相做自动转换。 正确使用ORM的前提是了解关系数据库的原理。 ORM就是把数据库表的行与相应的对象建立关联,互相转换。 由于关系数据库的多个表还可以用外键实现一对多、多对多等关联,相应地, ORM框架也可以提供两个对象之间的一对多、多对多等功能。

     1 创建表

    #coding:utf8
    import sqlalchemy
    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String
    from sqlalchemy.orm import sessionmaker
    print(sqlalchemy.__version__)
    
    
    engine = create_engine('sqlite:///dbyuan111.db', echo=True)#1 连接数据库
    
    Base = declarative_base()#2 生成一个SQLORM基类
    
    class User(Base):
        __tablename__ = 'users'
    
        id = Column(Integer, primary_key=True)
        name = Column(String)
        fullname = Column(String)
        password = Column(String)
    
        def __repr__(self):
           return "<User(name='%s', fullname='%s', password='%s')>" % (
                                self.name, self.fullname, self.password)
    
    Base.metadata.create_all(engine)  #3 创建所有表结构
    
    ed_user = User(name='xiaoyu', fullname='Xiaoyu Liu', password='123')
    # print(ed_user)
    #3 这两行触发sessionmaker类下的__call__方法,return得到 Session实例,赋给变量session,所以session可以调用Session类下的add,add_all等方法
    MySession = sessionmaker(bind=engine)
    session = MySession()
    
    # session.add(ed_user)
    # our_user = session.query(User).filter_by(name='ed').first()
    # SELECT * FROM users WHERE name="ed" LIMIT 1;
    # session.add_all([
    #     User(name='alex', fullname='Alex Li', password='456'),
    #     User(name='alex', fullname='Alex old', password='789'),
    #     User(name='peiqi', fullname='Peiqi Wu', password='sxsxsx')])
    
    # session.commit()
    
    #print(">>>",session.query(User).filter_by(name='ed').first())
    
    #print(session.query(User).all())
    
    
    #order_by前不加all()
    # for row in session.query(User).order_by(User.id):
    #      print('<<',row)
    
    
    # for row in session.query(User).filter(User.name.in_(['alex', 'wendy', 'jack'])):#这里的名字是完全匹配
    #     print(row)
    
    # for row in session.query(User).filter(~User.name.in_(['ed', 'wendy', 'jack'])):
    #     print(row)
    
    #print(session.query(User).filter(User.name == 'ed').count())
    
    #from sqlalchemy import and_, or_
    
    # for row in session.query(User).filter(and_(User.name == 'ed', User.fullname == 'Ed Jones')):
    #     print(row)
    
    # for row in session.query(User).filter(or_(User.name == 'ed', User.name == 'wendy')):
    #     print(row)
    
    单表
    单表
    # #coding:utf8
    #
    # import sqlalchemy
    # from sqlalchemy import create_engine
    # from sqlalchemy.ext.declarative import declarative_base
    # from sqlalchemy import Column, Integer, String,ForeignKey
    # from sqlalchemy.orm import sessionmaker,relationship
    #
    #
    # engine = create_engine('sqlite:///dbyuan2.db', echo=True)
    #
    # Base = declarative_base()
    # #多对多:创建第三张表
    # class Author2Book(Base):
    #     __tablename__='author2book'
    #
    #     nid=Column(Integer,primary_key=True)
    #     author_id=Column(Integer,ForeignKey("author.id"))
    #     book_id=Column(Integer,ForeignKey("book.id"))
    #
    #
    # class Publisher(Base):
    #     __tablename__ = 'publisher'
    #     #id = Column(Integer, primary_key=True)里的数据类型一定写整型(Integer)
    #     id = Column(Integer, primary_key=True)
    #     name = Column(String(20))
    #     city = Column(String(20))
    #     country = Column(String(20))
    #
    #
    #     def __str__(self):
    #         return self.name
    #
    # class Author(Base):
    #     __tablename__ = 'author'
    #     id = Column(Integer, primary_key=True)
    #     name = Column(String(20))
    #
    #     def __str__(self):
    #         return self.name
    #
    # class AuthorDetail(Base):
    #     __tablename__ = 'author_detail'
    #
    #     id = Column(Integer, primary_key=True)
    #     sex = Column(String(20),default='male')
    #     email =Column(String(20),default='123@qq.com')
    #     address = Column(String(20),default='beijing')
    #     birthday =Column(String(20))
    #     author = Column(String(20),ForeignKey('author.id'),unique=True)#一对一
    #
    # class Book(Base):
    #     __tablename__ = 'book'
    #
    #     id = Column(Integer, primary_key=True)
    #     title = Column(String(20))
    #     publisher_id = Column(String(20),ForeignKey('publisher.id'))#一对多
    #     publication_date = Column(String(20))
    #     price=Column(String(20))
    #
    #     def __str__(self):
    #         return self.title
    #
    #
    #
    #
    # Base.metadata.create_all(engine)
    #
    # Session = sessionmaker(bind=engine)
    # session = Session()
    #
    #
    # b1= Book(title='PHP',publisher_id=1,publication_date='2016-8-24',price=100)
    # b2= Book(title='python',publisher_id=3,publication_date='2017-8-24',price=210)
    # b3= Book(title='java',publisher_id=2,publication_date='2018-8-24',price=90)
    #
    # a1=Author(name='alex')
    # a2=Author(name='alvin')
    #
    # ad1=AuthorDetail(birthday='1980-2-16',author=1)
    # ad2=AuthorDetail(birthday='1990-3-16',author=1)
    #
    #
    # p1=Publisher(name='北大出版社',city='北京',country='中国')
    # p2=Publisher(name='河大出版社',city='保定',country='中国')
    # p3=Publisher(name='中国机械出版社',city='北京',country='中国')
    #
    # ab1=Author2Book(author_id=1,book_id=1)
    # ab2=Author2Book(author_id=1,book_id=2)
    # ab3=Author2Book(author_id=2,book_id=2)
    #
    #
    # session.add_all([a1,a2,ad1,ad2,b1,b2,b3,p1,p2,p3,ab1,ab2,ab3])
    # session.commit()
    
    ####################################################
    #很明显,这种建立表关系的方式不够直接和简单.
    
    
    
    
    #coding:utf8
    
    import sqlalchemy
    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String,ForeignKey
    from sqlalchemy.orm import sessionmaker,relationship
    
    
    engine = create_engine('sqlite:///dbyuan242246.db', echo=True)
    
    Base = declarative_base()
    #多对多:创建第三张表
    class Author2Book(Base):
        __tablename__='author2book'
    
        nid=Column(Integer,primary_key=True)
        author_id=Column(Integer,ForeignKey("author.id"))
        book_id=Column(Integer,ForeignKey("book.id"))
    
    
    class Publisher(Base):
        __tablename__ = 'publisher'
        #id = Column(Integer, primary_key=True)里的数据类型一定写整型(Integer)
        id = Column(Integer, primary_key=True)
        name = Column(String(20))
        city = Column(String(20))
        country = Column(String(20))
    
    
        def __str__(self):
            return self.name
    
    class Author(Base):
        __tablename__ = 'author'
        id = Column(Integer, primary_key=True)
        name = Column(String(20))
    
        book_obj_list=relationship('Book',secondary=Author2Book.__table__,backref='author_obj_list')#多对多的relationship如是写,有一个secondary
    
    
        def __str__(self):
            return self.name
    
    class AuthorDetail(Base):
        __tablename__ = 'author_detail'
    
        id = Column(Integer, primary_key=True)
        sex = Column(String(20),default='male')
        email =Column(String(20),default='123@qq.com')
        address = Column(String(20),default='beijing')
        birthday =Column(String(20))
        author = Column(String(20),ForeignKey('author.id'),unique=True)#一对一
    
    class Book(Base):
        __tablename__ = 'book'
    
        id = Column(Integer, primary_key=True)
        title = Column(String(20))
        publisher_id = Column(String(20),ForeignKey('publisher.id'))#一对多
    
        publisher_obj_list=relationship('Publisher',backref='book_obj_list')#一对多的relationship如是写
    
    
        publication_date = Column(String(20))
        price=Column(String(20))
    
    
        def __str__(self):
            return self.title
    
    
    
    
    Base.metadata.create_all(engine)
    
    Session = sessionmaker(bind=engine)
    session = Session()
    
    #publisher_id不用加上啦
    b1= Book(title='PHP',publication_date='2016-8-24',price=100)
    b2= Book(title='python',publication_date='2017-8-24',price=210)
    b3= Book(title='java',publication_date='2018-8-24',price=90)
    
    a1=Author(name='alex')
    a2=Author(name='alvin')
    
    ad1=AuthorDetail(birthday='1980-2-16',author=1)
    ad2=AuthorDetail(birthday='1990-3-16',author=2)
    
    
    p1=Publisher(name='北大出版社',city='北京',country='中国')
    p2=Publisher(name='河大出版社',city='保定',country='中国')
    p3=Publisher(name='中国机械出版社',city='北京',country='中国')
    
    # ab1=Author2Book(author_id=1,book_id=1)
    # ab2=Author2Book(author_id=1,book_id=2)
    # ab3=Author2Book(author_id=2,book_id=2)
    #第三张表就不用插入数据了
    
    #建立多对多的关系,增加关系用append:b1.author_obj_list.append([a1,a2])
    b1.author_obj_list=[a1,a2]
    b2.author_obj_list=[a1,a2]
    
    b1.publisher_obj_list=p1
    # b1.publisher_obj_list=[p1,p2,p3]这样会报错,因为一对多的关系,b1.publisher_obj_list不可能绑定多个对象,反过来可以,如下
    p1.book_obj_list=[b1,b2,b3]
    
    
    '''
    大家思考:b1.publisher_obj_list=p1与p1.book_obj_list=b1效果相同吗?
    其实是一样的,举个例子:书法协会作为一个团体招人,alex也想进入该协会,两个动作都可以完成这件事:
    书法协会作为主体把alex招了进来
    alex作为主体加入了该组织
    '''
    
    '''
    注意点:
    ret = session.query(Users).all()
      有all().first()等,ret是对象列表;没有,则是sql语句
    关联查询
      r = session.query(Book.title,Publisher.name).join(Publisher).all()
      r = session.query(Author2Book).join(Author).all()
    
    '''
    session.add_all([a1,a2,ad1,ad2,b1,b2,b3,p1,p2,p3])
    session.commit()
    
    关系表

    2 操作表

    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_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()
    
    其它
  • 相关阅读:
    灾难 BZOJ 2815
    消耗战 BZOJ 2286
    征途 BZOJ 4518
    纸箱堆叠 BZOJ 2253
    Gate Of Babylon BZOJ 1272
    std::string::npos mean
    [转]整理索引碎片,提升SQL Server速度
    笔记本win7制作wifi
    关闭linux下的使用的端口
    linux多线程
  • 原文地址:https://www.cnblogs.com/935415150wang/p/7263826.html
Copyright © 2011-2022 走看看