zoukankan      html  css  js  c++  java
  • SQLAlchemy 增删改查 一对多 多对多

    python的orm框架SQLAlchemy,有人说它没有django的models好用

    models仅仅只是配置和使用比较简单,因为他是django自带的orm,框架,也正是因为是django原生的,所以兼容性远远不如SQLAlchemy,真正算得上全面的orm框架必然是我们的SQLAlchemy ORM框架,他可以在任何使用SQL查询时使用,当然了,无论是使用任何ORM框架,都是为了放不安不熟练数据库的同学使用,话不多说,我们来看一下SQLAlchenmy如何使用.

    1.创建数据表

     1 # ORM中的数据表是什么呢?
     2 # Object Relation Mapping
     3 # Object - Table 通过 Object 去操纵数据表
     4 # 从而引出了我们的第一步创建数据表 - 创建Object
     5 # 1. 创建Object
     6 # class User(object):
     7 #     pass
     8 
     9 # 2. 让Object与数据表产生某种关系 也就是让Object与数据表格式极度相似
    10 # 导入官宣基础模型
    11 from sqlalchemy.ext.declarative import declarative_base
    12 # 实例化官宣模型 - Base 就是 ORM 模型
    13 Base = declarative_base()
    14 # 当前的这个Object继承了Base也就是代表了Object继承了ORM的模型
    15 class User(Base):  # 相当于 Django Models中的 Model
    16     # 为Table创建名称
    17     __tablename__ = "user"
    18     # 创建ID数据字段 , 那么ID是不是一个数据列呢? 也就是说创建ID字段 == 创建ID数据列
    19     from sqlalchemy import Column,Integer,String
    20     # id = Column(数据类型,索引,主键,外键,等等)
    21     # int == Integer
    22     id = Column(Integer,primary_key=True,autoincrement=True)
    23     # str == char(长度) == String(长度)
    24     name = Column(String(32),index=True)
    25 
    26 # 3.去数据库中创建数据表? or 先连接数据库?
    27 # 3.去连接数据库 创建数据引擎
    28 from sqlalchemy import create_engine
    29 # 创建的数据库引擎
    30 engine = create_engine("mysql+pymysql://root:DragonFire@127.0.0.1:3306/dragon?charset=utf8")
    31 
    32 # Base 自动检索所有继承Base的ORM 对象 并且创建所有的数据表
    33 Base.metadata.create_all(engine)

    2.增删改查操作

    2.1增加数据

    1 #insert 为数据表增加数据
     2 # insert One 增加一行数据
     3 # insert into user(name) values ("DragonFire")
     4 # 在ORM中的操作:
     5 # 1.首先导入之间做好的ORM 对象 User
     6 from my_create_table import User
     7 # 2.使用Users ORM模型创建一条数据
     8 user1 = User(name="DragonFire")
     9 # 数据已经创建完了,但是需要写入到数据库中啊,怎么写入呢?
    10 # 3.写入数据库:
    11 # 首先打开数据库会话 , 说白了就是创建了一个操纵数据库的窗口
    12 # 导入 sqlalchemy.orm 中的 sessionmaker
    13 from sqlalchemy.orm import sessionmaker
    14 # 导入之前创建好的 create_engine
    15 from my_create_table import engine
    16 # 创建 sessionmaker 会话对象,将数据库引擎 engine 交给 sessionmaker
    17 Session = sessionmaker(engine)
    18 # 打开会话对象 Session
    19 db_session = Session()
    20 # 在db_session会话中添加一条 UserORM模型创建的数据
    21 db_session.add(user1)
    22 # 使用 db_session 会话提交 , 这里的提交是指将db_session中的所有指令一次性提交
    23 db_session.commit()
    24 
    25 # 当然也你也可很任性的提交多条数据
    26 # 方法一:
    27 user2 = User(name="Dragon")
    28 user3 = User(name="Fire")
    29 db_session.add(user2)
    30 db_session.add(user3)
    31 db_session.commit()
    32 # 之前说过commit是将db_session中的所有指令一次性提交,现在的db_session中至少有两条指令user2和user3
    33 db_session.close()
    34 #关闭会话
    35 
    36 # 如果说你觉得方法一很麻烦,那么方法二一定非常非常适合你
    37 # 方法二:
    38 user_list = [
    39     User(name="Dragon1"),
    40     User(name="Dragon2"),
    41     User(name="Dragon3")
    42 ]
    43 db_session.add_all(user_list)
    44 db_session.commit()
    45 
    46 db_session.close()

    2.2查询数据

    1 # ORM操作查询数据
     2 # 有了刚才Insert增加数据的经验,那么查询之前的准备工作,就不用再重复了吧
     3 # 回想一下刚才Insert时我们的操作
     4 from my_create_table import User, engine
     5 from sqlalchemy.orm import sessionmaker
     6 
     7 Session = sessionmaker(engine)
     8 db_session = Session()
     9 
    10 # 1. select * from user 查询user表中的所有数据
    11 # 语法是这样的 使用 db_session 会话 执行User表 query(User) 取出全部数据 all()
    12 user_all_list = db_session.query(User).all()
    13 print(user_all_list)  # [<my_create_table.User object at 0x0000016D7C4BCDD8>]
    14 # 如何查看user_all_list其中的数据呢? 循环呗
    15 for i in user_all_list:
    16     print(i.id, i.name)  # ORM对象 直接使用调用属性的方法 拿出对应字段的值
    17 
    18 db_session.close()
    19 #关闭会话
    20 
    21 # 2. select * from user where id >= 20
    22 # 语法是这样的 使用 db_session 会话 执行User表 query(User) 筛选内容User.id >=20 的数据全部取出 all()
    23 user_all_list = db_session.query(User).filter(User.id >= 20).all()
    24 print(user_all_list)
    25 for i in user_all_list:
    26     print(i.id, i.name)
    27 
    28 db_session.close()
    29 #关闭会话
    30 
    31 # 3. 除了取出全部还可以只取出一条
    32 user = db_session.query(User).filter(User.id >= 20).first()
    33 print(user.id, user.name)
    34 db_session.close()
    35 #关闭会话
    36 
    37 # 4. 乌龙 之 忘了取出数据.......
    38 wulong1 = db_session.query(User).filter(User.id >= 20)
    39 print(wulong1)
    40 #SELECT user.id AS user_id, user.name AS user_name
    41 #FROM user
    42 #WHERE user.id >= %(id_1)s
    43 # Fuck我忘了取出数据了!!!!!!! 哎? wulong1给我显示了原生SQL语句,因祸得福了
    44 wulong2 = db_session.query(User)
    45 print(wulong2)
    46 #SELECT user.id AS user_id, user.name AS user_name
    47 #FROM user
    48 # Fuck我又忘了取出数据了!!!!!!! 哎? wulong2给我显示了原生SQL语句,因祸得福了
    49 db_session.close()
    50 #关闭会话

    2.3修改数据

    # ORM更新数据
    # 无论是更新还是删除,首先要做的事情,就应该是查询吧
    # 根据之前原有的经验,接下来是不是要导入ORM对象了,是不是要创建db_session会话了
    from my_create_table import User,engine
    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(engine)
    db_session = Session()
    
    # UPDATE user SET name="NBDragon" WHERE id=20 更新一条数据
    # 语法是这样的 :
    # 使用 db_session 执行User表 query(User) 筛选 User.id = 20 的数据 filter(User.id == 20)
    # 将name字段的值改为NBDragon update({"name":"NBDragon"})
    res = db_session.query(User).filter(User.id == 20).update({"name":"NBDragon"})
    print(res) # 1 res就是我们当前这句更新语句所更新的行数
    # 注意注意注意
    # 这里一定要将db_session中的执行语句进行提交,因为你这是要对数据中的数据进行操作
    # 数据库中 增 改 删 都是操作,也就是说执行以上三种操作的时候一定要commit
    db_session.commit()
    db_session.close()
    #关闭会话
    
    # 更新多条
    res = db_session.query(User).filter(User.id <= 20).update({"name":"NBDragon"})
    print(res) # 6 res就是我们当前这句更新语句所更新的行数
    db_session.commit()
    db_session.close()
    #关闭会话
    
    orm_update

    2.4删除数据

    # ORM 删除一条多条数据
    # 老规矩
    # 导入 ORM 创建会话
    from my_create_table import User,engine
    from sqlalchemy.orm import sessionmaker
    Session = sessionmaker(engine)
    db_session = Session()
    
    # DELETE FROM `user` WHERE id=20
    res = db_session.query(User).filter(User.id==20).delete()
    print(res)
    # 是删除操作吧,没错吧,那你想什么呢?commit吧
    db_session.commit()
    
    db_session.close()
    #关闭会话
    
    orm_delete

    2.5 高级查询操作

    # 高级版查询操作,厉害了哦
    #老规矩
    from my_create_table import User,engine
    from sqlalchemy.orm import sessionmaker
    
    Session = sessionmaker(engine)
    db_session = Session()
    
    # 查询数据表操作
    # and or
    from sqlalchemy.sql import and_ , or_
    ret = db_session.query(User).filter(and_(User.id > 3, User.name == 'DragonFire')).all()
    ret = db_session.query(User).filter(or_(User.id < 2, User.name == 'DragonFire')).all()
    
    # 查询所有数据
    r1 = db_session.query(User).all()
    
    # 查询数据 指定查询数据列 加入别名
    r2 = db_session.query(User.name.label('username'), User.id).first()
    print(r2.id,r2.username) # 15 NBDragon
    
    # 表达式筛选条件
    r3 = db_session.query(User).filter(User.name == "DragonFire").all()
    
    # 原生SQL筛选条件
    r4 = db_session.query(User).filter_by(name='DragonFire').all()
    r5 = db_session.query(User).filter_by(name='DragonFire').first()
    
    # 字符串匹配方式筛选条件 并使用 order_by进行排序
    r6 = db_session.query(User).filter(text("id<:value and name=:name")).params(value=224, name='DragonFire').order_by(User.id).all()
    
    #原生SQL查询
    r7 = db_session.query(User).from_statement(text("SELECT * FROM User where name=:name")).params(name='DragonFire').all()
    
    # 筛选查询列
    # query的时候我们不在使用User ORM对象,而是使用User.name来对内容进行选取
    user_list = db_session.query(User.name).all()
    print(user_list)
    for row in user_list:
        print(row.name)
    
    # 别名映射  name as nick
    user_list = db_session.query(User.name.label("nick")).all()
    print(user_list)
    for row in user_list:
        print(row.nick) # 这里要写别名了
    
    # 筛选条件格式
    user_list = db_session.query(User).filter(User.name == "DragonFire").all()
    user_list = db_session.query(User).filter(User.name == "DragonFire").first()
    user_list = db_session.query(User).filter_by(name="DragonFire").first()
    for row in user_list:
        print(row.nick)
    
    # 复杂查询
    from sqlalchemy.sql import text
    user_list = db_session.query(User).filter(text("id<:value and name=:name")).params(value=3,name="DragonFire")
    
    # 查询语句
    from sqlalchemy.sql import text
    user_list = db_session.query(User).filter(text("select * from User id<:value and name=:name")).params(value=3,name="DragonFire")
    
    # 排序 :
    user_list = db_session.query(User).order_by(User.id).all()
    user_list = db_session.query(User).order_by(User.id.desc()).all()
    for row in user_list:
        print(row.name,row.id)
    
    #其他查询条件
    """
    ret = session.query(User).filter_by(name='DragonFire').all()
    ret = session.query(User).filter(User.id > 1, User.name == 'DragonFire').all()
    ret = session.query(User).filter(User.id.between(1, 3), User.name == 'DragonFire').all() # between 大于1小于3的
    ret = session.query(User).filter(User.id.in_([1,3,4])).all() # in_([1,3,4]) 只查询id等于1,3,4的
    ret = session.query(User).filter(~User.id.in_([1,3,4])).all() # ~xxxx.in_([1,3,4]) 查询不等于1,3,4的
    ret = session.query(User).filter(User.id.in_(session.query(User.id).filter_by(name='DragonFire'))).all() 子查询
    from sqlalchemy import and_, or_
    ret = session.query(User).filter(and_(User.id > 3, User.name == 'DragonFire')).all()
    ret = session.query(User).filter(or_(User.id < 2, User.name == 'DragonFire')).all()
    ret = session.query(User).filter(
        or_(
            User.id < 2,
            and_(User.name == 'eric', User.id > 3),
            User.extra != ""
        )).all()
    # select * from User where id<2 or (name="eric" and id>3) or extra != "" 
    
    # 通配符
    ret = db_session.query(User).filter(User.name.like('e%')).all()
    ret = db_session.query(User).filter(~User.name.like('e%')).all()
    
    # 限制
    ret = db_session.query(User)[1:2]
    
    # 排序
    ret = db_session.query(User).order_by(User.name.desc()).all()
    ret = db_session.query(User).order_by(User.name.desc(), User.id.asc()).all()
    
    # 分组
    from sqlalchemy.sql import func
    
    ret = db_session.query(User).group_by(User.extra).all()
    ret = db_session.query(
        func.max(User.id),
        func.sum(User.id),
        func.min(User.id)).group_by(User.name).all()
    
    ret = db_session.query(
        func.max(User.id),
        func.sum(User.id),
        func.min(User.id)).group_by(User.name).having(func.min(User.id) >2).all()
    """
    
    # 关闭连接
    db_session.close()
    
    orm_select_more

    2.6.高级修改数据操作

    #高级版更新操作
    from my_create_table import User,engine
    from sqlalchemy.orm import sessionmaker
    
    Session = sessionmaker(engine)
    db_session = Session()
    
    #直接修改
    db_session.query(User).filter(User.id > 0).update({"name" : "099"})
    
    #在原有值基础上添加 - 1
    db_session.query(User).filter(User.id > 0).update({User.name: User.name + "099"}, synchronize_session=False)
    
    #在原有值基础上添加 - 2
    db_session.query(User).filter(User.id > 0).update({"age": User.age + 1}, synchronize_session="evaluate")
    db_session.commit()
    
    orm_update_more

     3.一对多的操作:ForeignKey

    3.1.创建数据表及关系relationship:

    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    # 这次我们要多导入一个 ForeignKey 字段了,外键关联对了
    from sqlalchemy import Column,Integer,String,ForeignKey
    # 还要从orm 中导入一个 relationship 关系映射
    from sqlalchemy.orm import relationship
    
    class ClassTable(Base):
        __tablename__="classtable"
        id = Column(Integer,primary_key=True)
        name = Column(String(32),index=True)
    
    class Student(Base):
        __tablename__="student"
        id=Column(Integer,primary_key=True)
        name = Column(String(32),index=True)
    
        # 关联字段,让class_id 与 class 的 id 进行关联,主外键关系(这里的ForeignKey一定要是表名.id不是对象名)
        class_id = Column(Integer,ForeignKey("classtable.id"))
    
        # 将student 与 classtable 创建关系 这个不是字段,只是关系,backref是反向关联的关键字
        to_class = relationship("ClassTable",backref = "stu2class")
    
    from sqlalchemy import create_engine
    engine = create_engine("mysql+pymysql://root:DragonFire@127.0.0.1:3306/dragon?charset=utf8")
    
    Base.metadata.create_all(engine)
    
    my_ForeignKey.py
    my_ForeignKey.py

     3.2.基于relationship增加数据

    from my_ForeignKey import Student, ClassTable,engine
    # 创建连接
    from sqlalchemy.orm import sessionmaker
    # 创建数据表操作对象 sessionmaker
    DB_session = sessionmaker(engine)
    db_session = DB_session()
    
    # 增加数据
    # 1.简单增加数据
    # 添加两个班级:
    # db_session.add_all([
    #     ClassTable(name="OldBoyS1"),
    #     ClassTable(name="OldBoyS2")
    # ])
    # db_session.commit()
    # 添加一个学生 DragonFire 班级是 OldBoyS1
    # 查询要添加到的班级
    # class_obj = db_session.query(ClassTable).filter(ClassTable.name == "OldBoyS1").first()
    # 创建学生
    # stu = Student(name="DragonFire",class_id = class_obj.id)
    # db_session.add(stu)
    # db_session.commit()
    
    # 2. relationship版 添加数据
    # 通过关系列 to_class 可以做到两件事
    # 第一件事 在ClassTable表中添加一条数据
    # 第二件事 在Student表中添加一条数据并将刚刚添加的ClassTable的数据id填写在Student的class_id中
    # stu_cla = Student(name="DragonFire",to_class=ClassTable(name="OldBoyS1"))
    # print(stu_cla.name,stu_cla.class_id)
    # db_session.add(stu_cla)
    # db_session.commit()
    
    # 3.relationship版 反向添加数据
    # 首先建立ClassTable数据
    class_obj = ClassTable(name="OldBoyS2")
    # 通过class_obj中的反向关联字段backref - stu2class
    # 向 Student 数据表中添加 2条数据 并将 2条数据的class_id 写成 class_obj的id
    # class_obj.stu2class = [Student(name="BMW"),Student(name="Audi")]
    # db_session.add(class_obj)
    # db_session.commit()
    
    # 关闭连接
    db_session.close()
    
    orm_ForeignKey_insert.py
    orm_ForeignKey_insert.py

     3.3.基于relationship查询数据

    from my_ForeignKey import Student, ClassTable,engine
    
    from sqlalchemy.orm import sessionmaker
    DB_session = sessionmaker(engine)
    db_session = DB_session()
    
    # 1.查询所有数据,并显示班级名称,连表查询
    student_list = db_session.query(Student).all()
    for row in student_list:
        # row.to_class.name 通过Student对象中的关系字段relationship to_class 获取关联 ClassTable中的name
        print(row.name,row.to_class.name,row.class_id)
    
    # 2.反向查询
    class_list = db_session.query(ClassTable).all()
    for row in class_list:
        for row2 in row.stu2class:
            print(row.name,row2.name)
    # row.stu2class 通过 backref 中的 stu2class 反向关联到 Student 表中根据ID获取name
    
    
    db_session.close()
    
    orm_ForeignKey_select.py
    orm_ForeignKey_select.py

     3.4.更新数据

    from my_ForeignKey import Student, ClassTable,engine
    
    from sqlalchemy.orm import sessionmaker
    DB_session = sessionmaker(engine)
    db_session = DB_session()
    
    # 更新
    class_info = db_session.query(ClassTable).filter(ClassTable.name=="OldBoyS1").first()
    db_session.query(Student).filter(Student.class_id == class_info.id).update({"name":"NBDragon"})
    db_session.commit()
    
    db_session.close()
    
    orm_ForeignKey_update
    orm_ForeignKey_update

     3.5.删除数据

    from my_ForeignKey import Student, ClassTable,engine
    
    from sqlalchemy.orm import sessionmaker
    DB_session = sessionmaker(engine)
    db_session = DB_session()
    
    # 删除
    class_info = db_session.query(ClassTable).filter(ClassTable.name=="OldBoyS1").first()
    db_session.query(Student).filter(Student.class_id == class_info.id).delete()
    db_session.commit()
    
    db_session.close()
    
    orm_ForeignKey_delete.py
    orm_ForeignKey_delete.py

     4.多对多: ManyToMany

    4.1创建表关系

    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    from sqlalchemy import Column,Integer,String,ForeignKey
    from sqlalchemy.orm import relationship
    
    class Hotel(Base):
        __tablename__="hotel"
        id=Column(Integer,primary_key=True)
        girl_id = Column(Integer,ForeignKey("girl.id"))
        boy_id = Column(Integer,ForeignKey("boy.id"))
    
    class Girl(Base):
        __tablename__="girl"
        id=Column(Integer,primary_key=True)
        name = Column(String(32),index=True)
    
        #创建关系
        boys = relationship("Boy",secondary="hotel",backref="girl2boy")
    
    
    class Boy(Base):
        __tablename__="boy"
        id=Column(Integer,primary_key=True)
        name = Column(String(32),index=True)
    
    
    from sqlalchemy import create_engine
    engine = create_engine("mysql+pymysql://root:DragonFire@127.0.0.1:3306/dragon?charset=utf8")
    
    Base.metadata.create_all(engine)
    
    my_M2M.py
    my_M2M.py

     4.2.基于relationship增加数据

    from my_M2M import Girl,Boy,Hotel,engine
    
    # 创建连接
    from sqlalchemy.orm import sessionmaker
    # 创建数据表操作对象 sessionmaker
    DB_session = sessionmaker(engine)
    db_session = DB_session()
    
    # 1.通过Boy添加Girl和Hotel数据
    boy = Boy(name="DragonFire")
    boy.girl2boy = [Girl(name="赵丽颖"),Girl(name="Angelababy")]
    db_session.add(boy)
    db_session.commit()
    
    # 2.通过Girl添加Boy和Hotel数据
    girl = Girl(name="珊珊")
    girl.boys = [Boy(name="Dragon")]
    db_session.add(girl)
    db_session.commit()
    
    orm_M2M_insert.py
    orm_M2M_insert.py

     4.3.基于relationship查询数据

    from my_M2M import Girl,Boy,Hotel,engine
    
    # 创建连接
    from sqlalchemy.orm import sessionmaker
    # 创建数据表操作对象 sessionmaker
    DB_session = sessionmaker(engine)
    db_session = DB_session()
    
    # 1.通过Boy查询约会过的所有Girl
    hotel = db_session.query(Boy).all()
    for row in hotel:
        for row2 in row.girl2boy:
            print(row.name,row2.name)
    
    # 2.通过Girl查询约会过的所有Boy
    hotel = db_session.query(Girl).all()
    for row in hotel:
        for row2 in row.boys:
            print(row.name,row2.name)
    
    orm_M2M_select.py
    orm_M2M_select.py
  • 相关阅读:
    【leetcode】1295. Find Numbers with Even Number of Digits
    【leetcode】427. Construct Quad Tree
    【leetcode】1240. Tiling a Rectangle with the Fewest Squares
    【leetcode】1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold
    【leetcode】1291. Sequential Digits
    【leetcode】1290. Convert Binary Number in a Linked List to Integer
    【leetcode】1269. Number of Ways to Stay in the Same Place After Some Steps
    【leetcode】1289. Minimum Falling Path Sum II
    【leetcode】1288. Remove Covered Intervals
    【leetcode】1287. Element Appearing More Than 25% In Sorted Array
  • 原文地址:https://www.cnblogs.com/baijinshuo/p/10380742.html
Copyright © 2011-2022 走看看