• SqlAlchemy基本使用


      

      sqlalchemy所依赖的模块

    import sqlalchemy
    import sqlalchemy.orm
    import sqlalchemy.ext.declarative

      

      连接数据库,利用数据库字符串构造engine, echo为True将打印所有的sql语句

    engine = sqlalchemy.create_engine("mysql+pymysql://dba_0:mimadba_0@101.200.174.172/data_secret", encoding="utf8", echo=False)
    with engine.connect() as conn:
        # 最基础的用法
        result = conn.execute("select * from tablename limit 10;")
        for item in result:
            print(item)
        # execute的几种用法,这里具体还是得参考pymysql的用法,不需要执行commit操作
        conn.execute("insert into tablename(id, url, title) values(1, 'url1', 'title1');")
        conn.execute("insert into tablename(id, url, title) values(%s, %s, %s);", 2, "url2", "title2")
        conn.execute("insert into tablename(id, url, title) values(%s, %s, %s)", (3, "url3", "title3"))
        conn.execute("insert into tablename(id, url, title) values(%s, %s, %s)", [(31, "url31", "title31"), (32, "url32", "title32")])
        # 使用事务可以进行批量提交和回滚
        trans = conn.begin()
        try:
            conn.execute("insert into tablename(id, url, title) values(%s, %s, %s)", [(4, "url4", "title4"), (5, "url5", "title5")])
            trans.commit()
        except Exception as excep:
            trans.rollback()
            raise
        trans.close()

       创建数据库和删除数据库:

    def init_db():
        """
        根据类创建数据库表
        :return: 
        """
        engine = create_engine(
            "mysql+pymysql://root:123@127.0.0.1:3306/s6?charset=utf8",
            max_overflow=0,  # 超过连接池大小外最多创建的连接
            pool_size=5,  # 连接池大小
            pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
            pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
        )
    
        Base.metadata.create_all(engine)
    
    
    def drop_db():
        """
        根据类删除数据库表
        :return: 
        """
        engine = create_engine(
            "mysql+pymysql://root:123@127.0.0.1:3306/s6?charset=utf8",
            max_overflow=0,  # 超过连接池大小外最多创建的连接
            pool_size=5,  # 连接池大小
            pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
            pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
        )
    
        Base.metadata.drop_all(engine)

      建表:首先需要生成一个BaseModel类,作为所有模型类的基类

    BaseModel = sqlalchemy.ext.declarative.declarative_base()

      

      构建数据模型User

    class User(BaseModel):
        __tablename__ = "Users"         # 表名
        __table_args__ = {
            "mysql_engine": "InnoDB",   # 表的引擎
            "mysql_charset": "utf8",    # 表的编码格式
        }
    
        # 表结构,具体更多的数据类型自行百度
        id = sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True, autoincrement=True)
        name = sqlalchemy.Column("name", sqlalchemy.String(50), nullable=False)
        age = sqlalchemy.Column("age", sqlalchemy.Integer, default=0)
    
        # 添加角色id外键,关联到表Roles的id属性
        role_id = sqlalchemy.Column("role_id", sqlalchemy.Integer, sqlalchemy.ForeignKey("Roles.id"))
    
        # 添加关系属性,关联到本实例的role_id外键属性上
        role = sqlalchemy.orm.relationship("Role", foreign_keys="User.role_id")
    
        # 添加关系属性,关联到本实例的role_id外键属性上,如果使用了这种方式,Role模型中的users可以省略
        # role = sqlalchemy.orm.relationship("Role", foreign_keys="User.role_id", backref=sqlalchemy.orm.backref("users"))

      ### 留意,ForeignKey字段,backref,relationship方法。后面是怎么用到的。relationship不添加额外字段,只是为了方便查询。

       

      构建数据模型Role:

    class Role(BaseModel):
        __tablename__ = "Roles"         # 表名
        __table_args__ = {
            "mysql_engine": "InnoDB",   # 表的引擎
            "mysql_charset": "utf8",    # 表的编码格式
        }
    
        # 表结构,具体更多的数据类型自行百度
        id = sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True)
        name = sqlalchemy.Column("name", sqlalchemy.String(50), unique=True)
    
        # 添加关系属性,关联到实例User的role_id外键属性上
        users = sqlalchemy.orm.relationship("User", foreign_keys="User.role_id")

      利用Session对象连接数据库

    DBSessinon = sqlalchemy.orm.sessionmaker(bind=engine)   # 创建会话类
    session = DBSessinon()                                  # 创建会话对象
    # 删除所有表
    BaseModel.metadata.drop_all(engine)
    # 创建所有表,如果表已经存在,则不会创建
    BaseModel.metadata.create_all(engine)

     常用查询:

    try:
        # 清空数据,不需要commit操作
        session.query(User).filter(User.id != -1).delete()
        session.query(Role).filter(Role.id != -1).delete()
        # 删除数据的另外一种形式:session.delete()
    
        # 插入数据,这里的一个实例只插入一次,第二次插入不生效
        session.add(Role(id=1, name="student"))
        session.add(Role(id=2, name="teacher"))
    
        session.commit()
    
        session.add(User(name="James", age=20, role_id=1))
        session.add(User(name="Wade", age=40, role_id=2))
    
        # 另外一种插入方法,一次插入多项
        session.add_all([
            User(name='alex1',age=30,role_id=3),
            User(name='alex2',age=32,role_id=5),
            ])
      
        user = User(name="Kobe", age=24, role_id=1)
        session.add(user)
        session.commit()
    
        # 删除数据
        session.query(User).filter(Users.id > 2).delete()
        session.commit()
    
    
        # 修改数据
        user.name = "Allen"
        session.merge(user)                         # 使用merge方法,如果存在则修改,如果不存在则插入
        session.query(User).filter(User.id == 3).update({User.name: "Allen"})         # 使用update方法
        session.query(User).filter(User.id == 4).update({User.age: User.age + 1})     # 使用update方法,自增操作
    
        # 查询数据
        roles = session.query(Role)                 # 返回全部结果
        for role in roles:
            print("Role:", role.id, role.name)
    
        users = session.query(User)                 # 返回全部结果
        for user in users:
            print("User:", user.id, user.name, user.age, user.role_id)
    
        # 其他获取数据的方式
        print("get(id):", session.query(User).get(1))                       # 返回结果集中id为1的项
        print("get[1:3]:", session.query(User)[1:3])                        # 返回结果集中的第2-3项
    
        # 其他高级查询,这里以Users表为例
        users = session.query(User).filter(User.id > 6)                     # 条件查询
        users = session.query(User).filter(User.id > 6).all()               # 条件查询,返回查询的全部数据
        user = session.query(User).filter(User.id > 6).first()              # 条件查询,返回查询数据的第一项
        users = session.query(User).filter(User.id > 6).limit(10)           # 条件查询,返回最多10条数据
        users = session.query(User).filter(User.id > 6).offset(2)           # 条件查询,从第3条数据开始返回
    
        users = session.query(User).filter(User.id > 6, User.name == "Kobe")                    # 条件查询,and操作
        users = session.query(User).filter(User.id > 6).filter(User.name == "Kobe")             # 条件查询,and操作
        users = session.query(User).filter(sqlalchemy.or_(User.id > 6, User.name == "Kobe"))    # 条件查询,or操作
        users = session.query(User).filter(User.id.in_((1, 2)))                                 # 条件查询,in操作
        users = session.query(User).filter(sqlalchemy.not_(User.name))                          # 条件查询,not操作
    
        user_count = session.query(User.id).count()                                             # 统计全部user的数量
        user_count = session.query(sqlalchemy.func.count(User.id)).scalar()                     # scalar操作返回第一行数据的第一个字段
        session.query(sqlalchemy.func.count("*")).select_from(User).scalar()                    # scalar操作返回第一行数据的第一个字段
        session.query(sqlalchemy.func.count(1)).select_from(User).scalar()                      # scalar操作返回第一行数据的第一个字段
        session.query(sqlalchemy.func.count(User.id)).filter(User.id > 0).scalar()              # filter() 中包含 User,因此不需要指定表
    
        session.query(sqlalchemy.func.sum(User.age)).scalar()                                   # 求和运算,运用scalar函数
        session.query(sqlalchemy.func.avg(User.age)).scalar()                                   # 求均值运算,运用scalar函数
        session.query(sqlalchemy.func.md5(User.name)).filter(User.id == 1).scalar()             # 运用md5函数
    
        users = session.query(sqlalchemy.distinct(User.name))               # 去重查询,根据name进行去重
        users = session.query(User).order_by(User.name)                     # 排序查询,正序查询
        users = session.query(User).order_by(User.name.desc())              # 排序查询,倒序查询
        users = session.query(User).order_by(sqlalchemy.desc(User.name))    # 排序查询,倒序查询的另外一种形式
    
        users = session.query(User.id, User.name)                           # 只查询部分属性
        users = session.query(User.name.label("user_name"))                 # 结果集的列取别名
        for user in users:
            print("label test:", user.user_name)                            # 这里使用别名
    
        users = session.query(sqlalchemy.func.count(User.name).label("count"), User.age).group_by(User.age)    # 分组查询
        for user in users:
            print("age:{0}, count:{1}".format(user.age, user.count))
    
        # 多表查询
        result = session.query(User, Role).filter(User.role_id == Role.id)
        for user, role in result:
            print("user %s's role is %s" % (user.name, role.name))
        users = session.query(User).join(Role, User.role_id == Role.id)
        for user in users:
            print("user join, name:", user.name)
    
        # 关联属性的用法
        roles = session.query(Role)
        for role in roles:
            print("role:%s users:" % role.name)
            for user in role.users:
                print("	%s" % user.name)
        users = session.query(User)
        for user in users:
            print("user %s's role is %s" % (user.name, user.role.name))
    
    except Exception as excep:
        session.rollback()
        raise
    
    session.close()

    relationship的应用:

    class Hobby(Base):
        __tablename__ = 'hobby'
        id = Column(Integer, primary_key=True)
        caption = Column(String(50), default='篮球')
    
    
    class Person(Base):
        __tablename__ = 'person'
        nid = Column(Integer, primary_key=True)
        name = Column(String(32), index=True, nullable=True)
        hobby_id = Column(Integer, ForeignKey("hobby.id"))
    
        # 与生成表结构无关,仅用于查询方便
        hobby = relationship("Hobby", backref='pers')
    # 使用relationship正向查询
    """
    v = session.query(Person).first()
    print(v.name)
    print(v.hobby.caption)
    """
    
    # 使用relationship反向查询
    """
    v = session.query(Hobby).first()
    print(v.caption)
    print(v.pers)
    """

    relationship不会产生额外的字段,他会像django ORM中的双下划线一样,可以跨表查询,backref相当于反向查。

    多对多:

      SQLAlchemy不会像django那样指定了manytomany就自动生成第三张表相关联,而是要我们手动添加第三张表:

    class Server2Group(Base):
        __tablename__ = 'server2group'
        id = Column(Integer, primary_key=True, autoincrement=True)
        server_id = Column(Integer, ForeignKey('server.id'))
        group_id = Column(Integer, ForeignKey('group.id'))
    
    
    class Group(Base):
        __tablename__ = 'group'
        id = Column(Integer, primary_key=True)
        name = Column(String(64), unique=True, nullable=False)
    
        # 与生成表结构无关,仅用于查询方便
        servers = relationship('Server', secondary='server2group', backref='groups')
    
    
    class Server(Base):
        __tablename__ = 'server'
    
        id = Column(Integer, primary_key=True, autoincrement=True)
        hostname = Column(String(64), unique=True, nullable=False)
  • 相关阅读:
    [CQOI2015]选数
    利用匈牙利算法&HopcroftKarp算法解决二分图中的最大二分匹配问题 例poj 1469 COURSES
    玩家死亡,屏幕灰白效果实现
    Bool值相加
    (转)D3D性能优化
    Flash AS3视频教程
    Accurately Profiling Direct3D API Calls (Direct3D 9)
    菲涅尔反射
    sscanf时用到郁闷问题
    如何精确测量程序运行时间(转)
  • 原文地址:https://www.cnblogs.com/jimmyhe/p/10827710.html
Copyright © 2020-2023  润新知