數據庫MySQL

MySQLhtml

MySQL:是用於管理文件的一個軟件mysql

 

—  服務端軟件

        —  socket服務器

        —  本地文件操做

        —  解析指令【SQL語句】

      —  客戶端軟件(各類各樣)

        —  socket客戶端

        —  發送指令

        —  解析指令【SQL語句】

鏈接:程序員

show databases;展現數據庫       use 數據庫名稱;       show table;展現列表       select * from 表名;展現列表裏面所有內容       select name,age,id from 表名;       mysql 數據庫user表       use mysql;       select user,host from user

 

學習SQL語句規則面試

    操做文件夾算法

create databases db1;建立文件夾       create dababases db1 default charset utf8;******       show databases;       drop databases db2;       操做文件       show tables;建立表       create table t1(id int,name,char(10)) default charset utf8;       creare table t1(id int,name char(10)) engine=innodb default charset=utf8;       create table t3(id int auto_increment,name chae(10))engine=innodb default charset=utf8;******       creat table t1(           列名 類型 null,           列名 類型 not null,           列名 類型 not null auto_increment primary key,           id int,           name char10)        )engine=innodb default charset=utf8;

 

innodb 支持事物,原子性操做           myisam           auto_increment 表示:自增           primary:表示約束(不能重複且不能爲空);加速查找           not null:是否爲空           數字類型:               數字:               tinyint:小整數,數據類型用於保存一些範圍的整數數值範圍:               int:整數,數據類型用於保存一些範圍的整數數值範圍:               bigint:大整數,數據類型用於保存一些範圍的整數數值範圍:               FLOAT(M,D):單精度浮點數(非準確小數值),m是數字總個數,d是小數點後個數。               DOUBLE(M,D):雙精度浮點數(非準確小數值),m是數字總個數,d是小數點後個數。               decimal[(m[,d])]:準確的小數值,m是數字總個數(負號不算),d是小數點後個數。               m最大值爲65,d最大值爲30。特別的:對於精確數值計算時須要用此類型。               decaimal可以存儲精確值的緣由在於其內部按照字符串存儲。               字符串:                   char(10)  (定長)速度快,空的位置補空值 ******

                  varchar(10) 節省空間                   PS:建立數據表定長列往前放             create table t1(                 id int not null auto_increment primary key,                 num decimal(10,5),                 name char(10),             )engine=innodb default charset=utf8;         清空表:             delete from t1;             truncate table t1;         刪除表:             drop table t1;

     

操做文件中的內容

插入數據:

    insert into t1(id,name) values(1,'alex'); 
刪除:

    delete from t1 where id>6; 
修改:

    update t1 set age=18;   update t1 set age=18 where age=17; 
查看數據:

select * from t1;

 

 

外鍵:

create table userinfo(

            uid int auto_increment primary key,

            name varchar(32),

            department_id int,

            student_id int,

            constraint fk_user_depar foreirn key (department_id) references color(id)

        )engine=innodb default charset=utf8;



        create table department(

            id bigint auto_increment primary key,

            title char(5)

        )engine=innodb default charset=utf8;
View Code

 主鍵:

 主鍵,一種特殊的惟一索引,不容許有空值,若是主鍵使用單個列,則它的值必須惟一,若是是多列,則其組合必須惟一。
            create table tb1(
                nid int not null auto_increment primary key,
                num int null
            )
            或
            create table tb1(
                nid int not null,
                num int not null,
                primary key(nid,num)
            )
View Code

自增:

自增,若是爲某列設置自增列,插入數據時無需設置此列,默認將自增(表中只能有一個自增列)
            create table tb1(
                nid int not null auto_increment primary key,
                num int null
            )
            或
            create table tb1(
                nid int not null auto_increment,
                num int null,
                index(nid)
            )
            注意:1、對於自增列,必須是索引(含主鍵)。
                 2、對於自增能夠設置步長和起始值
                     show session variables like 'auto_inc%';
                     set session auto_increment_increment=2;
                     set session auto_increment_offset=10;

                     shwo global  variables like 'auto_inc%';
                     set global auto_increment_increment=2;
                     set global auto_increment_offset=10;
View Code

表內容操做:


  1 insert
into 表 (列名,列名...) values (值,值,值...)   2 insert into 表 (列名,列名...) values (值,值,值...),(值,值,值...)   3 insert into 表 (列名,列名...) select (列名,列名...) from 表


    1 deletefrom表
    2 delete from 表 where id=1 and name'alex'
 
  改
    1 update 表 set name = 'alex' where id>1
 
  查
    1 select from 
    2 select from 表 where id > 1
    3 select nid,name,gender as gg from 表 where id > 1
 

其它

一、條件
    select * from 表 where id > 1 and name != 'alex' and num = 12;
 
    select * from 表 where id between 5 and 16;
 
    select * from 表 where id in (11,22,33)
    select * from 表 where id not in (11,22,33)
    select * from 表 where id in (select nid from 表)
  二、通配符
     select from 表 where name like 'ale%'  - ale開頭的全部(多個字符串)
      select from 表 where name like 'ale_'  - ale開頭的全部(一個字符)
 
  三、限制
      select from limit 5;            - 前5行
      select from limit 4,5;          - 從第4行開始的5行
      select from limit 5 offset 4    - 從第4行開始的5行
 
  四、排序
      select from 表 order by 列 asc              - 根據 「列」 從小到大排列
      select from 表 order by 列 desc             - 根據 「列」 從大到小排列
      select from 表 order by 列1 desc,列2 asc    - 根據 「列1」 從大到小排列,若是相同則按列2從小到大排序
 
  五、分組
      select num from 表 group by num
      select num,nid from 表 group by num,nid
      select num,nid from 表  where nid > 10 group by num,nid order by nid desc
      select num,nid,count(*),sum(score),max(score),min(score) from 表 group by num,nid
 
      select num from 表 group by num having max(id) > 10
      **** 若是對於聚合函數結果進行二次篩選時,必須使用having ****

    select count(id),part_id from userinfo5 group by part_id having count(id) > 1;
    select count(id),part_id from userinfo5 where id > 0 group by part_id having count(id) > 1;sql

      特別的:group by 必須在where以後,order by以前
 
  六、連表
    select * from userinfo5,department5 where userinfo5.part_id = department5.id
    select * from department5 left join userinfo5 on userinfo5.part_id = department5.id
      # userinfo 左邊所有顯示
    select * from userinfo5 right join department5 on userinfo5.part_id = department5.id
      # department5右邊所有顯示
    select * from userinfo5 innder join department5 on userinfo5.part_id = department5.id
        #  將出現null時一行隱藏
 
      無對應關係則不顯示
      select A.num, A.name, B.name
      from A,B
      Where A.nid = B.nid
 
      無對應關係則不顯示
      select A.num, A.name, B.name
      from inner join B
      on A.nid = B.nid
 
      A表全部顯示,若是B中無對應關係,則值爲null
      select A.num, A.name, B.name
      from left join B
      on A.nid = B.nid
 
      B表全部顯示,若是B中無對應關係,則值爲null
      select A.num, A.name, B.name
      from right join B
      on A.nid = B.nid
 
  七、組合
      組合,自動處理重合
      select nickname
      from A
      union
      select name
      from B
 
      組合,不處理重合
      select nickname
      from A
      union all
      select name
      from B

 MySQL練習題數據庫

