MySQL 基本操作

 数据库的基本概念

数据

l  描述事物的符号记录称为数据(Data)

l  包括数字,文字、图形、图像、声音、档案记录等

l  以“记录”形式按统一的格式进行存储

数据表

l  将不同的记录组织在一起,就形成了 “表”

l  是用来存储具体数据的

数据库

l  数据库就是表的集合,是存储数据表的仓库

l  以一定的组织方式存储的相互有关的数据

   MySQL 数据库系统也是典型的C/S(客户端/服务器)架构的应用,连接时需要专用的客户端工具,Linux下通过mysql命令工具(如果是通过rpm格式安装软件需要安装mysql软件包)。

 
  连接并登录到MySQL操作环境
  mysql
     -u 指定用户名
     -p 指定密码(选项和密码之间不能有空格)
     -h 指定主机
     -P 指定端口
     -S 指定Socket文件
     -e 指定SQL命令语句(非交互模式)
 

SQL及其规范

 
<1> 在数据库系统中,SQL语句不区分大小写(建议用大写) 。但字符串常量区分大小写。建议命令大写,表名库名小写;

<2> SQL语句可单行或多行书写,以“;”结尾。关键词不能跨多行或简写。

<3> 用空格和缩进来提高语句的可读性。子句通常位于独立行,便于编辑,提高可读性。

SELECT * FROM tb_table
            WHERE NAME="YUAN";
<4> 注释:单行注释:-- 多行注释:/*......*/ <5>sql语句可以折行操作
 

SQL语句分类:

1、数据定义语言(DDL)

创建、修改或删除数据库中各种对象,包括表、视图、索引等。

命令:CREATE TABLE , CREATE VIEW, CREATE INDEX、ALTER TABLE ,

DROP TABLE , DROP VIEW, DROP INDEX

 

2、查询语言(DQL)

按照指定的组合、条件表达式或排序检索已存在的数据库中数据,

不改变数据库中数据。

命令:SELECT…FROM…WHERE…

 

3、数据操纵语言(DML)

对已经存在的数据库进行元组的插入、删除、修改等操作

命令:INSERT、UPDATE、DELETE

 

4、数据控制语言(DCL)

用来授予或收回访问数据库的某种特权、

控制数据操纵事务的发生时间及效果、对数据库进行监视

命令:GRANT、REVOKE、COMMIT、ROLLBACK 

数据库操作

库名的命令规则:首字符是字母,其余部分可以是字母、数字、下划线、@、$

不能是关键字,如create database table,最长128位,不能是纯数字

 
   查询所有库
   show databases;
   
   mysql> show databases;
   +--------------------+
   | Database           |
   +--------------------+
   | information_schema |               #虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数(用户表信息,列信息,权限信息,字符信息),存放于内存中
   | mysql              |               #授权库,存放mysql所有的授权信息
   | performance_schema |               #存放mysql服务的性能参数
   | test               |               #测试库
   +--------------------+
   5 rows in set (0.00 sec)
  
   创建库
   create database  数据库名;
 
   查看某一个数据库
   show create database  数据库名;
示例: mysql> create database xixi; Query OK, 1 row affected (0.00 sec) mysql> show create database xixi; +----------+------------------------------------------------------------------+ | Database | Create Database | +----------+------------------------------------------------------------------+ | xixi | CREATE DATABASE `xixi` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ | +----------+------------------------------------------------------------------+ 1 row in set (0.00 sec) 登录使用数据库 use 库名;
查看当前使用的库 select database();
示例: mysql> use xixi; Database changed mysql> select database(); +------------+ | database() | +------------+ | xixi | +------------+ 1 row in set (0.00 sec) 修改:alter 删除库 drop database 数据库名;
示例: mysql> drop database xixi; Query OK, 0 rows affected (0.01 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.00 sec)
 

mysql数据库类型

数值类型

下面的表显示了需要的每个整数类型的存储和范围。

MySQL 基本操作

日期 /时间类型

 MySQL 基本操作

字符串类型

字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

MySQL 基本操作

    CHAR和VARCHAR类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。

    BINARY和VARBINARY类类似于CHAR和VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。

    BLOB是一个二进制大对象,可以容纳可变数量的数据。有4种BLOB类型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。

    有4种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。这些对应4种BLOB类型,有相同的最大长度和存储需求。

 

数据表操作

1 我们需要进入某一个库里才能创建表
2 一张表必须属于一个库
3 表分成:字段+数据记录

 

 
 
  创建表
