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

 

 
 
 
posted @ 2019-07-25 13:59  大步向前blue  阅读(2105)  评论(0编辑  收藏  举报