1、自行建立測試數據

2、查詢「生物」課程比「物理」課程成績高的全部學生的學號;

3、查詢平均成績大於60分的同窗的學號和平均成績; 

4、查詢全部同窗的學號、姓名、選課數、總成績;

5、查詢姓「李」的老師的個數;

6、查詢沒學過「葉平」老師課的同窗的學號、姓名;

7、查詢學過「001」而且也學過編號「002」課程的同窗的學號、姓名;

8、查詢學過「葉平」老師所教的全部課的同窗的學號、姓名;

9、查詢課程編號「002」的成績比課程編號「001」課程低的全部同窗的學號、姓名;

10、查詢有課程成績小於60分的同窗的學號、姓名;

11、查詢沒有學全全部課的同窗的學號、姓名;

12、查詢至少有一門課與學號爲「001」的同窗所學相同的同窗的學號和姓名;

13、查詢至少學過學號爲「001」同窗所選課程中任意一門課的其餘同窗學號和姓名;

14、查詢和「002」號的同窗學習的課程徹底相同的其餘同窗學號和姓名;

15、刪除學習「葉平」老師課的SC表記錄;

16、向SC表中插入一些記錄,這些記錄要求符合如下條件:①沒有上過編號「002」課程的同窗學號;②插入「002」號課程的平均成績; 

17、按平均成績從低到高顯示全部學生的「語文」、「數學」、「英語」三門的課程成績,按以下形式顯示: 學生ID,語文,數學,英語,有效課程數,有效平均分;

18、查詢各科成績最高和最低的分:以以下形式顯示:課程ID,最高分,最低分;

19、按各科平均成績從低到高和及格率的百分數從高到低順序;

20、課程平均分從高到低顯示(現實任課老師);

21、查詢各科成績前三名的記錄:(不考慮成績並列狀況) 

22、查詢每門課程被選修的學生數;

23、查詢出只選修了一門課程的所有學生的學號和姓名;

24、查詢男生、女生的人數;

25、查詢姓「張」的學生名單;

26、查詢同名同姓學生名單,並統計同名人數;

27、查詢每門課程的平均成績,結果按平均成績升序排列,平均成績相同時,按課程號降序排列;

28、查詢平均成績大於85的全部學生的學號、姓名和平均成績;

29、查詢課程名稱爲「數學」,且分數低於60的學生姓名和分數;

30、查詢課程編號爲003且課程成績在80分以上的學生的學號和姓名; 

31、求選了課程的學生人數

32、查詢選修「楊豔」老師所授課程的學生中,成績最高的學生姓名及其成績;

33、查詢各個課程及相應的選修人數;

34、查詢不一樣課程但成績相同的學生的學號、課程號、學生成績;

35、查詢每門課程成績最好的前兩名;

36、檢索至少選修兩門課程的學生學號;

37、查詢所有學生都選修的課程的課程號和課程名;

38、查詢沒學過「葉平」老師講授的任一門課程的學生姓名;

39、查詢兩門以上不及格課程的同窗的學號及其平均成績;

40、檢索「004」課程分數小於60,按分數降序排列的同窗學號;

41、刪除「002」同窗的「001」課程的成績;
練習題
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `class`
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `caption` varchar(32) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `class`
-- ----------------------------
BEGIN;
INSERT INTO `class` VALUES ('1', '三年二班'), ('2', '三年三班'), ('3', '一年二班'), ('4', '二年九班');
COMMIT;

-- ----------------------------
--  Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `fk_course_teacher` (`teacher_id`),
  CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `course`
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('1', '生物', '1'), ('2', '物理', '2'), ('3', '體育', '3'), ('4', '美術', '2');
COMMIT;

-- ----------------------------
--  Table structure for `score`
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) NOT NULL,
  `course_id` int(11) NOT NULL,
  `num` int(11) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_score_student` (`student_id`),
  KEY `fk_score_course` (`course_id`),
  CONSTRAINT `fk_score_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`cid`),
  CONSTRAINT `fk_score_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `score`
-- ----------------------------
BEGIN;
INSERT INTO `score` VALUES ('1', '1', '1', '10'), ('2', '1', '2', '9'), ('5', '1', '4', '66'), ('6', '2', '1', '8'), ('8', '2', '3', '68'), ('9', '2', '4', '99'), ('10', '3', '1', '77'), ('11', '3', '2', '66'), ('12', '3', '3', '87'), ('13', '3', '4', '99'), ('14', '4', '1', '79'), ('15', '4', '2', '11'), ('16', '4', '3', '67'), ('17', '4', '4', '100'), ('18', '5', '1', '79'), ('19', '5', '2', '11'), ('20', '5', '3', '67'), ('21', '5', '4', '100'), ('22', '6', '1', '9'), ('23', '6', '2', '100'), ('24', '6', '3', '67'), ('25', '6', '4', '100'), ('26', '7', '1', '9'), ('27', '7', '2', '100'), ('28', '7', '3', '67'), ('29', '7', '4', '88'), ('30', '8', '1', '9'), ('31', '8', '2', '100'), ('32', '8', '3', '67'), ('33', '8', '4', '88'), ('34', '9', '1', '91'), ('35', '9', '2', '88'), ('36', '9', '3', '67'), ('37', '9', '4', '22'), ('38', '10', '1', '90'), ('39', '10', '2', '77'), ('40', '10', '3', '43'), ('41', '10', '4', '87'), ('42', '11', '1', '90'), ('43', '11', '2', '77'), ('44', '11', '3', '43'), ('45', '11', '4', '87'), ('46', '12', '1', '90'), ('47', '12', '2', '77'), ('48', '12', '3', '43'), ('49', '12', '4', '87'), ('52', '13', '3', '87');
COMMIT;

-- ----------------------------
--  Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `gender` char(1) NOT NULL,
  `class_id` int(11) NOT NULL,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_class` (`class_id`),
  CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `student`
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('1', '', '1', '理解'), ('2', '', '1', '鋼蛋'), ('3', '', '1', '張三'), ('4', '', '1', '張一'), ('5', '', '1', '張二'), ('6', '', '1', '張四'), ('7', '', '2', '鐵錘'), ('8', '', '2', '李三'), ('9', '', '2', '李一'), ('10', '', '2', '李二'), ('11', '', '2', '李四'), ('12', '', '3', '如花'), ('13', '', '3', '劉三'), ('14', '', '3', '劉一'), ('15', '', '3', '劉二'), ('16', '', '3', '劉四');
COMMIT;