create table 表名 (
                            字段名1  类型 (宽度) 约束条件,
                            字段名2  类型(宽度)  约束条件,
                            字段名3  类型(宽度)  约束条件,
                            .......
                            );
                             
注:
同一张表中,字段名不能相同
字段名和类型必须有宽度和约束条件为可选项
最后一个字段不加 “,”
示例: mysql> create table host ( -> id int(10) not null, -> hostname char(20) default '', -> primary key(id) -> ); Query OK, 0 rows affected (0.11 sec)
 
 
  查看某个库有多少表,先进入库
  show  tables;
查看某个新建表信息 show create table 表名;
查看表结构 desc 表名; describe 库名.表名;
查看表的所有字段内容 select * from 表名; mysql> select * from host; Empty set (0.00 sec) #表中没有内容,空集
查看表的某些字段的内容 select id from host; #查看host表的id字段的内容 select id,port from host; #查看host表的id字段和port字典的内容
查看表的某一行的内容 select * from user wherer user_name='zhangsan' #查看user表中user_name等于zhangsan的这一行的所有字段

#查看字符集是否支持中文
  show variables like 'character_set_%'; 

示例:
  mysql> show tables;
  +----------------+
  | Tables_in_xixi |
  +----------------+
  | host           |
  +----------------+
  1 row in set (0.00 sec)
   
  mysql> show create table host;
  +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
  | Table | Create Table                                                                                                                                                |
  +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
  | host  | CREATE TABLE `host` (
    `id` int(10) DEFAULT NULL,
    `hostname` char(20) DEFAULT NULL,
    `port` int(5) DEFAULT NULL
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
  +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
  1 row in set (0.00 sec)
  
  
  mysql> desc host;
  +----------+----------+------+-----+---------+-------+
  | Field    | Type     | Null | Key | Default | Extra |
  +----------+----------+------+-----+---------+-------+
  | id       | int(10)  | YES  |     | NULL    |       |
  | hostname | char(20) | YES  |     | NULL    |       |
  | port     | int(5)   | YES  |     | NULL    |       |
  +----------+----------+------+-----+---------+-------+
  3 rows in set (0.01 sec)
  field         代表字段名
  type          代表该字段类型,
  Null          该字段是否可以为空
  default       该字段的默认设置
  extra         额外的设置
  
  mysql> select * from xixi.host;
  Empty set (0.00 sec)    #empty这里表示一张空表
  
  mysql> select id,port from xixi.host;
  Empty set (0.00 sec)

  mysql> select * from user where user_name='zhangsan';

    +-----------+-------------------------------------------+
    | user_name | user_passwd |
    +-----------+-------------------------------------------+
    | zhangsan | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
    +-----------+-------------------------------------------+
    1 row in set (0.00 sec)

 
create table employee(
            id int primary key auto_increment ,
            name varchar(20),
            gender bit default 1,   -- gender char(1)  default 1   -----    或者 TINYINT(1) 
            birthday date,
            entry_date date,
            job varchar(20),
            salary double(4,2) unsigned,
            resume text    -- 注意,这里作为最后一个字段不加逗号
          );


    /* 约束:
       primary key (非空且唯一)  :能够唯一区分出当前记录的字段称为主键!
       unique
       not null
       auto_increment 主键字段必须是数字类型。
       外键约束 foreign key  */
 

设置用户权限(用户不存在时,则新建用户)

       MySQL数据库的root用户账户拥有对所有库,表的全部权限,频繁使用root账号会给数据库服务器带来一定的安全风险,实际工作中,通常会建立一些低权限的用户,只负责一部分库,表的管理和维护操作,甚至可以对查询,修改,删除记录等各种操作做进一步的细化限制,从而降低数据库的风险。

GRANT 权限列表 ON 数据库名.表名 TO 用户名@来源地址 [ IDENTIFIED BY ‘密码’ ];

l  权限列表:用于列出授权的各种数据库操作,通过逗号进行分割,如:select,insert,update等,all表示所有权限,可以执行任意操作。

l  库名.表名:用于指定授权操作的数据库和表的名称,可以使用通配符(*)表示所有

l  用户名@来源地址:用于指定用户和允许访问的客户机地址;来源地址可以是IP地址,域名,%通配符表示所有(但不能表示localhost)

MySQL通配符:

l  _:任意单个字符  192.168.1._

l  %:任意长度的任意字符 192.168.1.%

案例:

mysql> GRANT select ON crushlinux.* TO 'teacher'@'localhost' IDENTIFIED BY '123456';

使用GRANT语句授权的用户记录,会保存到mysql库的user,db,host,tables_priv等相关表中,无需刷新授权表即可生效。

查看用户的权限

SHOW GRANTS FOR 用户名@域名或IP

案例:

mysql> SHOW GRANTS FOR 'teacher'@'localhost';              

+---------------------------------------------------------+

| Grants for teacher@localhost                            |

+---------------------------------------------------------+

| GRANT USAGE ON *.* TO 'teacher'@'localhost'             |

| GRANT SELECT ON `crushlinux`.* TO 'teacher'@'localhost' |

+---------------------------------------------------------+

2 rows in set (0.00 sec)

撤销用户的权限

REVOKE 权限列表 ON 数据库名.表名 FROM 用户名@域名或IP

案例:

mysql> REVOKE all ON crushlinux.* FROM 'teacher'@'localhost';

Query OK, 0 rows affected (0.01 sec)

mysql> SHOW GRANTS FOR 'teacher'@'localhost';

+---------------------------------------------+

| Grants for teacher@localhost                |

+---------------------------------------------+

| GRANT USAGE ON *.* TO 'teacher'@'localhost' |

+---------------------------------------------+

1 row in set (0.01 sec)

显示服务器信息

mysql> status;
--------------
mysql Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using EditLine wrapper

Connection id: 29
Current database: client
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.7.24-log Source distribution
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /tmp/mysql.sock
Uptime: 2 days 42 sec

Threads: 1 Questions: 276 Slow queries: 0 Opens: 125 Flush tables: 1 Open tables: 112 Queries per second avg: 0.001
--------------

用于显示广泛的服务器状态信息

mysql> show status;

+-----------------------------------------------+--------------------------------------------------+

| Variable_name                                 | Value                                            |

+-----------------------------------------------+--------------------------------------------------+

| Aborted_clients                               | 0                                                |

| Aborted_connects                              | 0                                                | 

显示创建特定数据库或表

help create database;

help create table;

显示授权用户的安全权限

mysql> show grants;

+---------------------------------------------------------------------+

| Grants for root@localhost                                           |

+---------------------------------------------------------------------+

| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |

| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION        |

+---------------------------------------------------------------------+

2 rows in set (0.00 sec)

显示服务器错误或警告信息

show errors;

show warnings;

显示当前时间

mysql> select now();

+---------------------+

| now()               |

+---------------------+

| 2018-12-07 21:05:00 |

+---------------------+

1 row in set (0.00 sec)

显示当前用户及时间

mysql> select CURRENT_USER(),CURRENT_TIMESTAMP;

mysql> select user(),now();

授权Windows客户机地址拥有访问权限:

mysql> grant all on *.* to 'root'@'192.168.200.2' IDENTIFIED BY '123456';

Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> flush privileges;

Query OK, 0 rows affected (0.01 sec)

Windows客户机安装Navicat客户端工具

MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

 MySQL 基本操作

修改表结构(字段)

MySQL 基本操作
修改一列类型
      alter table tab_name modify 列名 类型 [完整性约束条件][first|after 字段名];
      alter table users2 modify age tinyint default 20;
      alter table users2 modify age int  after id;
   
修改列名
      alter table tab_name change [column] 列名 新列名 类型 [完整性约束条件][first|after 字段名];
      alter table users2 change age Age int default 28 first;

删除一列
      alter table tab_name drop [column] 列名;
      -- 思考:删除多列呢?删一个填一个呢?
      alter table users2 
            add salary float(6,2) unsigned not null after name,
            drop addr;    

修改表名
      rename table 表名 to 新表名;
修该表所用的字符集    
      alter table student character set utf8;

删除表
    drop table tab_name;

添加主键,删除主键
    alter table tab_name add primary key(字段名称,...) 
    alter table users drop primary key;

eg:
    mysql> create table test5(num int auto_increment);
    ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
    create table test(num int primary key auto_increment);
    -- 思考,如何删除主键?
    alter table test modify id int;   -- auto_increment没了,但这样写主键依然存在,所以还要加上下面这句
    alter table test drop primary key;-- 仅仅用这句也无法直接删除主键

-- 唯一索引
    alter table tab_name add unique [index|key] [索引名称](字段名称,...) 

    alter table users add unique(name)-- 索引值默认为字段名show create table users;
    alter table users add unique key user_name(name);-- 索引值为user_name

    -- 添加联合索引
    alter table users add unique index name_age(name,age);#show create table users;

    -- 删除唯一索引
    alter table tab_name drop {index|key} index_name
MySQL 基本操作

表记录增,删,改

MySQL 基本操作
-- 1.增加一条记录insert

      /*insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......);*/


      create table employee_new(
                 id int primary key auto_increment,
                 name varchar(20) not null unique,
                 birthday varchar(20),
                 salary float(7,2)
                             );

       insert into employee_new (id,name,birthday,salary) values
                     (1,'yuan','1990-09-09',9000);

       insert into employee_new values
       (2,'alex','1989-08-08',3000);

       insert into employee_new (name,salary) values
       ('xialv',1000);

      -- 插入多条数据
       insert into employee_new values
       (4,'alvin1','1993-04-20',3000),
       (5,'alvin2','1995-05-12',5000);

      -- set插入: insert [into] tab_name set 字段名=值

      insert into employee_new set id=12,name="alvin3";


-- 2.修改表记录  update tab_name set field1=value1,field2=value2,......[where 语句]

    /*      UPDATE语法可以用新值更新原有表行中的各列。
            SET子句指示要修改哪些列和要给予哪些值。
            WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行。*/


    update employee_new set birthday="1989-10-24" WHERE id=1;

    --- 将yuan的薪水在原有基础上增加1000元。
    update employee_new set salary=salary+4000 where name='yuan';

-- 3.删除表纪录

     delete from tab_name [where ....]

        /*    如果不跟where语句则删除整张表中的数据
            delete只能用来删除一行记录
            delete语句只能删除表中的内容,不能删除表本身,想要删除表,用drop
            TRUNCATE TABLE也可以删除表中的所有数据,词语句首先摧毁表,再新建表。此种方式删除的数据不能在
            事务中恢复。*/

                -- 删除表中名称为’alex’的记录。
                delete from employee_new where name='alex';
                -- 删除表中所有记录。
                delete from employee_new;-- 注意auto_increment没有被重置:alter table employee auto_increment=1;
                -- 使用truncate删除表中记录。
                truncate table emp_new;
MySQL 基本操作

表记录 查

MySQL 基本操作
CREATE TABLE ExamResult(

   id INT PRIMARY KEY  auto_increment,
   name VARCHAR (20),
   JS DOUBLE ,
   Django DOUBLE ,
   Database DOUBLE
);


INSERT INTO ExamResult VALUES  (1,"yuan",98,98,98),
                               (2,"xialv",35,98,67),
                               (3,"alex",59,59,62),
                               (4,"wusir",88,89,82),
                               (5,"alvin",88,98,67),
                               (6,"yuan",86,100,55);


-- (1)select [distinct] *|field1,field2,......   from tab_name
            -- 其中from指定从哪张表筛选,*表示查找所有列,也可以指定一个列
            -- 表明确指定要查找的列,distinct用来剔除重复行。

                    -- 查询表中所有学生的信息。
                    select * from ExamResult;
                    -- 查询表中所有学生的姓名和对应的英语成绩。
                    select name,JS from ExamResult;
                    -- 过滤表中重复数据。
                    select distinct JS ,name from ExamResult;



-- (2)select 也可以使用表达式,并且可以使用: 字段 as 别名或者:字段 别名

                -- 在所有学生分数上加10分特长分显示。
                select name,JS+10,Django+10,Database+10 from ExamResult;
                -- 统计每个学生的总分。
                select name,JS+Django+Database from ExamResult;
                -- 使用别名表示学生总分。
                select name as 姓名,JS+Django+Database as 总成绩 from ExamResult;
                select name,JS+Django+Database 总成绩 from ExamResult;
                select name JS from ExamResult; //what will happen?---->记得加逗号

-- (3)使用where子句,进行过滤查询。

            -- 查询姓名为XXX的学生成绩
            select * from ExamResult where name='yuan';
            -- 查询英语成绩大于90分的同学
            select id,name,JS from ExamResult where JS>90;
            -- 查询总分大于200分的所有同学
            select name,JS+Django+Database as 总成绩 from
                        ExamResult where JS+Django+Database>200 ;
            -- where字句中可以使用:
                     -- 比较运算符:
                        > < >= <= <> !=
                        between 80 and 100 值在10到20之间
                        in(80,90,100) 值是10或20或30
                        like 'yuan%'
                        /*
                        pattern可以是%或者_,
                        如果是%则表示任意多字符,此例如唐僧,唐国强
                        如果是_则表示一个字符唐_,只有唐僧符合。
                        */

                    -- 逻辑运算符
                        在多个条件直接可以使用逻辑运算符 and or not
            -- 练习
                -- 查询JS分数在 70-100之间的同学。
                select name ,JS from ExamResult where JS between 80 and 100;
                -- 查询Django分数为75,76,77的同学。
                select name ,Django from ExamResult where Django in (75,98,77);
                -- 查询所有姓王的学生成绩。
                select * from ExamResult where name like '王%';
                -- 查询JS分>90,Django分>90的同学。
                select id,name from ExamResult where JS>90 and Django >90;
                -- 查找缺考数学的学生的姓名
                select name from ExamResult where Database is null;


-- (4)Order by 指定排序的列,排序的列即可是表中的列名,也可以是select 语句后指定的别名。

              -- select *|field1,field2... from tab_name order by field [Asc|Desc]

              -- Asc 升序、Desc 降序,其中asc为默认值 ORDER BY 子句应位于SELECT语句的结尾。
              -- 练习:
              -- 对JS成绩排序后输出。
              select * from ExamResult order by JS;
              -- 对总分排序按从高到低的顺序输出
              select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))
                   总成绩 from ExamResult order by 总成绩 desc;
              -- 对姓李的学生成绩排序输出
              select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(Dababase,0))
                   总成绩 from ExamResult where name like 'a%'
                                         order by 总成绩 desc;


