zoukankan      html  css  js  c++  java
  • SqlAlchemy ORM

    SQLAlchemy

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

    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

    使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。

    创建表

    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://user02:user02@192.168.33.35:3306/aaa?charset=utf8", max_overflow=5)
    # mysql+pymysql:固定格式
    # user02:user02:用户名及密码
    # @192.168.33.35:3306/
    # aaa:数据库名字
    # ?charset=utf8:支持utf8
    Base = declarative_base()  # 生成orm基类
    
    
    # 创建单表
    class User(Base):
        __tablename__ = 'users'  # 表名
        id = Column(Integer, primary_key=True, autoincrement=True)  # 主键自增
        name = Column(String(50), index=True, nullable=True)  # 创建索引并不能为空
        extra = Column(String(50))
    
        __table_args__ = (
            UniqueConstraint('id', 'name', name='uix_id_name'),  # 联合唯一索引
            Index('ix_id_name', 'name', 'extra'),  # 联合索引
        )
    
    
    # 一对多
    class Colour(Base):
        __tablename__ = 'colour'  # 表名
        cid = Column(Integer, primary_key=True, autoincrement=True)
        colour = Column(String(20), server_default='red', unique=True)
    
    
    class Dress(Base):
        __tablename__ = 'dress'  # 表名
        did = Column(Integer, primary_key=True)
        name = Column(String(32), index=True, nullable=True)
        colour_id = Column(Integer, ForeignKey(Colour.cid))
    
    
    # 多对多
    class Group(Base):
        __tablename__ = 'group'
        id = Column(Integer, primary_key=True)
        name = Column(String(64), unique=True, nullable=False)
    
    
    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)  # 创建表结构
    
    
    init_db()

    Foreignkey的2种写法的区别:

    是用第一种写法,必须要注意顺序,如果是用第二种,就随意了

    user_type_id = Column(Integer, ForeignKey(UserType.user_type_id))  # 使用这个写法,必须把UserType表放在前面
    user_type_id = Column(Integer, ForeignKey('user_type.user_type_id'))

    也可以在类下面加上这个方法:

    目的是在我们查询的时候,都显示的是方法,如果把该方法加入到相关类下面,返回的就是数据了

        def __repr__(self):
            tmp = '%s - %s - %s - %s' % (self.id, self.name, self.extra, self.num)
            return tmp

    删除表

    def drop_db():
        Base.metadata.drop_all(engine)

    最基本的增删改查

    add

    Session = sessionmaker(bind=engine)
    session = Session()
    # 增(单条)
    obj1 = User(name='test1', extra='test1')
    session.add(obj1)  # 增加单条
    session.commit()
    
    # ============================================
    # 增(多条)
    session.add_all([
        User(name='test3', extra='test3'),
        User(name='test4', extra='test4'),
    ])
    session.commit()

    delete

    # 删除
    session.query(User).filter(User.id > 4, User.extra == 'd').delete()
    
    session.commit()

    update

    session.query(User).filter(User.id > 4).update({User.name: 'test10'})
    session.query(User).filter(User.id > 4).update({User.extra: User.extra + "111"}, synchronize_session=False)  # 字符串拼接
    session.query(User).filter(User.id > 4).update({User.num: User.num + 1}, synchronize_session="evaluate")  # 数字相加
    session.commit()

    select

    ret = session.query(User).all()  # 已对象形式返回所有数据
    ret = session.query(User.name, User.id).all()
    ret = session.query(User).filter_by(name='a').all()
    ret = session.query(User).filter_by(name='a').first()

    进阶篇增删改查

    select

    ret = session.query(User).filter(User.id > 2, User.name == 'c').all()
    ret = session.query(User).filter(User.id.between(1, 3), User.name == 'c').all()
    ret = session.query(User).filter(User.id.in_([1, 3, 4])).all()
    ret = session.query(User).filter(~User.id.in_([1, 3, 4])).all()
    ret = session.query(User).filter(User.id.in_(session.query(User.id).filter_by(name='c'))).all()  # 嵌套查询

    and、or

    需要先导入模块

    from sqlalchemy import and_,or_
    ret = session.query(User).filter(and_(User.id > 2, User.name == 'c')).all()
    ret = session.query(User).filter(or_(User.id > 2, and_(User.name == 'c'), User.extra != '')).all()

    通配符

    ret = session.query(User).filter(User.name.like('e%')).all()  # 查询已e开始的name字段
    ret = session.query(User).filter(~User.name.like('e%')).all()

    限制

    ret = session.query(User)[1:4]  # 这个不需要all

    排序

    ret = session.query(User).order_by(User.name.desc()).all()  # 从高到低
    ret = session.query(User).order_by(User.name.desc(), User.id.asc()).all()

    groupby

    需要先导入一个模块

    from sqlalchemy.sql import func

    连表操作

    ret = session.query(Colour, Dress).filter(Colour.cid == Dress.colour_id).all()
    print(ret)
    for i in ret:
        print(i.name)
    ret = session.query(Dress).join(Colour).all()  # 默认是inner join
    ret = session.query(Dress).join(Colour, isouter=True).all()  # 默认是left join
    
    sql = session.query(Dress.name, Colour.colour).join(Colour)  # 输出sql语句
    print(sql)
    a = session.query(Dress.name, Colour.colour).join(Colour).all()
    print(a)

    组合

    q1 = session.query(User.name).filter(User.id > 4)
    q2 = session.query(Colour.colour).filter(Colour.colour == 'red')
    ret = q1.union(q2).all()  # 默认去重
    
    q1 = session.query(User.name).filter(User.id > 4)
    q2 = session.query(Colour.colour).filter(Colour.colour == 'red')
    ret = q1.union_all(q2).all()  # 不去重

    relationship

    这个功能只是优化在你写代码过程中,进一步优化

    一般情况下,relationship跟外键在一起,当用显示存在obj.col这个方式的时候,我们一般叫正向查找,当使用backref叫做反向查找

    正向查找:

    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://user02:user02@192.168.33.35:3306/aaa?charset=utf8", max_overflow=5)
    
    Base = declarative_base()  # 生成orm基类
    
    # 一对多
    class Colour(Base):
        __tablename__ = 'colour'  # 表名
        cid = Column(Integer, primary_key=True, autoincrement=True)
        colour = Column(String(20), default='red', unique=True)
    
    
    class Dress(Base):
        __tablename__ = 'dress'  # 表名
        did = Column(Integer, primary_key=True)
        name = Column(String(32), index=True, nullable=True)
        colour_id = Column(Integer, ForeignKey(Colour.cid))
        # 与生成表结构无关,仅用于查询方便
        col = relationship("Colour", backref='uuu')
    
    Session = sessionmaker(bind=engine)
    session = Session()
    ret = session.query(Dress).all()
    for obj in ret:
        # obj代指Dress的每一行数据
        # obj.col代指group对象,封装了Group里面的所有数据
        print(obj.did, obj.name, obj.col.colour, obj.col.cid)

    反向查找:

    Session = sessionmaker(bind=engine)
    session = Session()
    obj = session.query(Colour).filter(Colour.colour == 'red').first()
    print(obj.cid)
    print(obj.colour)
    print(obj.uuu)

    MySql数据库常用命令

  • 相关阅读:
    markdown 书写文档的框架
    使用snap
    如何让pandas表格直接转换为markdown表格
    我们需要怎样去写博客
    jupyter notebook 远程访问
    安装tensorflowGPU版本
    Data Science Project
    使用python处理地理数据:Geopandas
    python移植环境
    Jupyter notbook& REVEAL.JS& nbconvert 使用jupyter notebook制作slides
  • 原文地址:https://www.cnblogs.com/chen1930/p/6224676.html
Copyright © 2011-2022 走看看