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

MySQL 多表查詢 python操作MySQL

內容概要

  • 多表查詢思路
  • navicat視覺化軟體
  • 多表查詢案例
  • python操作MySQL
  • 事物

內容詳細

多表查詢思路

        # 資料準備
        #建表
        create table dep(
        id int primary key auto_increment,
        name varchar(20) 
        );

        create table emp(
        id int primary key auto_increment,
        name varchar(20),
        sex enum('male','female') not null default 'male',
        age int,
        dep_id int
        );

        #插入資料
        insert into dep values
        (200,'技術'),
        (201,'人力資源'),
        (202,'銷售'),
        (203,'運營'),
        (205,'保潔')
        ;

        insert into emp(name,sex,age,dep_id) values
        ('jason','male',18,200),
        ('egon','female',48,201),
        ('kevin','male',18,201),
        ('nick','male',28,202),
        ('owen','male',18,203),
        ('jerry','female',18,204);


        # 1.查詢jason所在的部門名稱
            涉及到SQL查詢題目 一定要先明確到底需要幾張表
            1.先查詢jason所在的部門編號
                select dep_id from emp where name='jason';
            2.根據部門編號查詢部門名稱
                select name from dep where id=(select dep_id from emp where name='jason'); 
            """一條SQL語句的查詢結果既可以看成是一張表也可以看成是查詢條件"""


        """
        多表查詢的思路
            1.子查詢
                將SQL語句查詢的結果括號括起來當做另外一條SQL語句的條件
                    大白話:就是我們日常生活中解決問題的方式>>>:分步操作
            2.連表操作(重要)
                先將需要使用到的表拼接成一張大表 之後基於單表查詢完成
                    inner join	內連線
                    left join	左連線
                    right join	右連線
                    union	    全連線
        """
        # 涉及到多表查詢的時候 欄位名稱容易衝突 需要使用表名點欄位的方式區分
        # inner join:只拼接兩張表中共有的部分
        select * from emp inner join dep on emp.dep_id = dep.id;
        # left join:以左表為基準展示所有的內容 沒有的NULL填充
        select * from emp left join dep on emp.dep_id = dep.id;
        # right join:以右表為基準展示所有的內容 沒有的NULL填充
        select * from emp right join dep on emp.dep_id = dep.id;
        # union:左右表所有的資料都在 沒有的NULL填充
        select * from emp left join dep on emp.dep_id = dep.id
        union
        select * from emp right join dep on emp.dep_id = dep.id;
        """
        疑問:上述操作一次只能連線兩張表 如何做到多張表?
            將兩張表的拼接結果當成一張表與跟另外一張表做拼接
            依次往復 即可拼接多張表
        """
        內部封裝了很多SQL的操作 使用者只需要滑鼠點點點 自動構建SQL語句並執行

        下載使用:需要破解
        基本使用
            navicat可以看成是很多資料庫軟體的客戶端

        MySQL的註釋語法
            # 註釋
            -- 註釋

多表查詢案例

        1、查詢所有的課程的名稱以及對應的任課老師姓名
        4、查詢平均成績大於八十分的同學的姓名和平均成績
        7、查詢沒有報李平老師課的學生姓名
        8、查詢沒有同時選修物理課程和體育課程的學生姓名
        9、查詢掛科超過兩門(包括兩門)的學生姓名和班級

        ###########################編寫SQL不要想著一次性寫完 可以邊寫邊看######################################
        -- 1、查詢所有的課程的名稱以及對應的任課老師姓名
        -- SELECT
        -- 	teacher.tname,
        -- 	course.cname 
        -- FROM
        -- 	teacher
        -- 	INNER JOIN course ON teacher.tid = course.teacher_id;
        -- 4、查詢平均成績大於八十分的同學的姓名和平均成績
        # 1.先確定需要使用到的表 
        # 2.在思考多表查詢的方式
        # 第一步先查詢成績表中 平均成績大於80的學生編號
        # 1.1 按照學生id分組並獲取平均成績
        -- select student_id,avg(num) from score group by student_id;
        # 1.2 篩選出平均成績大於80的資料  (針對聚合函式的欄位結果 最好起別名防止衝突)
        -- select student_id,avg(num) as avg_num from score group by student_id having avg(num) > 80;
        # 1.3 將上述SQL的結果與student表拼接
        -- SELECT
        -- 	student.sname,
        -- 	t1.avg_num 
        -- FROM
        -- 	student
        -- 	INNER JOIN ( SELECT student_id, avg( num ) AS avg_num FROM score GROUP BY student_id HAVING avg( num ) > 80 ) AS t1 ON student.sid = t1.student_id;
        -- 7、查詢沒有報李平老師課的學生姓名
        # 1.先查詢李平老師教授的課程編號
        -- select course.cid from course where teacher_id = 
        -- (select tid from teacher where tname ='李平老師');
        # 2.根據課程id號篩選出所有報了的學生id號
        -- select distinct score.student_id from score where course_id in (select course.cid from course where teacher_id = 
        -- (select tid from teacher where tname ='李平老師'));
        # 3.去學生表中根據id號取反篩選學生姓名
        -- SELECT
        -- 	student.sname 
        -- FROM
        -- 	student 
        -- WHERE
        -- 	sid NOT IN (
        -- SELECT DISTINCT
        -- 	score.student_id 
        -- FROM
        -- 	score 
        -- WHERE
        -- 	course_id IN ( SELECT course.cid FROM course WHERE teacher_id = ( SELECT tid FROM teacher WHERE tname = '李平老師' ) ) 
        -- 	);
        -- 8、查詢沒有同時選修物理課程和體育課程的學生姓名(只要了報了一門的  兩門和一門沒報的都不要)
        # 1.先獲取兩門課程的id號
        -- select course.cid from course where cname in ('物理','體育');
        # 2.再去分數表中先篩選出所有報了物理和體育的學生id(兩門 一門)
        -- select * from score where course_id in (select course.cid from course where cname in ('物理','體育'));
        # 3.如何篩選出只報了一門的學生id  按照學生id分組 然後計數 並過濾出計數結果為1的資料
        -- select score.student_id from score where course_id in (select course.cid from course where cname in ('物理','體育'))
        -- group by score.student_id
        -- having count(score.course_id) = 1
        -- ;
        # 4.根據學生id號去student表中篩選學生姓名
        -- SELECT
        -- 	student.sname 
        -- FROM
        -- 	student 
        -- WHERE
        -- 	sid IN (
        -- SELECT
        -- 	score.student_id 
        -- FROM
        -- 	score 
        -- WHERE
        -- 	course_id IN ( SELECT course.cid FROM course WHERE cname IN ( '物理', '體育' ) ) 
        -- GROUP BY
        -- 	score.student_id 
        -- HAVING
        -- 	count( score.course_id ) = 1 
        -- 	);
        -- 9、查詢掛科超過兩門(包括兩門)的學生姓名和班級
        # 1.先篩選出小於60分的資料
        -- select * from score where num < 60;
        # 2.按照學生id分組 然後統計掛科數量
        -- select student_id,count(course_id) from score where num < 60 group by student_id;
        # 3.篩選出掛科超過兩門的學生id
        -- select student_id from score where num < 60 group by student_id
        -- having count(course_id) >=2;
        # 4.先將上述結果放在一邊 去連線student和class表
        SELECT
            student.sname,
            class.caption 
        FROM
            class
            INNER JOIN student ON class.cid = student.class_id 
        WHERE
            student.sid IN ( SELECT student_id FROM score WHERE num < 60 GROUP BY student_id HAVING count( course_id ) >= 2 );

        更多案例
        https://www.cnblogs.com/Dominic-Ji/p/10875493.html