-- (5)group by 分组查询:

            -- 注意,按分组条件分组后每一组只会显示第一条记录

            -- group by字句,其后可以接多个列名,也可以跟having子句,对group by 的结果进行筛选。
                      -- 按位置字段筛选
                         select * from ExamResult group by 2;

                      -- 练习:对成绩表按名字分组后,显示每一类名字的JS的分数总和
                          select NAME ,SUM(JS)from ExamResult group by name;
                      -- 练习:对成绩表按名字分组后,显示每一类名字的Django的分数总和>150的
                      --      类名字和django总分
                         --INSERT INTO ExamResult VALUES  (12,"alex",90,90,90);

                          select name,sum(Django) from ExamResult group by name
                                                  having sum(Django)>150;

                   /*
                   having 和 where两者都可以对查询结果进行进一步的过滤,差别有:
                     <1>where语句只能用在分组之前的筛选,having可以用在分组之后的筛选;
                     <2>使用where语句的地方都可以用having进行替换
                     <3>having中可以用聚合函数,where中就不行。
                   */
                    -- 练习:对成绩表按名字分组后,显示除了yuan这一组以外的每一类名字的Django
                    -- 的分数总和>150的类名字和django总分


                        select name,sum(Django) from ExamResult
                                                  WHERE name!="yuan"
                                                  group by name
                                                  having sum(Django)>130;


            -- GROUP_CONCAT() 函数
            SELECT id,GROUP_CONCAT(name),GROUP_CONCAT(JS) from ExamResult GROUP BY id;

