1. 程式人生 > 其它 >MySQL多表查詢&python操作MySQL

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()