-- ----------------------------
--  Table structure for `teacher`
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `teacher`
-- ----------------------------
BEGIN;
INSERT INTO `teacher` VALUES ('1', '張磊老師'), ('2', '李平老師'), ('3', '劉海燕老師'), ('4', '朱雲海老師'), ('5', '李傑老師');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
創建表和插入數據
2、查詢「生物」課程比「物理」課程成績高的全部學生的學號;
  先查找每一個學生的生物成績:
  select student_id,num from score left join course on score.course_id=course.cid where course.cname='生物';
  再查找每一個學生的物理成績:
  select student_id,num from score left join course on score.course_id=course.cid where course.cname='物理';
  把兩個成績表進行合併:
  select * from
  (select student_id,num from score left join course on score.course_id=course.cid where course.cname='生物') as A
left join
  (select student_id,num from score left join course on score.course_id=course.cid where course.cname='物理') as B
  on A.student_id = B.student_id;
  最後合併:

  select A.student_id,A.num,B.num from
  (select student_id,num from score left join course on score.course_id=course.cid where course.cname='生物') as A
  left join
  (select student_id,num from score left join course on score.course_id=course.cid where course.cname='物理') as B
  on A.student_id = B.student_id
  where A.num>B.num;

三、查詢平均成績大於60分的同窗的學號和平均成績;

  先查看每一個同窗的平均分數:
  select student_id,avg(num) from score group by student_id;
  再篩選成績大於60分的同窗的學號和平均成績;
  select student_id,avg(num) as anum from score group by student_id having anum > 60;

四、查詢全部同窗的學號、姓名、選課數、總成績;

  先查看每一個同窗的總成績:
  select student_id,sum(num) from score group by student_id;
  學生和課程的關係只有成績表中存在,所以要獲取每一個學生選擇的課程,須要經過score表:
  select count(sid),student_id from score group by student_id;
  合併上面的兩步:
  select sum(num),count(sid),student_id from score group by student_id;
  將學生的信息和成績選課狀況拼在一塊兒:
  select score.student_id,student.sname,count(score.student_id),sum(score.num)
  from score left join student on score.student_id = student.sid
  group by score.student_id;

五、查詢姓「李」的老師的個數;
  select count(tid) as cou_tid from teacher where tname like '李%';

六、查詢沒學過「李平老師」課的同窗的學號、姓名;
  找到李平老師的id:  
  select tid from teacher where tname='李平老師';
  找到全部學習這門課的學生id:
  select student_id from score where course_id in
  (select cid from course where teacher_id=(select tid from teacher where tname='李平老師'));

  找到沒有學過這門課的學生對應的學生學號、姓名:
  select sid,sname from student where sid not in
  (select student_id from score where course_id in
  (select cid from course where teacher_id=(select tid from teacher where tname='李平老師')));

七、查詢學過「1」而且也學過編號「2」課程的同窗的學號、姓名;
  首先找出學過課程1的學生學號:
  select * from score where course_id = 1;
  找出學過課程2的學生學號:
  select * from score where course_id =2;
  把這兩張表按照學生的id 內鏈接起來 去掉只學習某一門課程的學生:
  select t1.student_id from
  (select student_id from score where course_id = 1)  t1
  inner join
  (select student_id from score where course_id = 2) t2
  on t1.student_id = t2.student_id;
  根據學號在學生表中找到對應的姓名:
  select t1.student_id,student.sname from (select * from score where course_id = 1) as t1
  inner join
  (select * from score where course_id =2) as t2
  on t1.student_id = t2.student_id
  left join
  student on t1.student_id = student.sid;

八、查詢學過「葉平」老師所教的全部課的同窗的學號、姓名;

九、查詢課程編號「002」的成績比課程編號「001」課程低的全部同窗的學號、姓名;
  首先查詢課程2的全部學生的成績:
  select student_id,num from course left join score on cid = course_id where course_id = 2;
  而後查詢課程1的全部學生的成績:
  select student_id,num from course left join score on cid = course_id where course_id = 1;
  把兩個表合併而且查出課程2成績比課程1成績低的學生學號:
  select * from
  (select A.student_id,A.num,B.num1 from
  (select student_id,num from course left join score on cid = course_id where course_id = 2) as A
  left join
  (select student_id,num as num1 from course left join score on cid = course_id where course_id = 1) as B
  on A.student_id = B.student_id) as C
  where C.num < C.num1;
  而後和student表合併:

    select student.sid,student.sname from
  (select * from
  (select A.student_id,A.num,B.num1 from
  (select student_id,num from course left join score on cid = course_id where course_id = 2) as A
  left join
  (select student_id,num as num1 from course left join score on cid = course_id where course_id = 1) as B
  on A.student_id = B.student_id) as C
  where C.num < C.num1) as D
  left join student
  on D.student_id=student.sid;編程

 


十、查詢有課程成績小於60分的同窗的學號、姓名;
  先查詢成績小於60分的同窗的學號:
  select student_id,num from score where num < 60;
  再查詢有課程成績小於60分的同窗的學號、姓名:
  select student.sid,student.sname from (select student_id,num from score where num < 60) as A
  left join
  student on A.student_id = student.sid;

十一、查詢沒有學全全部課的同窗的學號、姓名;

     首先查詢全部學生選修的課程數服務器

    select student_id,count(1) from score group by student_id;session

    而後查詢全部的課程數:
    select count(cid) from course;

    再進行比較:

    select student_id,count(1) from score group by student_id 

    having count(1) < (select count(cid) from course);

    最後和student表合併:
    select student.sid,student.sname from

    (select student_id,count(1) from score group by student_id 

    having count(1) < (select count(cid) from course)) as A

    left join student on student_id = student.sid;

十二、查詢至少有一門課與學號爲「001」的同窗所學相同的同窗的學號和姓名;
首先查詢學號爲1的同窗學到全部課程號:
select course_id from score where student_id=1;
而後查詢其餘同窗的課程有跟1號同窗課程同樣的同窗學號:
select student_id from score where student_id !=1 and course_id in
(select course_id from score where student_id=1) group by student_id;
最後跟student表合併:
select student.sid,student.sname from
(select student_id from score where student_id != 1 
and course_id not in
(select course_id from score where student_id = 1) group by student_id) as A
left join student on student.sid=A.student_id;

1三、查詢至少學過學號爲「001」同窗全部課的其餘同窗學號和姓名;


1八、查詢各科成績最高和最低的分:以以下形式顯示:課程ID,最高分,最低分;
首先查詢每一個課程的最高成績:
select course_id,max(num) as max_num from score group by course_id;
而後查詢每一個課程的最低成績:
select course_id,min(num) as min_num from score group by course_id;
而後合併:
select A.course_id,A.max_num,B.min_num from
(select course_id,max(num) as max_num from score group by course_id) as A
left join
(select course_id,min(num) as min_num from score group by course_id) as B
on A.course_id = B.course_id;

