• Python 操作mysql数据库之 SQLAlchemy 案例详解


     
    前言:
    1.         字段声明类型中,最右边的是数据库中对应的字段,我们依然可以使用,其左边的的 SQLAchemy 则是其自身封装的自定义类型。
    2.         本篇不会讲太多的理论知识,因为这个实用性更强,所以通篇全部都是案例,每个案例都会输出对应的 sql , 这样你也能更清晰的明白自己写出的代码最终都转化成什么样的 sql 了。
    3.         本篇的最后一个案例是 upsert “存在则更新,不存在则插入”的高级用法。
    4.     本篇中的所有案例都亲测可用
     
    案例一: 创建一个自定义类
     
    数据库结构
    CREATE TABLE `student` (
      `id` int(2) NOT NULL AUTO_INCREMENT,
      `name` char(20) NOT NULL,
      `code` char(64) NOT NULL,
      `sex` char(4) NOT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
    

      

    数据库中的值
    Id   name  code  sex
    ------------------------------------ 
    1    Bob    AU    dddd
    2    Bob    BR    girl
    3    Hua    CA    boy
    4    Lan    CN    girl
    5    Hua    RU    girl
    6    Smith  US    boy
    7    Bob    AU    boy
    8    Smith  BM    girl
    9    Hub    BU    boy
    10    Hip   HK    boy

    ps: 下面的例子全部是依据这

    创建自定义类,后面的所有操作的 session,都根据此案例的  session 来操作的。

    from sqlalchemy import create_engine, Column, INT, VARCHAR
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
    
    
      
    # 创建基类,返回一个定制的metaclass 类
    Base = declarative_base()
     
     
    # 自定义类
    class Student(Base):
        # 表名
        __tablename__ = 'student'
        # 字段映射
        id = Column('id', INT, primary_key=True)
        name = Column('name', VARCHAR)
        code = Column('code', VARCHAR)
        sex = Column('sex', VARCHAR)
     
     
        def to_dict(self):
            """
            将查询的结果转化为字典类型
            Student 对象的内容如下 {'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x10174c898>, 'sex': 'nan', 'name': 'ygh', 'code': 'AU', 'school': 'hua'}
            获取其值剔除 "_sa_instance_state 即可。但不能在self.__dict__上直接删除”_sa_instance_state” 这个值是公用的。
            :return:
            """
            return {k: v for k, v in self.__dict__.items() if k != "_sa_instance_state”}
    
    # 创建引擎 , echo=True ,表示需要开启 sql 打印,调试的以后特别好用
    engine =create_engine("mysql+mysqldb://root:123qwe@192.168.1.254:3306/yinguohai", pool_size=2, max_overflow=0, echo=True
    # 创建会话对象,用于操作数据库
    Session = sessionmaker(bind=engine)
    session = Session()
     
     
    案例二: 全部查询
    result = session.query(Student).all()
    for i in result:
        # i是一个Student对象,所以可以使用其 to_dict() 去格式化其对象的值
        if isinstance(i, Student):
            print(i.to_dict())
    
    -------------------------结果-------------------------
    {'sex': 'dddd', 'name': 'Bob', 'id': 1, 'code': 'AU'}
    {'sex': 'girl', 'name': 'Bob', 'id': 2, 'code': 'BR'}
    {'sex': 'boy', 'name': 'Hua', 'id': 3, 'code': 'CA'}
    {'sex': 'girl', 'name': 'Lan', 'id': 4, 'code': 'CN'}
    {'sex': 'girl', 'name': 'Hua', 'id': 5, 'code': 'RU'}
    {'sex': 'boy', 'name': 'Smith', 'id': 6, 'code': 'US'}
    {'sex': 'boy', 'name': 'Bob', 'id': 7, 'code': 'AU'}
    {'sex': 'girl', 'name': 'Smith', 'id': 8, 'code': 'BM'}
    {'sex': 'boy', 'name': 'Hub', 'id': 9, 'code': 'BU'}
    {'sex': 'boy', 'name': 'Hip', 'id': 10, 'code': 'HK'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    

      


     
    案例三: 部分字段查询
    result = session.query(Student.id, Student.name).all()
    for i in result:
        # 此时返回的是一个tuple ,而不是一个Student对象
        print(i)
    -------------------------结果-------------------------
    (1, 'Bob')
    (2, 'Bob')
    (3, 'Hua')
    (4, 'Lan')
    (5, 'Hua')
    (6, 'Smith')
    (7, 'Bob')
    (8, 'Smith')
    (9, 'Hub')
    (10, 'Hip')
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name
    FROM
        student
    

      

    案例四:多条件查询, or_ , and_
     
    或, or_
    result = session.query(Student).filter(or_(Student.name == "Bob", Student.sex != "aa")).first()
    print(result.to_dict())
    -------------------------结果-------------------------
    {'sex': 'dddd', 'name': 'Bob', 'id': 1, 'code': 'AU'}

    对应Sql:

    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    WHERE
        student.NAME = % s
        OR student.sex != % s ( 'Bob', 'aa', 1 )
     
    且,and_
    result = session.query(Student).filter(and_(Student.name == "Bob" , Student.sex != "aa")).first()
    print(result.to_dict())
    -------------------------结果-------------------------
    {'sex': 'dddd', 'name': 'Bob', 'id': 1, 'code': 'AU'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    WHERE
        student.NAME = % s
        AND student.sex != % s
        LIMIT % s ( 'Bob', 'aa', 1 )
     
    案例五:模糊查询,like 
     
    result = session.query(Student).filter(Student.sex.like('%bo%')).first()
    print(result.to_dict())
    -------------------------结果-------------------------
    {'sex': 'dddd', 'name': 'Bob', 'id': 1, 'code': 'AU'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    WHERE
        student.sex LIKE % s
        LIMIT %s  ('%bo%', 1)
     
    案例六:in_  , 范围查询
     
    result = session.query(Student).filter(Student.name.in_(["Bob", "Smith"])).all()
    for i in result:
        print(i.to_dict())
    -------------------------结果-------------------------
    {'code': 'AU', 'id': 1, 'name': 'Bob', 'sex': 'dddd'}
    {'code': 'BR', 'id': 2, 'name': 'Bob', 'sex': 'girl'}
    {'code': 'US', 'id': 6, 'name': 'Smith', 'sex': 'boy'}
    {'code': 'AU', 'id': 7, 'name': 'Bob', 'sex': 'boy'}
    {'code': 'BM', 'id': 8, 'name': 'Smith', 'sex': 'girl'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    WHERE
        student.NAME IN (% s, % s ) ( 'Bob', 'Smith' )
     
     
    案例七:排序,asc() , desc()
     
    #result = session.query(Student).order_by(Student.id.desc()).all()
    result = session.query(Student).order_by(Student.id.asc()).all()
    for i in result:
        print(i.to_dict())
    -------------------------结果-------------------------
    {'sex': 'dddd', 'name': 'Bob', 'id': 1, 'code': 'AU'}
    {'sex': 'girl', 'name': 'Bob', 'id': 2, 'code': 'BR'}
    {'sex': 'boy', 'name': 'Hua', 'id': 3, 'code': 'CA'}
    {'sex': 'girl', 'name': 'Lan', 'id': 4, 'code': 'CN'}
    {'sex': 'girl', 'name': 'Hua', 'id': 5, 'code': 'RU'}
    {'sex': 'boy', 'name': 'Smith', 'id': 6, 'code': 'US'}
    {'sex': 'boy', 'name': 'Bob', 'id': 7, 'code': 'AU'}
    {'sex': 'girl', 'name': 'Smith', 'id': 8, 'code': 'BM'}
    {'sex': 'boy', 'name': 'Hub', 'id': 9, 'code': 'BU'}
    {'sex': 'boy', 'name': 'Hip', 'id': 10, 'code': 'HK'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    ORDER BY
        student.id ASC
     
    案例八:限制,limit , slice
     
    方式一 ,limit( position )
     
    result = session.query(Student).limit(2).all()
    for i in result:
        print(i.to_dict()) 
    -------------------------结果-------------------------
    {'sex': 'dddd', 'name': 'Bob', 'id': 1, 'code': 'AU'}
    {'sex': 'girl', 'name': 'Bob', 'id': 2, 'code': 'BR'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
        LIMIT % s (2,)
     
    方式二: slice(start, end)
    result = session.query(Student).order_by(Student.id.asc()).slice(2, 3).all()
    for i in result:
        print(i.to_dict())
    -------------------------结果-------------------------
    {'sex': 'boy', 'code': 'CA', 'id': 3, 'name': 'Hua'}
    对应Sql:
    SELECT
        student.id AS student_id,
        student.NAME AS student_name,
        student.CODE AS student_code,
        student.sex AS student_sex
    FROM
        student
    ORDER BY
        student.id ASC
        LIMIT % s,% s ( 2, 1 )
     
    案例九:统计,count()
    result = session.query(Student).count()
    print(result)
    -------------------------结果-------------------------
    10
    对应Sql:
    SELECT
        count(*) AS count_1
    FROM
        ( SELECT student.id AS student_id, student.NAME AS student_name, student.CODE AS student_code, student.sex AS student_sex FROM student ) AS anon_1
    案例十:去重,distinct()
    result = session.query(Student.name).distinct(Student.name).all()
    -------------------------结果-------------------------
    ('Bob',)
    ('Hua',)
    ('Lan',)
    ('Smith',)
    ('Hub',)
    ('Hip',)
    对应Sql:
    SELECT DISTINCT
        student.NAME AS student_name
    FROM
        student
     
     
    案例十 一: 联合查询,默认 inner join查询
     
    result = session.query(Student.id, Student.code, Student.name, Country.population).join(Country, Student.code == Country.code).all()
    for i in result:
        print(i)
    -------------------------结果-------------------------
    (1, 'AU', 'Bob', 18886000)
    (2, 'BR', 'Bob', 170115000)
    (3, 'CA', 'Hua', 1147000)
    (4, 'CN', 'Lan', 1277558000)
    (5, 'RU', 'Hua', 146934000)
    (6, 'US', 'Smith', 278357000)
    (7, 'AU', 'Bob', 18886000)
    对应Sql:
    SELECT
        student.id AS student_id,
        student.CODE AS student_code,
        student.NAME AS student_name,
        a_country.population AS a_country_population
    FROM
        student
        INNER JOIN a_country ON student.CODE = a_country.CODE
     
     
    案例十二:添加,add() , add_all()
     
    方式一,单条插入,add( )
    result = session.add(Student(name="Bob", code="AU", sex="boy"))
    print(result)
    #事务需要提交才能生效,有别与查询
    session.commit()
    
    -------------------------结果-------------------------
    None 
    Sql:
    BEGIN
    INSERT INTO student (name, code, sex) VALUES (%s, %s, %s) ('Bob', 'AU', 'boy') 
    COMMIT
     
     
    方式二,批量插入, add_all( )
    result = session.add_all([
        Student(name="Smith", code="BM", sex="girl"),
        Student(name="Hub", code="BU", sex="boy"),
        Student(name="Hip", code="HK", sex="boy"),
    ])
    session.commit()
    print(result)
    -------------------------结果-------------------------
    None
    对应Sql:
    BEGIN
    INSERT INTO student (name, code, sex) VALUES (%s, %s, %s) ('Smith', 'BM', 'girl')
    INSERT INTO student (name, code, sex) VALUES (%s, %s, %s) ('Hub', 'BU', 'boy')
    INSERT INTO student (name, code, sex) VALUES (%s, %s, %s) ('Hip', 'HK', 'boy')
    COMMIT
    案例十三: 更新,update()
    result = session.query(Student).filter(Student.id == 1).update({Student.sex: "dddd”})
    # 如果想回滚,则使用 session.rollback() 回滚即可
    session.commit()
    # 返回修改的记录函数
    print(result)
    -------------------------结果-------------------------
    1
    对应Sql:
    BEGIN
    UPDATE student SET sex=%s WHERE student.id = %s ('dddd', 1)
    COMMIT 
     
     
    案例十四: 不存在则插入,存在则更新,on_duplicate_key_update()
     
    这个属于一种高级的用法,不过也特别简单,看此案例你基本上就秒懂了。
     
    insert_smt = insert(Student).values(id=1, name="bb", code="AA", sex="boy").on_duplicate_key_update(sex="aaaaa",code="uuuuu")
    result = session.execute(insert_smt)
    session.commit()
    print(result.rowcount)
    -------------------------结果-------------------------
    1
    注意事项:
    1. 需要引入 一个特别函数 , insert( ) , 它是mysql包下的。from sqlalchemy.dialects.mysql import insert
    2. 使用 on_duplicate_key_update( ) 这个函数进行异常处理,别用错了
    3. 使用execute , 执行insert( ) 函数创建的 Sql 语句即可
    4. 最后一定要记得 commit( ) 一下。
     
    Sql:
    BEGIN
     
    INSERT INTO student ( id, NAME, CODE, sex )
    VALUES (% s, % s, % s, % s )
    ON DUPLICATE KEY UPDATE code = %s, sex = %s
    (1, 'bb', 'AA', 'boy', 'uuuuu', 'aaaaa')
     
    COMMIT
     
     
     
  • 相关阅读:
    ADB 操作手机的粘贴板
    JSESSIONID的简单说明
    Android无线调试出现错误的解决方法
    adb shell input text 完美支持中文输入
    SQL Server 2022来了
    新技能GET!在前端表格中花式使用异步函数的奥义
    地表最强IDE ——Visual Studio 2022正式发布
    用前端表格技术构建医疗SaaS 解决方案
    JavaScript Sanitizer API:原生WEB安全API出现啦
    突破技术限制,实现Web端静默打印
  • 原文地址:https://www.cnblogs.com/yinguohai/p/11243834.html
Copyright © 2020-2023  润新知