MySQL多表查询&python操作MySQL

1. 多表查询思路

# 涉及到SQL查询题目,一定要先明确到底需要几张表。

"""
多表查询的思路
    1. 子查询
        将SQL语句的查询结果括号括起来,当作另外一条SQL。
        就是日常生活中解决问题的方式,分布操作。

    2. 连表操作(重要)
        先将需要使用的表拼成一张大表,之后基于单表查询完成。
        inner join 内连接
        left join  左外连接
        right join 右连接
        union      全连接

"""
# 涉及到多表查询的时候,字段名容易冲突,需要使用表名点字段的方法避免冲突。

"inner join"
# 只拼接两张表有关系的部分--两张表共有的!!
select * from emp inner join dep on dep.id=emp.dep_id;

"left join"
# 以左表为基准,展示所有的内容,没有的NULL填充。
select * from emp left join dep on dep.id=emp.dep_id;

"right join"
# 以右表为基准,没有的NULL填充。
select * from emp right join dep on dep.id=emp.dep_id;

"union"
# 左右表所有的数据都在,没有的NULL填充
select * from emp left join dep on dep.id=emp.dep_id
union
select * from emp right join dep on dep.id=emp.dep_id;

"""
疑问:上述操作一次只能连接两张表,如何做到多张表?
    将两张表的拼接结果当成一张表与另外一张表做拼接
    以此往复,连接多张表。

"""

2. navicat 可视化软件

内部封装了很多SQL操作,用户用鼠标即可构建SQL语句并执行。

3. 多表查询练习

2. 查询平均成绩大于80分的同学的姓名和平均成绩
SELECT
    student.sname,
    avg( num ) 
FROM
    score
    LEFT JOIN student ON score.student_id = student.sid 
GROUP BY
    student_id 
HAVING
    avg( num )> 80;
    
3. 查询没有报李平老师课的学生姓名
SELECT
    student.sid 
FROM
    student 
WHERE
    student.sid NOT IN (
    SELECT
        student.sid 
    FROM
        teacher
        LEFT JOIN course ON teacher.tid = course.teacher_id
        LEFT JOIN score ON course.cid = score.course_id
        LEFT JOIN student ON score.student_id = student.sid 
    WHERE
    teacher.tname = "李平老师" 
    );


4. 查询没有同时选修物理课程和体育课程的学生姓名
SELECT
    student.sname 
FROM
    student 
WHERE
    student.sname NOT IN (
    SELECT
        student.sname 
    FROM
        student
        LEFT JOIN score ON student.sid = score.student_id
        LEFT JOIN course ON score.course_id = course.cid 
    WHERE
        course.cname IN ( "物理", "体育" ) 
    GROUP BY
        student_id 
    HAVING
    count( student_id )= 1 
    );

5. 查询挂科超过两门(包括两名)的学生姓名和班级
SELECT
    student.sname,
    class.caption 
FROM
    score
    LEFT JOIN student ON score.student_id = student.sid
    LEFT JOIN class ON class.cid = student.class_id 
WHERE
    num < 60 
GROUP BY
    student_id 
HAVING
    count( course_id )>= 2;


4. python操作mysql

4.1 基本使用

pip3 install pymysql

# 1. 连接MySQL服务端
conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="123",
    db="dbtest",
    charset="utf8"
)

# 2. 产生一个游标对象
cursor = conn.cursor(cursor=pymysql.cursor.DictCursor)

# 3. 编写SQL语句
sql = "select * from teacher"
affect_rows = cursor.execute(sql)
print(affect_rows)

# 4. 获取执行结果
print(cursor.fetchall())  # 获取所有
print(cursor.fetchall())  # 类似于文件光标,全获取完了,没了
print(cursor.fetchone())  # 获取单个
print(cursor.fetchmany(3))  # 想获取几个

cursor.scroll(1,'relative')  # 也可以控制光标的移动
cursor.scroll(1,'absolute')


4.2 SQL注入


conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="123",
    db="数据库名",
    charset="utf8",
    autocommit=True,
)

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql = 'insert into userinfo(name,pwd) values("joshua","123")'

cursor.execute()

"""
在使用代码进行数据操作的时候,不同操作的级别是不一样的,
针对查无所谓
针对 增 改 删 都需要二次确认
commit
"""
conn.commit()  # 可以设置自动提交

"""
SQL注入的原因 是由于特殊符号的组合会产生特殊的效果
    实际生活中尤其是在注册用户名的时候,会非常明显的提示你很多特殊符号不能用
    原因也是一样的

"""
# 针对SQL注入可以这样做
sql = "select * from userinfo where name=%s and pwd=%s"
cursor.execute(sql,(username,password))


5. MySQL其他理论补充


"事务(重要)"
    ACID
	A:原子性
	C:一致性
	I:隔离性
	D:持久性

# 原子性(Atomicity)
原子性是指事务包含的所有操作不可分割,要么全部成功,要么全部失败回滚。

# 一致性(Consistency)
执行的前后数据的完整性保持一致。

# 隔离性(Isolation)
一个事务执行的过程中,不应该受到其他事务的干扰。

# 持久性(Durability)
事务一旦结束,数据就持久到数据库

"MySQL客户端开启事务"
begin;  # 开启事务  start transaction;
执行操作
执行操作
commit; # 提交事务  rollback;(表示要回滚,回滚到开启事务之后)


python代码:

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="123",
    db="数据库名",
    charset="utf8",
    autocommit=True,
)

# 开启事务
conn.begin()

try:
    cursor.execute("update users set amount=1 where id=1")
    int('123')
    cursor.execute("update tran set amount=2 where id=2")
except Exception as e:
    # 回滚
    print("回滚")
    conn.rollback()
else:
    # 提交
    print("提交")
    conn.commit()

cursor.close()
conn.close()


posted @ 2022-02-22 15:53  Joshua_jiaxue  阅读(207)  评论(0编辑  收藏  举报