1九、按各科平均成績從低到高和及格率的百分數從高到低順序;
select course_id, avg(num) as avgnum,sum
(case when score.num > 60 then 1 else 0 END)/count(1)*100 as percent
from score group by course_id order by avgnum asc,percent desc;
=====================================================================================
select C.course_id,C.avg_num,D.c1,D.c2 from
(select course_id,avg(num) as avg_num from score group by course_id order by avg_num asc) as C
left join
(SELECT A.course_id,A.c1,B.c2 FROM
(select course_id,count(1) as c1 from score where num > 60 group by course_id) as A
left join
(select course_id,count(1) as c2 from score where num < 60 group by course_id) as B
on a.course_id = b.course_id) as D
on C.course_id = D.course_id

20、課程平均分從高到低顯示(現實任課老師);
select B.avg_num,C.tname from
(select course_id,avg(num) as avg_num from score group by course_id order by avg_num desc) as B
left join

((select * from (select * from teacher left join course on tid=teacher_id) as A 
left join score on A.cid = score.course_id group by A.cid)) as C
on B.course_id = C.tid group by B.course_id order by B.avg_num desc

================================================================
select avg(if(isnull(score.num),0,score.num)) as A,teacher.tname from course
left join score on course.cid = score.course_id
left join teacher on course.teacher_id = teacher.tid
group by score.course_id order by A desc


2二、查詢每門課程被選修的學生數;
select course_id,count(1) from score group by course_id;

2三、查詢出只選修了一門課程的所有學生的學號和姓名;
首先查詢只選修了一門課的學生ID:
select student_id,count(1) as cou from score group by student_id having cou =1
而後合併student表:
select student.sid,student.sname from
(select student_id,count(1) as cou from score group by student_id having cou =1) as A
left join student on A.student_id=student.sid

2四、查詢男生、女生的人數;
首先分別查詢男生、女生的個數:
select sid,count(1) as c1 from student where gender = '男';
select sid,count(1) as c2 from student where gender = '女';
而後再用union進行上下鏈接表格:
select A.sid,A.c1 from
(select sid,count(1) as c1 from student where gender = '男') as A
union
select B.sid,B.c2 from
(select sid,count(1) as c2 from student where gender = '女') as B
2五、查詢姓「張」的學生名單;
select * from student where sname like '張%';

2六、查詢同名同姓學生名單,並統計同名人數;
select sid,sname,count(1) as con from student group by sname;

2七、查詢每門課程的平均成績,結果按平均成績升序排列,平均成績相同時,按課程號降序排列;
select course_id,avg(if(isnull(num),0,num)) as avg_num from score group by course_id
order by avg_num asc,avg_num asc;

2八、查詢平均成績大於85的全部學生的學號、姓名和平均成績;
首先查詢平均成績大於85的全部同窗:
select student_id,avg(num) as avg_num from score group by student_id having avg_num > 85;
而後和student表進行合併:
select student.sid,student.sname,A.avg_num from
(select student_id,avg(num) as avg_num from score group by student_id having avg_num > 85) as A
left join student on A.student_id = student.sid;

2九、查詢課程名稱爲「生物」,且分數低於60的學生姓名和分數;
首先查詢生物課程的課程ID:
select cid from course where cname = '生物';
而後查詢成績低於60的學生學號和成績:
select student_id,score.num from
(select cid from course where cname = '生物') as A left join score on A.cid = score.course_id
where score.num < 60;
再和student表進行合併:
select student.sname,B.num from
(select student_id,score.num from
(select cid from course where cname = '生物') as A left join score on A.cid = score.course_id
where score.num < 60) as B
left join student on B.student_id = student.sid;





 

Python操做MySQL

下載安裝

pip3 install pymysql -i https://pypi.douban.com/simple

使用操做

import pymysql # 建立鏈接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='t1') # 建立遊標
cursor = conn.cursor() # 執行SQL,並返回收影響行數
effect_row = cursor.execute("update hosts set host = '1.1.1.2'") # 執行SQL,並返回受影響行數 #effect_row = cursor.execute("update hosts set host = '1.1.1.2' where nid > %s", (1,))
  
# 執行SQL,並返回受影響行數 #effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)])
   
# 提交,否則沒法保存新建或者修改的數據
conn.commit() # 關閉遊標
cursor.close() # 關閉鏈接
conn.close()


import pymysql
user = input("username:")
pwd = input("password:")
conn = pymysql.connect(host="localhost",user='root',password='',database="db1")
cursor = conn.cursor()
sql = "select * from userinfo where username=%s and password=%s"
cursor.execute(sql,(user,pwd))
# cursor.execute(sql,[user,pwd])
# cursor.execute(sql,{'u':user,'p':pwd})
result = cursor.fetchone()
cursor.close()
conn.close()
if result:
print('登陸成功')
else:
print('登陸失敗')

插入數據
import pymysql
conn = pymysql.connect(host='localhost',user = 'root',password='',database='db1')
cursor = conn.cursor()
sql = "insert into userinfo(username,password) values('jinboss','123')"
r = cursor.execute(sql)
conn.commit()
cursor.close()
conn.close()

獲取查詢數據

import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='t1') cursor = conn.cursor() cursor.execute("select * from hosts") # 獲取第一行數據
row_1 = cursor.fetchone() # 獲取前n行數據 # row_2 = cursor.fetchmany(3) # 獲取全部數據 # row_3 = cursor.fetchall()
 conn.commit() cursor.close() conn.close()

獲取新建立數據自增ID

import pymysql conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1') cursor = conn.cursor() cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)]) conn.commit() cursor.close() conn.close() # 獲取最新自增ID
new_id = cursor.lastrowid

  注:在fetch數據時按照順序進行,可使用cursor.scroll(num,mode)來移動遊標位置,如:

    cursor.scroll(1,mode='relative')  # 相對當前位置移動

    cursor.scroll(2,mode='absolute') # 相對絕對位置移動

fetch數據類型

  關於默認獲取的數據是元祖類型,若是想要或者字典類型的數據,即:

import pymysql
conn
= pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='t1') # 遊標設置爲字典類型 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) r = cursor.execute("call p1()") result = cursor.fetchone() conn.commit() cursor.close() conn.close()

 視圖

視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,併爲其命名】,用戶使用時只需使用【名稱】便可獲取結果集,並能夠將其看成表來使用。

1、建立視圖
    --格式:create view 視圖名稱 as SQL語句;
    create view v1 as select * from A where nid > 3;
    PS:虛擬
二、修改視圖
    --格式:alter view 視圖名稱 as SQL語句;
    alter view v1 as select A.nid,B.name from A left join B on A.id = B.id
    left join C on A.id = C.id where A.id > 2 and C.nid < 5;
三、刪除視圖
    drop view 視圖名稱;
    drop view v1;
