子查询
子查询指的是当一个查询语句被作为另一个查询语句的条件时,该查询语句就称之为子查询(内层查询)
可以将一个大问题 拆分几个小的问题 然后一步一步来查询
需求:财务不有哪些人
create table emp (id int,name char(10),sex char,dept char(10),job char(10),salary double); insert into emp values (1,"刘备","男","市场","总监",5800), (2,"张飞","男","市场","员工",3000), (3,"关羽","男","市场","员工",4000), (4,"孙权","男","行政","总监",6000), (5,"周瑜","男","行政","员工",5000), (6,"小乔","女","行政","员工",4000), (7,"曹操","男","财务","总监",10000), (8,"司马懿","男","财务","员工",6000); create table dept(id int primary key,name char(10)); insert into dept values(1,"市场"),(2,"行政"),(3,"财务");
select *from emp join dept on emp.dept_id = dept.id where dept.name = "财务";
子查询的语法:将子查询(内层查询)用括号包裹即可
子查询的实现思路
1.通过部门名称拿到部门的id
select id from dept where name='财务';
2.通过部门id取员工表查询对应的员工
select * from emp where dept_id =(select id from dept where name='财务');
查询平均年龄大于25的部门名称
1.先查询出一堆平均年龄大于25的部门id
2.在通过id 查询部门的名称
select name from dept where id in(select dept_id from emp group by dept_id having avg(age)>25)
查询平均年龄大于25的部门
使用连接查询完成
1.先连接在一起
2.on 筛选正确匹配关系
3.where 条件
select dept.name from emp join dept on emp.dept_id =dept.id group by dept.name having avg(age)>25;
查询每个部门工资最高的员工信息
1.查询出每个部门的最高工资是多少
select dept_id,max(salary)from emp group by dept_id;
2.拿着最高工资查询员工信息
select *from emp join (select dept_id,max(salary) as maxs from emp group by dept_id) as t1 on emp.dept_id = t1.dept_id where emp.salary = t1.maxs;
#查询语句无论多长 其实都是一步一步做出来的 先写一段测试一下没问题 再接着写
create table test(day_id date,result char(10)); insert test values("2018-10-01","success"); insert test values("2018-10-01","fail"); insert test values("2018-10-01","fail"); insert test values("2018-10-01","success"); insert test values("2018-10-02","success"); insert test values("2018-10-02","fail"); insert test values("2018-10-02","fail");
查询出以下结果:
day_id success fail
2018-10-01 2 2
2018-10-02 1 2
select t1.day_id,success,fail from (select day_id,count(*) as success from test group by day_id,result having result = "success") as t1 join (select day_id,count(*) as fail from test group by day_id,result having result = "fail") as t2 on t1.day_id = t2.day_id;
用户管理
mysql用户指的是客户端连接服务器时使用的账户
在一些公司中,很多项目的数据 可能会放在同一个服务器
那就必须要为每一个用户明确其所拥有的权限
通常到公司之后都会给你一个账号名称和密码 并且 为你制定你可以访问哪些数据库或表
对用户账号增删改查以及权限的增删改查
mysql与权限相关的表:
user columns_priv tables_priv db
select * from user G;#当字段太多 一行显示不了可以G
create user 用户名@主机名称 indentfied by '密码';
该语句只是单纯创建一个用户后续还要分配权限稍微麻烦
推荐使用grant语句可以在创建账户的同时分配权限
grant all on *.* to用户名@主机名 indentfied by '密码';
grant all on *.* to用户名@loaclhost indentfied by '密码';
#授予所有库的所有表的所有权限给用户名这个账户然后密码只允许在127.0.0.1上登录
主机地址可以是%意味着这个用户可以在任何主机上登录服务器 需要加上双引号
#这个用户不能其他用户授权 默认只有root可以为其他账户授权
grant all on day45.* to jerry@localhost identified by "123"; # day45所有表
grant all on day45.dept to tom@localhost identified by "123"; # day45的dept表
mysql的权限可以精确到列(某个字段的某种权限)
但是不能精确到某一行(需要使用视图)
可以将权限授予其他账户
grant all on day45.dept to bgon@localhost identified by "123" with grant option;
回收权限
revoke all privileges [column] on db.table from user@"host";
revoke all privileges on day45.dept from bgon@"localhost";
删除用户
drop user username@host;
刷新权限
flush privileges
正常开发时我们的数据库服务器也会运行在云服务器上,经常需要从本地远程操作数据库
但是默认请款root只能在服务器本机上登录
所以我们可以grant语句来授权所有主机
grant all on *.* to root@192.168.111 identified by "123321" with grant option;
PYMYSQL
pymysql是由mysql提供的一个模块 需要单独安装
pymysql的作用就是可以使用python代码来操作数据库上的数据
本质上还是一个CS的客户端
1.连接数据库
2.发送sql指令给服务器
3.接收服务器返回的结果
import pymysql try: # 1.conn是一个表示连接的对象 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123321', database='day44' ) print('连接服务器成功!') # 2.查询数据 需要借助cursor类 游标 默认游标返回值类型为元组 # pymysql.cursors.DictCursor 可以将结果转换为字典 cursor = conn.cursor(pymysql.cursors.DictCursor) # 3.执行sql语句 sql = 'select *from dept;' res = cursor.execute(sql) # res为本次查询得到的记录条数 print(res) # 4.提取数据 # print(cursor.fetchall()) #获取本次查询所有结果 # print(cursor.fetchone())#提起本次查询的第一条记录 print(cursor.fetchmany(2)) # 指定提取记录的条数 # 如果游标已经到达最后 将无法再读取数据 可以使用scroll来移动游标位置 cursor.scroll(-1, mode='relative') # mode参数表示 是相对位置relative 还是绝对位置absolute # cursor.scroll() except Exception: print(type(Exception), Exception) finally: # 无论石是否执行成功 最后都需要关闭连接 if cursor: cursor.close() # 关闭游标 if conn: conn.close() # 关闭连接
登录 客户端再网页输入用户和密码 浏览器要把接收的数据传给后台服务器
再由后台服务器交给数据库服务器
可能会遇到sql注入攻击
什么是sql注入攻击 一些不法分子可能会在输入的数据中添加一系列sql语句来跳过认证环节
甚至直接删除数据
解决方案
1.在客户端接收数据时做一个re的判断 如果包含sql相关的字符就直接报错
2.在服务器收到某一个客户端发送的数据时做一个判断
其实pymysql已经封装好了相关的判断逻辑 只要将参数交给pymysql来拼接即可
pymysql使用
1.用pymysql.connect(参数)建立连接 得到连接对象
2.通过连接对象拿到游标对象conn.cursor(pymysql.cursors.DictCursor)
3.通过调用游标对象的excute或者excutemany 来执行sql
4.调用游标的fetch(one/many/all)相关函数来提取执行结果
强调:pymysql默认不会提交修改需要手动调用conn.commit或是在创建时指定自动提交
scroll移动游标不常用
import pymysql # 1.conn是一个表示连接的对象 conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123321', database='day44', autocommit=True ) print('连接服务器成功!') # 增加数据 # sql = "insert into user values(null,'tom','123')" # 删除 # sql = "delete from user where name = 'tom'" # 更新 # sql = "update user set id = 10000 where id = 1" cursor = conn.cursor(pymysql.cursors.DictCursor) # 返回的是 本次sql语句执行后 受到影响行数 # count = cursor.execute(sql) # 用来批量添加数据 可提高效率 count = cursor.executemany("insert into user values (null,%s,%s)", [("tom1", "123"), ("tom2", "123"), ("tom3", "321")]) if count: print("修改成功!") else: print("修改失败!") # 需要调用commit来提交修改 或者在创建连接时 指定自动提交修改 # conn.commit()