-- (6)聚合函数: 先不要管聚合函数要干嘛,先把要求的内容查出来再包上聚合函数即可。
                 --   (一般和分组查询配合使用)

        --<1> 统计表中所有记录

            -- COUNT(列名):统计行的个数
                    -- 统计一个班级共有多少学生?先查出所有的学生,再用count包上
                     select count(*) from ExamResult;
                    -- 统计JS成绩大于70的学生有多少个?
                     select count(JS) from ExamResult where JS>70;
                    -- 统计总分大于280的人数有多少?
                     select count(name) from ExamResult
                           where (ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))>280;
                    -- 注意:count(*)统计所有行;     count(字段)不统计null值.

            -- SUM(列名):统计满足条件的行的内容和
                    -- 统计一个班级JS总成绩?先查出所有的JS成绩,再用sum包上
                        select JS as JS总成绩 from ExamResult;
                        select sum(JS) as JS总成绩 from ExamResult;
                    -- 统计一个班级各科分别的总成绩
                        select sum(JS) as JS总成绩,
                               sum(Django) as Django总成绩,
                               sum(Database) as Database总成绩 from ExamResult;

                    -- 统计一个班级各科的成绩总和
                        select sum(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))
                                                    as 总成绩 from ExamResult;
                    -- 统计一个班级JS成绩平均分
                        select sum(JS)/count(*) from ExamResult ;
                    -- 注意:sum仅对数值起作用,否则会报错。

            -- AVG(列名):
                            -- 求一个班级JS平均分?先查出所有的JS分,然后用avg包上。
                                select avg(ifnull(JS,0)) from ExamResult;
                            -- 求一个班级总分平均分
                                select avg((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
                                                         from ExamResult ;
                -- Max、Min
                            -- 求班级最高分和最低分(数值范围在统计中特别有用)
                            select Max((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
                            最高分 from ExamResult;
                            select Min((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
                            最低分 from ExamResult;

                -- 注意:null 和所有的数计算都是null,所以需要用ifnull将null转换为0!
                --      -----ifnull(JS,0)


                -- with rollup的使用

            --<2> 统计分组后的组记录


-- (7) 重点:Select from where group by having order by
                -- Mysql在执行sql语句时的执行顺序:from  where  select group by  having order by
                -- 分析:
                select JS as JS成绩 from ExamResult where JS成绩 >70; ---- 不成功
                select JS as JS成绩 from ExamResult having JS成绩 >90; --- 成功
                select JS as JS成绩 from ExamResult group by JS成绩 having JS成绩 >80; ----成功
                select JS as JS成绩 from ExamResult order by JS成绩;----成功
                select * from ExamResult as 成绩 where 成绩.JS>85; ---- 成功

--  (8) limit
                SELECT * from ExamResult limit 1;
                SELECT * from ExamResult limit 1,5;
MySQL 基本操作

外键约束

创建外键

 
   ---  每一个班主任会对应多个学生 , 而每个学生只能对应一个班主任
  
   ---  主表
  
   CREATE TABLE ClassCharger(
   
          id TINYINT PRIMARY KEY auto_increment,
          name VARCHAR (20),
          age INT ,
          is_marriged boolean  -- show create table ClassCharger: tinyint(1)
   
   );
   
   INSERT INTO ClassCharger (name,age,is_marriged) VALUES ("冰冰",12,0),
                                                          ("丹丹",14,0),
                                                          ("歪歪",22,0),
                                                          ("姗姗",20,0),
                                                          ("小雨",21,0);
 
 
   --- 子表
 
   CREATE TABLE Student(
  
         id INT PRIMARY KEY auto_increment,
         name VARCHAR (20),
         charger_id TINYINT,     --切记:作为外键一定要和关联主键的数据类型保持一致
         -- [ADD CONSTRAINT charger_fk_stu]FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
 
  ) ENGINE=INNODB;
  
  INSERT INTO Student(name,charger_id) VALUES ("alvin1",2),
                                              ("alvin2",4),
                                              ("alvin3",1),
                                              ("alvin4",3),
                                              ("alvin5",1),
                                              ("alvin6",3),
                                              ("alvin7",2);
 
 
  DELETE FROM ClassCharger WHERE name="冰冰";
  INSERT student (name,charger_id) VALUES ("yuan",1);
  -- 删除居然成功,可是 alvin3显示还是有班主任id=1的冰冰的;
 
  -----------增加外键和删除外键---------
 
  ALTER TABLE student  ADD CONSTRAINT abc
                       FOREIGN KEY(charger_id)
                       REFERENCES  classcharger(id);
  
 
  ALTER TABLE student DROP FOREIGN KEY abc;
 

innodb支持的on语句

 
  --外键约束对子表的含义:   如果在父表中找不到候选键,则不允许在子表上进行insert/update
  
  --外键约束对父表的含义:    在父表上进行update/delete以更新或删除在子表中有一条或多条对
                      -- 应匹配行的候选键时,父表的行为取决于:在定义子表的外键时指定的
                      -- on update/on delete子句
  
  
  -----------------innodb支持的四种方式---------------------------------------
  
  -----cascade方式 在父表上update/delete记录时,同步update/delete掉子表的匹配记录
  -----外键的级联删除:如果父表中的记录被删除,则子表中对应的记录自动被删除--------
 
       FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
                                ON DELETE CASCADE
 
 
  ------set null方式 在父表上update/delete记录时,将子表上匹配记录的列设为null
     -- 要注意子表的外键列不能为not null
 
       FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
                                ON DELETE SET NULL
 
 
  ------Restrict方式 :拒绝对父表进行删除更新操作(了解)
 
  ------No action方式 在mysql中同Restrict,如果子表中有匹配的记录,则不允许对父表对应候选键
     -- 进行update/delete操作(了解)
 

多表查询

 
   -- 准备两张表
   -- company.employee
   -- company.department
  
        create table employee(
        emp_id int auto_increment primary key not null,
        emp_name varchar(50),
        age int,
        dept_id int
        );
 
        insert into employee(emp_name,age,dept_id) values
         ('A',19,200),
         ('B',26,201),
         ('C',30,201),
         ('D',24,202),
         ('E',20,200),
         ('F',38,204);
 
 
      create table department(
         dept_id int,
         dept_name varchar(100)
        );
 
      insert into department values
        (200,'人事部'),
        (201,'技术部'),
        (202,'销售部'),
        (203,'财政部');
 
  mysql> select * from employee;
  +--------+----------+------+---------+
  | emp_id | emp_name | age  | dept_id |
  +--------+----------+------+---------+
  |      1 | A        |   19 |     200 |
  |      2 | B        |   26 |     201 |
  |      3 | C        |   30 |     201 |
  |      4 | D        |   24 |     202 |
  |      5 | E        |   20 |     200 |
  |      6 | F        |   38 |     204 |
  +--------+----------+------+---------+
  rows in set (0.00 sec)
 
  mysql> select * from department;
  +---------+-----------+
  | dept_id | dept_name |
  +---------+-----------+
  |     200 | 人事部    |
  |     201 | 技术部    |
  |     202 | 销售部    |
  |     203 | 财政部    |
  +---------+-----------+
  rows in set (0.01 sec)
 

多表查询之连接查询

1.笛卡尔积查询

 
mysql> SELECT * FROM employee,department;

--        select employee.emp_id,employee.emp_name,employee.age,
--        department.dept_name from employee,department;

+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age  | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
|      1 | A        |   19 |     200 |     200 | 人事部    |
|      1 | A        |   19 |     200 |     201 | 技术部    |
|      1 | A        |   19 |     200 |     202 | 销售部    |
|      1 | A        |   19 |     200 |     203 | 财政部    |
|      2 | B        |   26 |     201 |     200 | 人事部    |
|      2 | B        |   26 |     201 |     201 | 技术部    |
|      2 | B        |   26 |     201 |     202 | 销售部    |
|      2 | B        |   26 |     201 |     203 | 财政部    |
|      3 | C        |   30 |     201 |     200 | 人事部    |
|      3 | C        |   30 |     201 |     201 | 技术部    |
|      3 | C        |   30 |     201 |     202 | 销售部    |
|      3 | C        |   30 |     201 |     203 | 财政部    |
|      4 | D        |   24 |     202 |     200 | 人事部    |
|      4 | D        |   24 |     202 |     201 | 技术部    |
|      4 | D        |   24 |     202 |     202 | 销售部    |
|      4 | D        |   24 |     202 |     203 | 财政部    |
|      5 | E        |   20 |     200 |     200 | 人事部    |
|      5 | E        |   20 |     200 |     201 | 技术部    |
|      5 | E        |   20 |     200 |     202 | 销售部    |
|      5 | E        |   20 |     200 |     203 | 财政部    |
|      6 | F        |   38 |     204 |     200 | 人事部    |
|      6 | F        |   38 |     204 |     201 | 技术部    |
|      6 | F        |   38 |     204 |     202 | 销售部    |
|      6 | F        |   38 |     204 |     203 | 财政部    |
+--------+----------+------+---------+---------+-----------+
 

2.内连接

 
  -- 查询两张表中都有的关联数据,相当于利用条件从笛卡尔积结果中筛选出了正确的结果。
  
    select * from employee,department where employee.dept_id = department.dept_id;
  --select * from employee inner join department on employee.dept_id = department.dept_id;
  
        +--------+----------+------+---------+---------+-----------+
        | emp_id | emp_name | age  | dept_id | dept_id | dept_name |
        +--------+----------+------+---------+---------+-----------+
        |      1 | A        |   19 |     200 |     200 | 人事部    |
        |      2 | B        |   26 |     201 |     201 | 技术部    |
        |      3 | C        |   30 |     201 |     201 | 技术部    |
        |      4 | D        |   24 |     202 |     202 | 销售部    |
        |      5 | E        |   20 |     200 |     200 | 人事部    |
        +--------+----------+------+---------+---------+-----------+
 

3.外链接

 
  --(1)左外连接:在内连接的基础上增加左边有右边没有的结果
  
   select * from employee left join department on employee.dept_id = department.dept_id;
  
       +--------+----------+------+---------+---------+-----------+
       | emp_id | emp_name | age  | dept_id | dept_id | dept_name |
       +--------+----------+------+---------+---------+-----------+
       |      1 | A        |   19 |     200 |     200 | 人事部    |
       |      5 | E        |   20 |     200 |     200 | 人事部    |
       |      2 | B        |   26 |     201 |     201 | 技术部    |
       |      3 | C        |   30 |     201 |     201 | 技术部    |
       |      4 | D        |   24 |     202 |     202 | 销售部    |
       |      6 | F        |   38 |     204 |    NULL | NULL      |
       +--------+----------+------+---------+---------+-----------+
 
   --(2)右外连接:在内连接的基础上增加右边有左边没有的结果
 
   select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id;
 
         +--------+----------+------+---------+---------+-----------+
         | emp_id | emp_name | age  | dept_id | dept_id | dept_name |
         +--------+----------+------+---------+---------+-----------+
         |      1 | A        |   19 |     200 |     200 | 人事部    |
         |      2 | B        |   26 |     201 |     201 | 技术部    |
         |      3 | C        |   30 |     201 |     201 | 技术部    |
         |      4 | D        |   24 |     202 |     202 | 销售部    |
         |      5 | E        |   20 |     200 |     200 | 人事部    |
         |   NULL | NULL     | NULL |    NULL |     203 | 财政部    |
         +--------+----------+------+---------+---------+-----------+
 
  --(3)全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
 
     -- mysql不支持全外连接 full JOIN
     -- mysql可以使用此种方式间接实现全外连接
     
    select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id
    UNION
    select * from employee LEFT JOIN department on employee.dept_id = department.dept_id;
 
         
 
         +--------+----------+------+---------+---------+-----------+
         | emp_id | emp_name | age  | dept_id | dept_id | dept_name |
         +--------+----------+------+---------+---------+-----------+
         |      1 | A        |   19 |     200 |     200 | 人事部    |
         |      2 | B        |   26 |     201 |     201 | 技术部    |
         |      3 | C        |   30 |     201 |     201 | 技术部    |
         |      4 | D        |   24 |     202 |     202 | 销售部    |
         |      5 | E        |   20 |     200 |     200 | 人事部    |
         |   NULL | NULL     | NULL |    NULL |     203 | 财政部    |
         |      6 | F        |   38 |     204 |    NULL | NULL      |
         +--------+----------+------+---------+---------+-----------+
 
      -- 注意 union与union all的区别:union会去掉相同的纪录
 

多表查询之复合条件链接查询

 
  -- 查询员工年龄大于等于25岁的部门
  
      SELECT DISTINCT department.dept_name
      FROM employee,department
      WHERE employee.dept_id = department.dept_id
      AND age>25;
  
  
  --以内连接的方式查询employee和department表,并且以age字段的升序方式显示
 
      select employee.emp_id,employee.emp_name,employee.age,department.dept_name
      from employee,department
      where employee.dept_id = department.dept_id
      order by age asc;
 

多表查询之子查询

 
 -- 子查询是将一个查询语句嵌套在另一个查询语句中。
 -- 内层查询语句的查询结果,可以为外层查询语句提供查询条件。
 -- 子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
 -- 还可以包含比较运算符:= 、 !=、> 、<等
 
 
 -- 1. 带IN关键字的子查询
 
    ---查询employee表,但dept_id必须在department表中出现过
 
    select * from employee
             where dept_id IN
             (select dept_id from department);
 
 
 +--------+----------+------+---------+
 | emp_id | emp_name | age  | dept_id |
 +--------+----------+------+---------+
 |      1 | A        |   19 |     200 |
 |      2 | B        |   26 |     201 |
 |      3 | C        |   30 |     201 |
 |      4 | D        |   24 |     202 |
 |      5 | E        |   20 |     200 |
 +--------+----------+------+---------+
 rows in set (0.01 sec)
 
 
 
 -- 2. 带比较运算符的子查询
       --      =、!=、>、>=、<、<=、<>
 
      -- 查询员工年龄大于等于25岁的部门
      select dept_id,dept_name from department
            where dept_id IN
           (select DISTINCT dept_id from employee where age>=25);
 
 -- 3. 带EXISTS关键字的子查询
 
 -- EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。
 -- 而是返回一个真假值。Ture或False
 -- 当返回Ture时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询
 
      select * from employee
               WHERE EXISTS
               (SELECT dept_name from department where dept_id=203);
 
       --department表中存在dept_id=203,Ture
 
 
      select * from employee
WHERE EXISTS (SELECT dept_name from department where dept_id=205); -- Empty set (0.00 sec) ps: create table t1(select * from t2);