四、使用視圖
    使用視圖時,將其看成表進行操做便可,因爲視圖是虛擬表,因此沒法使用其對真實表進行建立、更新和刪除操做,僅能作查詢用。
    select * from v1;

觸發器

對某個表進行【增/刪/改】操做的先後若是但願觸發某個特定的行爲時,可使用觸發器,觸發器用於定製用戶對錶的行進行【增/刪/改】先後的行爲。

delimiter //
create trigger t1 before insert on student for each row begin
        insert into teacher(tname) values(new.sname); end // delimiter; insert into student(gender,class_id,sname) values('',1,'小明'),('',1,'小花');
-- new,代指新數據
-- old,代指老數據

函數

MySQL提供了不少內置函數,例如:

CHAR_LENGTH(str)
        返回值爲字符串str 的長度,長度的單位爲字符。一個多字節字符算做一個單字符。
        對於一個包含五個二字節字符集, LENGTH()返回值爲 10, 而CHAR_LENGTH()的返回值爲5。

    CONCAT(str1,str2,...)
        字符串拼接
        若有任何一個參數爲NULL ,則返回值爲 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字符串拼接(自定義鏈接符)
        CONCAT_WS()不會忽略任何空字符串。 (然而會忽略全部的 NULL)。

    CONV(N,from_base,to_base)
        進制轉換
        例如:
            SELECT CONV('a',16,2); 表示將 a 由16進制轉換爲2進制字符串表示

    FORMAT(X,D)
        將數字X 的格式寫爲'#,###,###.##',以四捨五入的方式保留小數點後 D 位, 並將結果以字符串的形式返回。若  D 爲 0, 則返回結果不帶有小數點,或不含小數部分。
        例如:
            SELECT FORMAT(12332.1,4); 結果爲: '12,332.1000'
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字符串
            pos:要替換位置其實位置
            len:替換的長度
            newstr:新字符串
        特別的:
            若是pos超過原字符串長度,則返回原字符串
            若是len超過原字符串長度,則由新字符串徹底替換
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一個出現位置。

    LEFT(str,len)
        返回字符串str 從開始的len位置的子序列字符。

    LOWER(str)
        變小寫

    UPPER(str)
        變大寫

    LTRIM(str)
        返回字符串 str ,其引導空格字符被刪除。
    RTRIM(str)
        返回字符串 str ,結尾空格字符被刪去。
    SUBSTRING(str,pos,len)
        獲取字符串子序列

    LOCATE(substr,str,pos)
        獲取子序列索引位置

    REPEAT(str,count)
        返回一個由重複的字符串str 組成的字符串,字符串str的數目等於count 。
        若 count <= 0,則返回一個空字符串。
        若str 或 countNULL,則返回 NULLREPLACE(str,from_str,to_str)
        返回字符串str 以及全部被字符串to_str替代的字符串from_str 。
    REVERSE(str)
        返回字符串 str ,順序和字符順序相反。
    RIGHT(str,len)
        從字符串str 開始,返回從後邊開始len個字符組成的子序列

    SPACE(N)
        返回一個由N空格組成的字符串。

    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不帶有len 參數的格式從字符串str返回一個子字符串,起始於位置 pos。帶有len參數的格式從字符串str返回一個長度同len字符相同的子字符串,起始於位置 pos。 使用 FROM的格式爲標準 SQL 語法。也可能對pos使用一個負值。倘若這樣,則子字符串的位置起始於字符串結尾的pos 字符,而不是字符串的開頭位置。在如下格式的函數中能夠對pos 使用一個負值。

        mysql> SELECT SUBSTRING('Quadratically',5);
            -> 'ratically'

        mysql> SELECT SUBSTRING('foobarbar' FROM 4);
            -> 'barbar'

        mysql> SELECT SUBSTRING('Quadratically',5,6);
            -> 'ratica'

        mysql> SELECT SUBSTRING('Sakila', -3);
            -> 'ila'

        mysql> SELECT SUBSTRING('Sakila', -5, 3);
            -> 'aki'

        mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
            -> 'ki'

    TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) TRIM(remstr FROM] str)
        返回字符串 str , 其中全部remstr 前綴和/或後綴都已被刪除。若分類符BOTH、LEADIN或TRAILING中沒有一個是給定的,則假設爲BOTH 。 remstr 爲可選項,在未指定狀況下,可刪除空格。

        mysql> SELECT TRIM('  bar   ');
                -> 'bar'

        mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
                -> 'barxxx'

        mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
                -> 'bar'

        mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
                -> 'barx'

部份內置函數
View Code
select ctime,count(1) from blod group ctime
select date_format(ctime,"%Y-%m"),count(1) from blog group date_format(ctime,"%Y-%m");
2018-11-1 1
2018-11-2 1 ------> 2018-11 2
2018-10-1 1 ------> 2018-10 2
2018-10-2 1

自定義函數(有返回值):

    delimiter \\

        create function fa(

            i1 int,

            i2 int)

        return int

        begin

            declare num int default 0;

            set num = i1 + i2;

            return(num);

        end \\

    delimiter;

執行函數:

    select f1(1,100);

    獲取返回值:

    declare @i varchar(32);

    select upper('alex') into @i;

    select @i;

    在查詢中使用:
    select f1(l1,nid),name from tb2;

存儲過程

保存在MySQL上的一個別名 => 一坨SQL語句 別名() 用於替代程序員寫SQL語句
方式一: MySQL:存儲過程 程序:調用存儲過程 方式二: MySQL:不執行 程序:寫SQL語句 方式三: MySQL:不執行 程序員:類和對象(SQL語句)
1、簡單
     -- 建立存儲過程:
     delimiter \\
create procedure p1() begin select * from student; insert into teacher(tname) values("ct"); end \\
     delimiter ;
     -- 執行存儲過程:
     call p1()
      pymysql: cursor.callproc('p1')

二、傳參數(in,out,inout)
    delimiter //
    create procedure p1(
        in n1 int,
        in n2 int
    )
    begin
        select * from student where sid > n1;
    end //
    delimiter ;
    
    call p2(12,2)
    pymysql: cursor.callproc('p2',(12,2))

三、參數 out
    delimiter //
    create procedure p3(
        in n1 int,
        inout n2 int
    )
    begin
        set n2 = 123;
        select * from student where sid > n1;
    end //
    delimiter ;
    set @ v1 = 10;
    call p2(12,@v1)
    selecr @v1;

    set @_p3_0 =12
    set @-p3_1 =2
    call p3(@-p3_0,@-p3_1)
    select @_p3_0,@_p3_1

    pymysql: cursor.callproc('p3',(12,2))
    r1 = cursor.fetchall()
    print(r1)

    cursor.execute('select @_p3_0,@_p3_1')
    r2 = cursor.fetchall()
    print(r2)
    
    ======> 特殊
        可傳參:in out inout
            cursor.callproc('p3',(12,2))
            1 = cursor.fetchall()
            print(r1)
        
            cursor.execute('select @_p3_0,@_p3_1')
            r2 = cursor.fetchall()
            print(r2)
    爲何有結果集又有out僞造的返回值?
        delimiter //
        create procedure p3(
        in n1 int,
        out n2 int  用於標識存儲過程的執行結果  1,2
        )
        begin
            insert into vv(..)
            insert into vv(..)
            insert into vv(..)
        end //
        delimiter ;