python操作MySQL

        第三方模組  pymysql
        pip3 install pymysql

        import pymysql


        # 連線MySQL服務端
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='123',
            database='db8_2',
            charset='utf8'
        )
        # 產生一個遊標物件
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 編寫SQL語句
        sql = 'select * from teacher'
        affect_rows = cursor.execute(sql)
        print(affect_rows)
        # 獲取執行結果
        print(cursor.fetchall())

SQL注入問題

        import pymysql


        # 連線MySQL服務端
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='123',
            database='db8_3',
            charset='utf8',
            autocommit=True  # 針對增 改 刪自動二次確認
        )
        # 產生一個遊標物件
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 編寫SQL語句
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        sql = "select * from userinfo where name=%s and pwd=%s"
        cursor.execute(sql,(username,password))
        data = cursor.fetchall()
        if data:
            print(data)
            print('登入成功')
        else:
            print('使用者名稱或密碼錯誤')


        # 1.只需要使用者名稱也可以登入
        # 2.不需要使用者名稱和密碼也可以登入
        """
        SQL注入的原因 是由於特殊符號的組合會產生特殊的效果
            實際生活中 尤其是在註冊使用者名稱的時候 會非常明顯的提示你很多特殊符號不能用
                原因也是一樣的
        結論:設計到敏感資料部分 不要自己拼接 交給現成的方法拼接即可
        """


        # sql = 'insert into userinfo(name,pwd) values("jason","123"),("kevin","321")'
        # res = cursor.execute(sql)

        # print(res)
        """
        在使用程式碼進行資料操作的時候 不同操作的級別是不一樣的
            針對查無所謂
            針對增 改 刪都需要二次確認
                conn.commit()
        """

事物

        # 事務(重要)
            ACID
                A:原子性
                C:一致性
                I:隔離性
                D:永續性
        原子性(atomicity)
            一個事務是一個不可分割的工作單位,事務中包括的諸操作要麼都做,要麼都不做。
        一致性(consistency)
            事務必須是使資料庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。
        隔離性(isolation)
            一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
        永續性(durability)
            永續性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響


        事務相關操作
            start transcation;  # 開啟事務
            諸多SQL操作
            rollback  # 回滾到操作之前的狀態
            commit  # 確認事務操作 之後不能回滾

        # 先介紹事務的三個關鍵字 再去用表實際展示效果

        create table user(
        id int primary key auto_increment,
        name char(32),
        balance int
        );

        insert into user(name,balance)
        values
        ('jason',1000),
        ('egon',1000),
        ('tank',1000);

        # 修改資料之前先開啟事務操作
        start transaction;

        # 修改操作
        update user set balance=900 where name='jason'; #買支付100元
        update user set balance=1010 where name='egon'; #中介拿走10元
        update user set balance=1090 where name='tank'; #賣家拿到90元

        # 回滾到上一個狀態
        rollback;

        # 開啟事務之後,只要沒有執行commit操作,資料其實都沒有真正重新整理到硬碟
        commit;
        """開啟事務檢測操作是否完整,不完整主動回滾到上一個狀態,如果完整就應該執行commit操作"""

        # 站在python程式碼的角度,應該實現的虛擬碼邏輯,
        try:
            update user set balance=900 where name='jason'; #買支付100元
            update user set balance=1010 where name='egon'; #中介拿走10元
            update user set balance=1090 where name='tank'; #賣家拿到90元
        except 異常:
            rollback;
        else:
            commit;