Python学习日记(四十二) Mysql数据库篇 十
前言
当我们自己去写SQL代码的时候有时候会因为不熟练会导致效率低,再之后要进行许多的优化,并且操作也较为繁琐。因此ORM框架就能够解决上面的问题,它能根据自身的一些规则来帮助开发者去生成SQL代码。按性能上看虽然直接去写SQL语句会比ORM框架生成的效率高,但实际上每一个开发者的SQL代码程度都参差不齐,因此框架在这里就起到了一个统一的作用。
ORM框架(SQLAlchemy)
作用:提供简单的规则,去自动转换成SQL语句
安装:
pip install SQLAlchemy;
系统架构:
SQLAlchemy主要分为SQLAlchemy ORM和SQLAlchemy Core两个部分,这里的DBAPI指的是像mysqldb、pymysql、cx_Oracle...用来连接数据库的模块。因此这里的DBAPI和SQLAchemy是没有直接的关系的,SQLAlchemy主要就是负责将对象和类转换为SQL语句。在使用SQLAlchemy去创建数据库中之前,要把pymysql给安装才能实现相关的功能。
Object Relational Mapper(ORM)为关系对象映射,简单来说就是对象和类
Schema/Types和SQL Expression Language主要帮助上面的ORM转换为SQL语句
Engine为引擎,用于操作配置文件、Connection Pooling为连接池用于保持多少个和数据库相连的连接、Dialect用于选择去连接Mysql、SQLSever、Oracle等数据库去选择
连接其他数据库的方法:
1.Oracle + cx_oracle
oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 2.SQLite + pysqlite
sqlite+pysqlite:///file_path 3.SQLite + pysqlcipher
sqlite+pysqlcipher://:passphrase/file_path[?kdf_iter=<iter>] 4.Mysql + pymysql
mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] 5.Mysql + Oursql
mysql+oursql://<user>:<password>@<host>[:<port>]/<dbname>
参考网站:https://www.sqlalchemy.org/
ORM分为两类(DB first、Code first)
DB first:手动创建数据以及表->通过ORM框架去自动生成类
Code first:手动创建类和数据库->通过ORM框架创建表。
创建一个表(前提先创建一个数据库):
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy import create_engine Base = declarative_base()
#创建表
class Users(Base):
__tablename__ = 'users' #定义数据库的表名,id,name,email表示这张表会生成三列
id = Column(Integer,primary_key = True,autoincrement = True)
name = Column(String(32))
email = Column(String(16)) engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5) #root后面可以写登录密码,max_overflow表示最多和数据库建立5个连接
Base.metadata.create_all(engine) #找到py文件中的这个类在数据库中创建表
完成表的创建:
那如果要删除这些创建的表:
Base.metadata.drop_all(engine)
创建两张表之间的关系员工和部门表:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,UniqueConstraint,Index
from sqlalchemy import create_engine Base = declarative_base()
#创建部门表
class Department(Base):
__tablename__ = 'department'
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
depart = Column(String(32),nullable=False) #创建员工表
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer,primary_key=True,autoincrement=True,nullable=False)
name = Column(String(32),nullable=False,index=True) #开启索引
age = Column(Integer,default=20) #默认年龄为20
email = Column(String(32),unique=True) #创建唯一索引
employee_depart_id = Column(Integer,ForeignKey('department.id')) #创建外键'employee_depart_id' __table_args__ = (
UniqueConstraint('id','name','email',name = 'uindex_i_n_e'), #创建联合唯一索引'uindex_i_n_e'
Index('index_name_email','name','email') #创建联合普通索引'index_name_email'
)
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Base.metadata.create_all(engine)
完成表的创建:
将删除表和创建表封装为两个不同的函数,方便之后的操作:
def create_db():
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Base.metadata.create_all(engine) def drop_db():
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8', max_overflow = 5)
Base.metadata.drop_all(engine)
代码中String表示了Char和Varchar,若只需要用Char或Varchar可以在import后面不写String单写Varchar或Char就好
操作数据行
增
增加部门表的数据
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8', max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() #获取一个连接去进行操作
#增加部门表数据
objs = [
Department(depart = '保安'), #一张表代表了一个类,对象代指的是数据行
Department(depart = '程序员'),
Department(depart = 'DBA'),
Department(depart = 'BOSS')
]
session.add_all(objs)
session.commit()
session.close()
增加员工表的数据
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8', max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session()
#增加员工表数据
objs = [
Employee(name='aaa1',age=21,email='165444236@gamil.com',employee_depart_id=1),
Employee(name='aaa2',email='265444236@gamil.com',employee_depart_id=2),
Employee(name='aaa3',age=23,email='365444236@gamil.com',employee_depart_id=3),
Employee(name='aaa4',age=31,email='465444236@gamil.com',employee_depart_id=4),
Employee(name='aaa5',email='565444236@gamil.com',employee_depart_id=3),
Employee(name='aaa6',age=51,email='665444236@gamil.com',employee_depart_id=3)
]
session.add_all(objs)
session.commit()
session.close()
删
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8', max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() employee_list = session.query(Employee).filter(Department.id == 6).delete() session.commit()
session.close()
改
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8', max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() employee_list = session.query(Employee.name).filter(Employee.id > 0).update({'name': 'abc'}) #全改
employee_list = session.query(Employee.name).filter(Employee.id > 0).update({Employee.name:Employee.name + ''},synchronize_session=False)
employee_list = session.query(Employee.name).filter(Employee.id > 0).update({'name':Employee.age + 1},synchronize_session='evaluate') session.commit()
session.close()
查
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8', max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() employee_list = session.query(Employee)
print(employee_list) #这里表示的是SQL查询语句 employee_list = session.query(Employee).all() #查询表内的数据
for i in employee_list:
print(type(i),i,i.name,i.age,i.email)
# <class '__main__.Employee'> <__main__.Employee object at 0x0000000003F1EF98> aaa1 21 165444236@gamil.com
# <class '__main__.Employee'> <__main__.Employee object at 0x0000000003F1EEF0> aaa2 20 265444236@gamil.com
# <class '__main__.Employee'> <__main__.Employee object at 0x0000000003F4E0F0> aaa3 23 365444236@gamil.com
# <class '__main__.Employee'> <__main__.Employee object at 0x0000000003F4E6D8> aaa4 31 465444236@gamil.com
# <class '__main__.Employee'> <__main__.Employee object at 0x0000000003F4E2E8> aaa5 20 565444236@gamil.com
# <class '__main__.Employee'> <__main__.Employee object at 0x0000000003F4E160> aaa6 51 665444236@gamil.com employee_list = session.query(Employee).filter(Employee.id > 2) #类似于使用where条件语句进行数据筛选
for i in employee_list:
print(i.id,i.name)
# 3 aaa3
# 4 aaa4
# 5 aaa5
# 6 aaa6 employee_list = session.query(Employee.name,Employee.email).filter(Employee.id > 2) #表示只取这张表的哪几列
for i in employee_list:
print(i.name)
# aaa3
# aaa4
# aaa5
# aaa6 session.commit()
session.close()
其他操作
员工表:
1.分组
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() from sqlalchemy.sql import func
ret1 = session.query(func.max(Employee.id),func.min(Employee.id),func.sum(Employee.id),func.avg(Employee.id)).group_by(Employee.name).all()
ret2 = session.query(func.max(Employee.id)).group_by(Employee.name).having(func.min(Employee.id) > 2).all() session.commit()
session.close()
2.排序
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() ret1 = session.query(Employee).order_by(Employee.name.desc(),Employee.age.asc(),Employee.email.desc()).all()
for i in ret1:
print(i.id, i.name, i.email)
# 6 52 665444236@gamil.com
# # 4 32 465444236@gamil.com
# # 3 24 365444236@gamil.com
# # 1 22 165444236@gamil.com
# # 5 21 565444236@gamil.com
# # 2 21 265444236@gamil.com session.commit()
session.close()
3.连表
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() ret1 = session.query(Employee,Department).filter(Employee.employee_depart_id == Department.id).all() ret2 = session.query(Employee).join(Department).all() #这里会自动找到外键将两张表进行连接,这里相当于inner join ret3 = session.query(Employee).join(Department,isouter=True).all() #这里相当于left join,这里开False也是inner join session.commit()
session.close()
4.通配符
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() ret1 = session.query(Employee).filter(Employee.name.like('2_')).all()
for i in ret1:
print(i.id, i.name, i.email)
# 2 21 265444236@gamil.com
# 5 21 565444236@gamil.com
# 1 22 165444236@gamil.com
# 3 24 365444236@gamil.com ret2 = session.query(Employee).filter(Employee.name.like('%2')).all()
for i in ret2:
print(i.id, i.name, i.email)
# 1 22 165444236@gamil.com
# 4 32 465444236@gamil.com
# 6 52 665444236@gamil.com ret3 = session.query(Employee).filter(~Employee.name.like('%2')).all()
for i in ret3:
print(i.id,i.name,i.email)
# 2 21 265444236@gamil.com
# 3 24 365444236@gamil.com
# 5 21 565444236@gamil.com
session.commit()
session.close()
5.子查询
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() #1.select * from b where id in (select id from tb);
ret1 = session.query(Employee).filter(Employee.id.in_(session.query(Employee.id).filter_by(name = ''))).all()
for i in ret1:
print(i.id,i.name,i.email)
# 2 21 265444236@gamil.com
# 5 21 565444236@gamil.com #2.select * from (select * from tb) as T;
q1 = session.query(Employee).filter(Employee.id > 2).subquery()
ret2 = session.query(q1).all()
for i in ret2:
print(i.id,i.name,i.email)
# 3 24 365444236@gamil.com
# 4 32 465444236@gamil.com
# 5 21 565444236@gamil.com
# 6 52 665444236@gamil.com #3.select id,(select * from tb where a.type_id == b.id) from b;
ret3 = session.query(Department.id,session.query(Employee).filter(Employee.id == Department.id).as_scalar()) session.commit()
session.close()
6.limit(限制)
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() ret1 = session.query(Employee)[3:6]
for i in ret1:
print(i.id, i.name, i.email)
# 4 32 465444236@gamil.com
# 5 21 565444236@gamil.com
# 6 52 665444236@gamil.com session.commit()
session.close()
7.union(组合)
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() q1 = session.query(Employee.name).filter(Employee.id > 3)
q2 = session.query(Department.depart).filter(Department.id > 1)
u1 = q1.union(q2).all() #去重
u2 = q1.union_all(q2).all() #不去重 session.commit()
session.close()
8.条件
filter_by里面穿的是参数,filter里面传的是表达式,filter_by内部会调用filter
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() ret1 = session.query(Employee).filter_by(name = '').all()
for i in ret1:
print(i.id,i.name,i.email)
#1 22 165444236@gamil.com ret2 = session.query(Employee).filter(Employee.id > 1,Employee.name == '').all() #这里默认使用AND
for i in ret2:
print(i.id,i.name,i.email)
# 2 21 265444236@gamil.com
# 5 21 565444236@gamil.com ret3 = session.query(Employee).filter(Employee.id.between(2,4),Employee.name == '').all()
for i in ret3:
print(i.id,i.name,i.email)
# 3 24 365444236@gamil.com ret4 = session.query(Employee).filter(Employee.id.in_([1,2,6])).all()
for i in ret4:
print(i.id,i.name,i.email)
# 1 22 165444236@gamil.com
# 2 21 265444236@gamil.com
# 6 52 665444236@gamil.com ret5 = session.query(Employee).filter(~Employee.id.in_([1,2,6])).all()
for i in ret5:
print(i.id,i.name,i.email)
# 3 24 365444236@gamil.com
# 4 32 465444236@gamil.com
# 5 21 565444236@gamil.com ret6 = session.query(Employee).filter(Employee.id.in_(session.query(Employee.id).filter_by(name = ''))).all() #临时表
for i in ret6:
print(i.id,i.name,i.email)
# 2 21 265444236@gamil.com
# 5 21 565444236@gamil.com from sqlalchemy import and_,or_
ret7 = session.query(Employee).filter(and_(Employee.id > 4,Employee.name == '')).all() #这里默认使用AND
for i in ret7:
print(i.id,i.name,i.email)
# 5 21 565444236@gamil.com ret8 = session.query(Employee).filter(or_(Employee.id > 4,Employee.name == '')).all()
for i in ret8:
print(i.id, i.name, i.email)
# 2 21 265444236@gamil.com
# 5 21 565444236@gamil.com
# 6 52 665444236@gamil.com ret9 = session.query(Employee).filter(
or_(
Employee.id > 2,
and_(
Employee.age > 20,Employee.email == "465444236@gamil.com"
),
Employee.name == ''
)
).all()
for i in ret9:
print(i.id, i.name, i.email)
# 2 21 265444236@gamil.com
# 3 24 365444236@gamil.com
# 4 32 465444236@gamil.com
# 5 21 565444236@gamil.com
# 6 52 665444236@gamil.com session.commit()
session.close()
9.原生SQL
建立Relationship
一般情况下我们要去获取员工信息以及与它关联的员工类型名称(正向操作)
写法一:
ret = session.query(Employee,Department).join(Department,isouter=True)
print(ret)
for row in ret:
print(row[0].id,row[0].name,row[0].age,row[0].email,row[0].employee_depart_id,row[1].depart)
写法二:
ret = session.query(Employee.name,Department.depart).join(Department,isouter=True)
print(ret)
for row in ret:
print(row[0],row[1]) #两种写法都一样
print(row.name,row.depart)
在query()后面不加上all()拿ret就相当于一个迭代器,加上all()就相当于fetchall()把所有的数据都拿回来了
那除了用以上的方法之外我们还可以在Employee表中加上关系:
depart_relation = relationship('Department')
在此之前要import relation模块
from sqlalchemy.orm import relationship
执行代码:
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db3?charset=utf8',max_overflow = 5)
Session = sessionmaker(bind=engine)
session = Session() ret = session.query(Employee)
for row in ret:
print(row.id,row.name,row.age,row.email,row.depart_relation.depart)
# 1 22 21 165444236@gamil.com 保安
# 2 21 20 265444236@gamil.com 程序员
# 3 24 23 365444236@gamil.com DBA
# 4 32 31 465444236@gamil.com BOSS
# 5 21 20 565444236@gamil.com DBA
# 6 52 51 665444236@gamil.com DBA session.commit()
session.close()
那如果要获取用户的数据类型(反向操作)该怎么写?
一般写法:
ret = session.query(Department)
for row in ret:
print(row.id,row.depart,session.query(Employee).filter(Employee.employee_depart_id == row.id).all())
# 1 保安 [<__main__.Employee object at 0x0000000003F67358>]
# 2 程序员 [<__main__.Employee object at 0x0000000003F674A8>]
# 3 DBA [<__main__.Employee object at 0x0000000003F675F8>, <__main__.Employee object at 0x0000000003F47F28>, <__main__.Employee object at 0x0000000003F47CF8>]
# 4 BOSS [<__main__.Employee object at 0x0000000003F67588>]
将添加的关系语句后加上:
depart_relation = relationship('Department',backref = 'relatvar') #这里的backref是给Department用的
执行代码:
ret = session.query(Department)
for row in ret:
print(row.id,row.depart,row.relatvar)
# 1 保安 [<__main__.Employee object at 0x0000000003F66BE0>]
# 2 程序员 [<__main__.Employee object at 0x0000000003F66C88>]
# 3 DBA [<__main__.Employee object at 0x0000000003F66DD8>, <__main__.Employee object at 0x0000000003F66E48>, <__main__.Employee object at 0x0000000003F66EB8>]
# 4 BOSS [<__main__.Employee object at 0x0000000003F87048>]
relationship一般写在有外键的那张表上
Python学习日记(四十二) Mysql数据库篇 十的更多相关文章
- Python学习日记(四十) Mysql数据库篇 八
Mysql存储过程 存储过程是保存在Mysql上的一个别名(就是一堆SQL语句),使用别名就可以查到结果不用再去写SQL语句.存储过程用于替代程序员写SQL语句. 创建存储过程 delimiter / ...
- Python学习日记(三十六) Mysql数据库篇 四
MySQL作业分析 五张表的增删改查: 完成所有表的关系创建 创建教师表(tid为这张表教师ID,tname为这张表教师的姓名) create table teacherTable( tid int ...
- Python学习日记(四十一) Mysql数据库篇 九
前言 索引的主要作用是起到约束和加速查找,ORM框架(sqlalchemy)是用类和对象对数据库进行操作 索引的种类 按种类去分 1.普通索引:能够加速查找 2.主键索引:能够加速查找.不能为空.不能 ...
- Python学习日记(三十八) Mysql数据库篇 六
Mysql视图 假设执行100条SQL语句时,里面都存在一条相同的语句,那我们可以把这条语句单独拿出来变成一个'临时表',也就是视图可以用来查询. 创建视图: CREATE VIEW passtvie ...
- Python学习日记(三十九) Mysql数据库篇 七
Mysql函数 高级函数 1.BIN(N) 返回N的二进制编码 ); 执行结果: 2.BINARY(str) 将字符串str转换为二进制字符串 select BINARY('ASCII'); 执行结果 ...
- Python学习日记(三十五) Mysql数据库篇 三
使用Navicate 创建一个连接去使用Mysql的数据库,连接名可以取任意字符但是要有意义 新增一个数据库 填写新数据库名,设置它的字符集和排序规则 新建一个表 增加表中的信息 点击保存再去输入表名 ...
- Python学习日记(四) 集合和元祖
元祖的特性:是一个只读列表.可以循环.可以切片,修改数据遵循'儿子'不能改但'孙子'可能可以改. iterable:可迭代对象(元祖.列表.字串.集合) 元祖宣告方式: tu = (1,2,3,['a ...
- Python datatime 格式转换,插入MySQL数据库
Python datatime 格式转换,插入MySQL数据库 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-11-2 ...
- python学习第四讲,python基础语法之判断语句,循环语句
目录 python学习第四讲,python基础语法之判断语句,选择语句,循环语句 一丶判断语句 if 1.if 语法 2. if else 语法 3. if 进阶 if elif else 二丶运算符 ...
随机推荐
- 在eclipse中新建java问题报错:The type XXX cannot be resolved. It is indirectly referenced from required .class files
在Eclipse中遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误 ...
- 三天精通Vue--Vue的常用语法
Vue的介绍 官网教程:https://cn.vuejs.org/v2/guide/installation.html 掘金:https://juejin.im/ cdn(在线的网络连接资源):htt ...
- Spring Boot 知识笔记(Filter过滤器)
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 htm ...
- mac 下使用nasm
#安装nasm brew install nasm #创建文件 vi hello.asm 写入如下内容 msg: db "hello world!", 0x0a len: equ ...
- vue 实现模块上移下移 实现排序
效果图 上移 下移 首先想到的是 数组的相互替换嘛 <template> <div> <div class="box" v-for="(it ...
- Apache的安装部署 2(加密认证 ,网页重写 ,搭建论坛)
一.http和https的基本理论知识1. 关于https: HTTPS(全称:Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道 ...
- python 使用nmap 模块
官网 https://pypi.org/project/python-nmap/ >>> import nmap>>> nm = nmap.PortScannerS ...
- Scala反射(二)
我们知道,scala编译器会将scala代码编译成JVM字节码,编译过程中会擦除scala特有的一些类型信息,在scala-2.10以前,只能在scala中利用java的反射机制,但是通过java反射 ...
- c++篇 vc++2010设置和c#一样的代码段,vs2010 两下tab设置
设置vs2010 tab敲两下出 for 片段,因为vs2010的代码片段是在番茄助手里设置的...代码片段管理器中不能设置c++ 所以我只能安装一个番茄助手了... 然后就是修改番茄助手内的[提示] ...
- spring boot 从开发到部署(二)—重启服务
上篇中,我们开发并部署上线了一个 spring boot 项目.现在需要编写服务重启脚本,保证服务器重启后能够自动的运行我们的项目. /home/web/sprint-web/restart-happ ...