四、事務

    delimiter //
    create procedure p4(
         out status int
    )
    begin
        1. 聲明若是出現異常則執行{
        set status = 1;
        rollback;
        }

        開始事務
            -- 由秦兵帳戶減去100
            -- 方少偉帳戶加90
            -- 張根帳戶加10
            commit;
        結束
        set status = 2;

    end //

    delimiter;

    ==========================================

    delimiter \\
    create PROCEDURE p5(
        OUT p_return_code tinyint
    )
    BEGIN
      DECLARE exit handler for sqlexception
      BEGIN
        -- ERROR
        set p_return_code = 1;
        rollback;
    END;

    START TRANSACTION;
        DELETE from tb1;
        insert into tb2(name)values('seven');
    COMMIT;

    -- SUCCESS
    set p_return_code = 2;

    END\\
    delimiter ;

 

五、遊標

    delimiter //
    create procedure p6()
    begin
        declare row_id int; -- 自定義變量1
        declare row_num int; -- 自定義變量2
        declare done INT DEFAULT FALSE;
        declare temp int;

        declare my_cursor CURSOR FOR select id,num from A;
        declare CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

        open my_cursor;
            xxoo: LOOP
            fetch my_cursor into row_id,row_num;
            if done then
                leave xxoo;
            END IF;
            set temp = row_id + row_num;
            insert into B(number) values(temp);
        end loop xxoo;
        close my_cursor;
    end //
    delimter ;

 

六、動態執行SQL(防SQL注入)   

    delimiter //
    create procedure p7(
        in tpl varchar(255),
        in arg int
    )
    begin
        1. 預檢測某個東西 SQL語句合法性
        2. SQL =格式化 tpl + arg
        3. 執行SQL語句

        set @xo = arg;
        PREPARE xxx FROM 'select * from student where sid > ?';
        EXECUTE xxx USING @xo;
        DEALLOCATE prepare prod;
    end //
    delimter ;

    call p7("select * from tb where id > ?",9)

    =======>

    delimiter \\
    CREATE PROCEDURE p8 (
        in nid int
    )
    BEGIN
        set @nid = nid;
        PREPARE prod FROM 'select * from student where sid > ?';
        EXECUTE prod USING @nid;
        DEALLOCATE prepare prod;
    END\\
    delimiter ;

 

 

 索引

索引,是數據庫中專門用於幫助用戶快速查詢數據的一種數據結構,相似於字典中的目錄,查找字典內容時能夠根據目錄查找到數據的存放位置,而後直接獲取便可。

插入10000條數據測試:

import pymysql
i = 1
while True:
    name = 'alex'+str(i)
    email = 'alex%s@qq.com'%i
    if i%2==1:
        gender = ''
    else:
        gender = ''

    conn = pymysql.connect(host='localhost',user = 'root',password='',database='db2')
    cursor = conn.cursor()
    sql = "insert into userinfo(name,email,gender) values(%s,%s,%s)"
    r = cursor.executemany(sql,[(name,email,gender)])
    conn.commit()
    i+=1
    if i==10001:break
    cursor.close()
    conn.close()
插入數據
做用: -- 約束
        -- 加速查找
索引:
       -- 主鍵索引:加速查找 + 不能爲空 + 不能重複
        -- 普通索引:加速查找
        -- 惟一索引:加速查找 + 不能重複
        -- 聯合索引(多列):
                    -- 聯合主鍵索引
                    -- 聯合惟一索引
                    -- 聯合普通索引
 -- 無索引:從前到後依次查找

索引種類(某種格式存儲):
    hash索引:
        單值快,範圍值慢
    btree索引:二叉樹

創建索引:

    -- 額外的文件保存特殊的數據結構

    -- 查詢快;插入更新和刪除慢

    -- 命中索引

            select * from userinfo3 where email='alex';

            select * from userinfo3 where email like 'alex';  -- 慢

主鍵索引

建立表和建立主鍵:

create
table in1( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) ) ==================================== create table in1( nid int not null auto_increment, name varchar(32) not null, email varchar(64) not null, extra text, primary key(ni1), index ix_name (name) )

建立主鍵:
alter table 表名 add primary key(列名);

刪除主鍵:
alter table 表名 drop primary key;
alter table 表名  modify  列名 int, drop primary key;

 

普通索引:

建立表和索引:
        create table in1( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) )

建立索引:
       create index 索引名稱 on 表名(列名) create index index_name on table_name(column_name)

查看索引:
       show index from table_name;   

刪除索引; -- drop index 索引名稱 on 表名
        show index from table_name;        

 

惟一索引

建立表和惟一索引:
create table in1( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text, unique ix_name (name)
)

建立惟一索引:
 create unique index 索引名稱 on 表名(列名)

刪除惟一索引:
 drop unique index 索引名稱 on 表名        

 

組合索引(最左前綴匹配)

建立表:
create table in3( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text ) 
建立組合索引:
     create unique index 索引名稱 on 表名(列名,列名) create index ix_name_email on in3(name,email); — 最左前綴匹配: select * from userinfo3 where name = 'alex'; select * from userinfo3 where name = 'alex' and email = 'asdf'; 組合索引效率 > 索引合併 組合索引 — (name,email) select  * from userinfo3 where name='alex' and email='asdf';   select  * from userinfo3 where name='alex'; 
    索引合併 — name,— email     
select * from userinfo3 where name='alex' and email='asdf';     select * from userinfo3 where name='alex';     select * from userinfo3 where email='alex'
; 名詞: 覆蓋索引: — 在索引文件中直接獲取數據 索引合併: — 把多個單列索引合併使用

頻繁查找的列建立索引

    —  建立索引

    —  命中索引 ******

正確使用索引:
數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,若是以錯誤的方式使用,則即便創建索引也會不奏效。
即便創建索引,索引也不會生效:

—— like '%xx'
    select * from tb1 where name like '%cn'; —— 使用函數 select * from tb1 where reverse(name) = 'wupeiqi'; —— or
    select * from tb1 where nid = 1 or email = 'seven@live.com'; 特別的:當or條件中有未創建索引的列才失效,如下會走索引 select * from tb1 where nid = 1 or name = 'seven'; select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex' —— 類型不一致 若是列是字符串類型,傳入條件是必須用引號引發來,否則... select * from tb1 where name = 999; —— !=
    select * from tb1 where name != 'alex' 特別的:若是是主鍵,則仍是會走索引 select * from tb1 where nid != 123 —— >
    select * from tb1 where name > 'alex' 特別的:若是是主鍵或索引是整數類型,則仍是會走索引 select * from tb1 where nid > 123
        select * from tb1 where num > 123 —— order by
    select email from tb1 order by name desc; 當根據索引排序時候,選擇的映射若是不是索引,則不走索引 特別的:若是對主鍵排序,則仍是走索引: select * from tb1 order by nid desc; —— 組合索引最左前綴 若是組合索引爲:(name,email) name and email       -- 使用索引
    name                 -- 使用索引
    email                -- 不使用索引

 

時間

執行計劃:讓mysql預估執行操做(通常正確)
   all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const 慢: select * from userinfo3 where name = 'alex' explain select * from userinfo3 where name = 'alex' type:ALL(全表掃描) select * from userinfo3 limit1;(快) 快: select * from userinfo3 where email = 'alex' type:const(走索引)

執行計劃

explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息能夠進行SQL優化

id
        查詢順序標識
            如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |    9 | NULL        |
            |  2 | DERIVED     | tb1        | range | PRIMARY       | PRIMARY | 8       | NULL |    9 | Using where |
            +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
        特別的:若是使用union鏈接氣值可能爲null


    select_type
        查詢類型
            SIMPLE          簡單查詢
            PRIMARY         最外層查詢
            SUBQUERY        映射爲子查詢
            DERIVED         子查詢
            UNION           聯合
            UNION RESULT    使用聯合的結果
            ...
    table
        正在訪問的表名


    type
        查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
            ALL             全表掃描,對於數據表從頭至尾找一遍
                            select * from tb1;
                            特別的:若是有limit限制,則找到以後就不在繼續向下掃描
                                   select * from tb1 where email = 'seven@live.com'
                                   select * from tb1 where email = 'seven@live.com' limit 1;
                                   雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就再也不繼續掃描。

            INDEX           全索引掃描,對索引從頭至尾找一遍
                            select nid from tb1;

            RANGE          對索引列進行範圍查找
                            select *  from tb1 where name < 'alex';
                            PS:
                                between and
                                in
                                >   >=  <   <=  操做
                                注意:!=> 符號


            INDEX_MERGE     合併索引,使用多個單列索引搜索
                            select *  from tb1 where name = 'alex' or nid in (11,22,33);

            REF             根據索引查找一個或多個值
                            select *  from tb1 where name = 'seven';

            EQ_REF          鏈接時使用primary key 或 unique類型
                            select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;



            CONST           常量
                            表最多有一個匹配行,由於僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,由於它們只讀取一次。
                            select nid from tb1 where nid = 2 ;

            SYSTEM          系統
                            表僅有一行(=系統表)。這是const聯接類型的一個特例。
                            select * from (select nid from tb1 where nid = 1) as A;
    possible_keys
        可能使用的索引

    key
        真實使用的

    key_len
        MySQL中使用索引字節長度

    rows
        mysql估計爲了找到所需的行而要讀取的行數 ------ 只是預估值

    extra
        該列包含MySQL解決查詢的詳細信息
        「Using index」
            此值表示mysql將使用覆蓋索引,以免訪問表。不要把覆蓋索引和index訪問類型弄混了。
        「Using where」
            這意味着mysql服務器將在存儲引擎檢索行後再進行過濾,許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where子句的查詢都會顯示「Using where」。有時「Using where」的出現就是一個暗示:查詢可受益於不一樣的索引。
        「Using temporary」
            這意味着mysql在對查詢結果排序時會使用一個臨時表。
        「Using filesort」
            這意味着mysql會對結果使用一個外部索引排序,而不是按索引次序從表裏讀取行。mysql有兩種文件排序算法,這兩種排序方式均可以在內存或者磁盤上完成,explain不會告訴你mysql將使用哪種文件排序,也不會告訴你排序會在內存裏仍是磁盤上完成。
        「Range checked for each record(index map: N)」
            這個意味着沒有好用的索引,新的索引將在聯接的每一行上從新估算,N是顯示在possible_keys列中索引的位圖,而且是冗餘的。
執行計劃

 

DBA工做

慢日誌
            - 執行時間 > 10
            - 未命中索引 - 日誌文件路徑 配置: - 內存 show variables like '%query%'
                set global 變量名 =- 配置文件 mysqld --defaults-file='E:\wupeiqi\mysql-5.7.16-winx64\mysql-5.7.16-winx64\my-default.ini'
 my.conf內容: slow_query_log = ON slow_query_log_file = D:/.... 注意:修改配置文件以後,須要重啓服務

 

****** 分頁 *******

    select * from userinfo3 limit 20,10;

面試問:
         — 網頁中只顯示有限個數據 — 索引表中掃描 select * from userinfo3 where id in(select id from userinfo3 limit 200000,10);
      — id不連續,因此沒法直接使用id範圍進行查找
     — 方案: 記錄當前頁最大或最小ID 
        1、頁面只有上一頁,下一頁
            max_id
            min_id


上一頁:
select * from userinfo3 where id > max_id limit 10;
    select * from tb1 where 
    nid < (select nid from (select nid from tb1 where nid < 當前頁最小值 order by nid desc
    limit 每頁數據 *【頁碼-當前頁】) A order by A.nid asc limit 1)  
    order by nid desc limit 10;
======================================================================== 
    select * from tb1 where 
    nid < (select nid from (select nid from tb1 where nid < 970  order by nid desc
    limit 40) A order by A.nid asc limit 1) 
    order by nid desc limit 10;

下一頁;
select * from userinfo3 where id < min_id order by id desc linit 10;

    select * from tb1 where 
    nid < (select nid from (select nid from tb1 where nid > 當前頁最大值 order by nid asc 
    limit 每頁數據 *【當前頁-頁碼】) A order by A.nid asc limit 1) 
    order by nid desc limit 10;
=================================================================
    select * from tb1 where
    nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc
    limit 20) A order by A.nid desc limit 1) 

        
2、上一頁 192 193 194 195 [196] 197 198 199 下一頁:     select * from userinfo where id in     (select id from (select id from userinfo3 where id > max_id limit 30)     as N order by N.id desc limit 10)

 類和麪向對象回顧

1、函數編程:數據和邏輯分離
        a = 123
        b = 456
        c = 789
        def exc3(proc_name):
                callproc(xxx)
                return xxx
        def exc4(proc_name):
                callproc(xxx)
                return xxx
2、面向對象:數據和邏輯(屬性和行爲)組合在一塊兒
        class SqlHelper:
                self.host = ''
                self.port = ''
                self.db = ''
        def exc1(self,SQL):
                # 鏈接
                conn(self.host,)
                execute('inser')
                return xx
        def exc2(self,proc_name):
                callproc(xxx)
                return xxx
        一類事物共同具備:屬性和行爲
        class Person:
                def __init__(self,name):
                        self.name = name
                def speak(self):
                        pass
        1、提取共性
        2、分類
        三、模板"約束"
        4、當一類函數公用一樣參數時候,能夠轉變成類進行 — 分類
                面向對象:數據和邏輯(屬性和行爲)組合在一塊兒
                函數編程:數據和邏輯分離
3、分類示例:
        類 = 表       對象 =class Userinfo:
                def __init__(self,id,name):
                        """'約束'每一個對象中只有兩個字段,即:每一個行數據都有id和name列"""
                        self.id = id
                        self.name = name
                def add(self,name):
                        pass
        # row1 = Userinfo(1,'alex') # 第一行
        # row2 = Userinfo(2,'alex') # 第二行
特殊方法:(比較重要的幾個「雙下方法」)
        class Foo:
                def __init__(self,name):
                        self.name = name
                def show(self):
                        print (self.name)
                def __call__(self):
                        pass
                def __getitem__(self,key):
                        pass
                def __setitem__(self,key,value):
                        pass
                def __delitem__(self,key):
                        pass
        obj1 = Foo('erio')
        obj1()
        obj1['k']
        obj1['k'] = 123
        del obj1[k]
        obj.__dict__                      

ORM框架:SQLAlchemy

    — 做用:

        一、提供簡單的規則

        二、自動轉換成SQL語句

    — DB first:手動建立數據庫以及表   —> ORM框架  —>自動生成類

    — code first:手動建立類和數據庫  —> ORM框架  —>自動生成表

    — 功能

        — 建立數據庫表

            — 鏈接數據庫(非SQLAlchemyl鏈接,是由pysql,mysqldb,等鏈接)

        — 操做數據行

            增

            刪

            改

            查

建立表

建立單表

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,UniqueConstraint,Index
from sqlalchemy.orm import sessionmaker,relationship
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db5',max_overflow=5)
Base = declarative_base()

#建立單表
class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    extra = Column(String(16))

    __table_args__ = (
        UniqueConstraint('id','name',name='uix_id_name'),
        Index('ix_id_name','name','extra')
    )
def init_db():
    Base.metadata.create_all(engine)

def drop_db():
    Base.metadata.drop_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

# 插入數據
obj = User(name='alex1',extra='鑽石玩家')
session.add(obj)
session.add_all([
    User(name='alex2',extra='鉑金玩家'),
    User(name='alex3',extra='黑金玩家')
])
session.commit()

一對多

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,UniqueConstraint,Index
from sqlalchemy.orm import sessionmaker,relationship
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db5',max_overflow=5)
Base = declarative_base()

#一對多
class Favors(Base):
    __tablename__ = 'favors'
    nid = Column(Integer,primary_key=True)
    caption = Column(String(50),default='red',unique=True)

class Persons(Base):
    __tablename__ = 'persons'
    nid = Column(Integer,primary_key=True)
    name = Column(String(32),index=True,nullable=True)
    favors_id = Column(Integer,ForeignKey('favors.nid'))

def init_db():
    Base.metadata.create_all(engine)

def drop_db():
    Base.metadata.drop_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

#插入數據
obj = Favors(caption='普通用戶')
session.add(obj)
session.add_all([
    Favors(caption='鉑金用戶'),
    Favors(caption='黑金用戶')
])
session.commit()

多對多

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,UniqueConstraint,Index
from sqlalchemy.orm import sessionmaker,relationship
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:@127.0.0.1:3306/db5',max_overflow=5)
Base = declarative_base()

#多對多
class Groups(Base):
    __tablename__ = 'groups'
    id = Column(Integer,primary_key=True)
    name = Column(String(64),unique=True,nullable=False)
    port = Column(Integer,default=22)

class Servers(Base):
    __tablename__ = 'servers'
    id = Column(Integer,primary_key=True,autoincrement=True)
    hostname = Column(String(32),unique=True,nullable=False)

class ServersToGroups(Base):
    __tablename__ = 'serverstogroups'
    nid = Column(Integer,primary_key=True,autoincrement=True)
    servers_id = Column(Integer,ForeignKey('servers.id'))
    group_id = Column(Integer,ForeignKey('groups.id'))


def init_db():
    Base.metadata.create_all(engine)

def drop_db():
    Base.metadata.drop_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

# 插入數據
obj = Servers(hostname='少司命')
session.add(obj)
session.add_all([
    Servers(hostname='項羽'),
    Servers(hostname='高月')
])
session.commit()

# print(session.query(UserType))
# user_type_list = session.query(UserType).all()
# for row in user_type_list:
#     print(row.id,row.title)

# select xxx  UserType where
# user_type_list = session.query(UserType.id,UserType.title).filter(UserType.id > 2)
# for row in user_type_list:
#     print(row.id,row.title)

刪除

session.query(UserType.id,UserType.title).filter(UserType.id > 2).delete()

修改

# session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({"title" : "黑金"})
# session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({UserType.title: UserType.title + "x"}, synchronize_session=False)
# session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({"num": Users.num + 1}, synchronize_session="evaluate")

其餘

# 分組,排序,連表,通配符,子查詢,limit,union,where,原生SQL、
# ret = session.query(Users, UserType)
# select * from user,usertype;
#
# ret = session.query(Users, UserType).filter(Users.usertype_id==UserType.id)
# select * from user,usertype whre user.usertype_id = usertype.id

# result = session.query(Users).join(UserType)
# print(result)

# result = session.query(Users).join(UserType,isouter=True)
# print(result)


# 1.
# select * from b where id in (select id from tb2)

# 2 select * from (select * from tb) as B
# q1 = session.query(UserType).filter(UserType.id > 0).subquery()
# result = session.query(q1).all()
# print(result)

# 3
# select
#   id ,
#   (select * from users where users.user_type_id=usertype.id)
# from usertype;

# session.query(UserType,session.query(Users).filter(Users.id == 1).subquery())
# session.query(UserType,Users)
# result = session.query(UserType.id,session.query(Users).as_scalar())
# print(result)
# result = session.query(UserType.id,session.query(Users).filter(Users.user_type_id==UserType.id).as_scalar())
# print(result)


# 問題1. 獲取用戶信息以及與其關聯的用戶類型名稱(FK,Relationship=>正向操做)
# user_list = session.query(Users,UserType).join(UserType,isouter=True)
# print(user_list)
# for row in user_list:
#     print(row[0].id,row[0].name,row[0].email,row[0].user_type_id,row[1].title)

# user_list = session.query(Users.name,UserType.title).join(UserType,isouter=True).all()
# for row in user_list:
#     print(row[0],row[1],row.name,row.title)


# user_list = session.query(Users)
# for row in user_list:
#     print(row.name,row.id,row.user_type.title)


# 問題2. 獲取用戶類型
# type_list = session.query(UserType)
# for row in type_list:
#     print(row.id,row.title,session.query(Users).filter(Users.user_type_id == row.id).all())

# type_list = session.query(UserType)
# for row in type_list:
#     print(row.id,row.title,row.xxoo)參考:https://www.cnblogs.com/wupeiqi/articles/5713330.html
相關文章
相關標籤/搜索