MySQL基础教学02

  • Post author:
  • Post category:mysql




1.DQL:查询语句



1.1 排序查询


  • 语法

    SELECT 字段名 FROM 表名 [WHERE条件] ORDER BY 字段名 [ASC|DESC];
    
    • ASC: 升序,默认值
    • DESC: 降序

  • 注意

    • 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。

  • 例子

    • 查询所有数据,使用年龄降序排序

      select * from student order by age desc;
      
    • 查询所有数据,在年龄降序排序的基础上,如果年龄相同再以数学成绩升序排序

      select * from student order by age desc, math asc;
      

  • 补充案例

    • 计算math 和 english总成绩 并按照总成绩降序排序

      SELECT NAME , math + IFNULL(english,0)  score FROM stu ORDER BY score DESC; 
      

  • order by 总结


    • order by 子句后可以支持那些内容?

      表中的字段  函数  
      

    • order by 执行顺序?

      最后再执行  除了limit语句
      



1.2 聚合函数


  • 什么是sql函数

    当我们学习编程语言的时候,经常会遇到函数。函数的好处是,它可以把我们经常使用的代码封装起来,需要的时候直接调用即可。这样既提高了编写代码的效率,又提高了可维护性。在sql中函数主要要对数据进行处理!


  • 常用的sql函数

    • 算术函数
    • 字符串函数
    • 日期函数
    • 转换函数
    • 聚合函数/聚集函数

  • 语法

    SELECT 聚合函数(列名) FROM 表名;
    

  • 五个聚合函数

    聚合函数 说明
    count(*) | count(主键) 计算表中的总记录数
    max 计算最大值
    min 计算最小值
    sum 计算和
    avg 计算平均值

  • 注意

    :聚合函数的计算,排除null值。


  • 解决方案

    1. 选择不包含非空的列进行计算
    2. IFNULL函数

  • 其他函数

    函数名 说明 作用
    length(str) 字符函数 获取字符的字节个数
    upper(str) 字符函数 将字符转换为大写字符
    lower(str) 字符函数 将字符转换为小写字符
    substring(str,pos) 字符函数 截取从指定索引处后面所有的字符
    substring(str,pos,len) 字符函数 截取从pos索引开始截取len个字符
    replace(str,from_str,to_str) 字符函数 将str中的字符 from_str字符替换成to_str字符
    round(x) 数学函数 四舍五入
    round(x,d) 数学函数 四舍五入 d:代表的是保留小数点后几位
    cell(x) 数学函数 向上取整
    floor(x) 数学函数 向下取整
    mod(n,m) 数学函数 取余数 mod(10,3) 相当于: select 10 % 3
    str_to_date(str,format) 日期函数 将日期字符转换成指定格式的日期 str_to_date(‘1990-11-11’,’%Y-%m-%d’);
    date_format(date,format) 日期函数 将日期转换成字符 date_format(now(),’%Y/%m/%d’);

  • 例子

    :

    • 查询 id 字段,如果为 null,则使用 0 代替

      select ifnull(id,0) from student;
      
    • 查询总记录数-利用 IFNULL()函数,如果记录为 NULL,给个默认值,这样统计的数据就不会遗漏

      select count(ifnull(id,0)) from student;
      
    • 查询年龄大于 20 的总数

      select count(*) from student where age>20;
      
    • 查询数学成绩总分

      select sum(math) 总分 from student;
      
    • 查询数学成绩平均分

      select avg(math) 平均分 from student;
      
    • 查询数学成绩最高分

      select max(math) 最高分 from student;
      
    • 查询数学成绩最低分

      select min(math) 最低分 from student;
      



1.3 分组查询


  • 语法

    SELECT 字段 1,字段 2... FROM 表名 [where条件] GROUP BY 分组字段 [HAVING 条件] [order by];
    

  • 注意

    • 分组之后查询的字段:分组字段、聚合函数
    • where 和 having 的区别?

      • where 在分组之前进行限定,如果不满足条件,则不参与分组。having在分组之后进行限定,如果不满足结果,则不会被查询出来 where 对基本的条件筛选
      • where 后不可以跟聚合函数,having可以进行聚合函数的判断。

    ​ where 操作的数据源: 原始表

    ​ having 操作的数据源: 结果集


  • 例子

    • 按照性别分组。分别查询男、女同学的平均分

      SELECT sex , AVG(math) FROM student GROUP BY sex;
      
    • 按照性别分组。分别查询男、女同学的平均分,人数

      SELECT sex , AVG(math),COUNT(id) FROM student GROUP BY sex;
      
    • 按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组

      SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex;
      
    • 按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组,分组之后。人数要大于2个人

      SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id) > 2;
      
      -- 最终写法
      SELECT sex , AVG(math),COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2;
      

  • 案例

    按照address进行分组,并且math>60分的人员 , 分组完成之后,我只要人数>=2,并按照人数降序排序
    
    SELECT 
    	address,
    	COUNT(id) AS c
    FROM 
    	student
    WHERE
    	math > 60
    GROUP BY 
    	address
    HAVING 
    	c>=2
    ORDER BY
    	c DESC;
    	
    #######################
    SELECT address,COUNT(id) AS c
    FROM student
    WHERE math > 60
    GROUP BY address
    HAVING c>=1
    ORDER BY c DESC	;
    



1.4 分页查询


  • 语法

    SELECT *|字段列表 [as 别名] FROM 表名 [WHERE 子句] [GROUP BY 子句][HAVING 子句][ORDER BY 子句][LIMIT 子句];
    

  • LIMIT语法格式


    • 格式

      LIMIT offset,length;
      
      • offset:起始行数,从 0 开始计数,如果省略,默认就是 0
      • length: 返回的行数

  • 计算公式

    开始的索引 = (当前的页码 - 1* 每页显示的条数
    

  • 例子

    -- 每页查询显示3条数据
    SELECT * FROM student LIMIT 0,3; -- 第1页
    SELECT * FROM student LIMIT 3,3; -- 第2页
    SELECT * FROM student LIMIT 6,3; -- 第3页
    



2. 约束



2.1 约束简介



2.1.1 什么是约束


  • 概念

    对表中的数据进行限定,保证数据的正确性、有效性和完整性。	
    



2.2.2 约束的分类

约束 说明
primary key 主键约束:非空且唯一
not null 非空约束 : 某一列的值不能为空
unique 唯一约束 : 某一列的值不能重复
foreign key 外键约束



2.2 约束详解



2.2.1 非空约束

create table 表名(

​ 列名1 数据类型 约束,

);


  • 创建表时添加约束

    CREATE TABLE stu(
    	id INT,
    	NAME VARCHAR(20) NOT NULL -- name为非空
    );
    

  • 创建表完后,添加非空约束

    ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
    

  • 删除name的非空约束

     ALTER TABLE stu MODIFY NAME VARCHAR(20);
    



2.2.2 唯一约束


  • 创建表时,添加唯一约束

    CREATE TABLE stu(
     	id INT,
     	phone_number VARCHAR(20) UNIQUE -- 手机号
    );
    

    • 注意

      • 唯一约束可以有NULL值,也可以有多个null值

  • 表创建完后,添加唯一约束

    ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
    

  • 删除唯一约束

    ALTER TABLE stu DROP INDEX phone_number;
    



2.2.3 主键约束


  • 在创建表时,添加主键约束:primary key

    create table stu(
    	id int primary key ,-- 给id添加主键约束
    	name varchar(20)
    );
    

  • 注意

    • 含义:非空且唯一
    • 一张表只能有一个字段为主键
    • 主键就是表中记录的唯一标识

  • 创建完表后,添加主键

    ALTER TABLE stu MODIFY id INT PRIMARY KEY;
    

  • 创建完表后,删除主键

    -- 错误 alter table stu modify id int ;
    ALTER TABLE stu DROP PRIMARY KEY;
    



2.2.4 自动增长


  • 概念

    如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长
    

  • 在创建表时,添加主键约束,并且完成主键自增长

    create table stu(
        id int primary key auto_increment,-- 给id添加主键约束
        name varchar(20)
    );
    

  • 添加自动增长

    ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
    

  • 删除自动增长

    ALTER TABLE stu MODIFY id INT;
    

  • 综合案例

    /*
      创建一个person表
    	pid 主键 自动增长
    	pname 不为空
    	phone_number 不为空,且唯一
    	address 不为空 
    	id_card 不为空,且唯一
    */
    
    -- 创建Person表
    CREATE TABLE person(
    	pid INT PRIMARY KEY AUTO_INCREMENT,
    	pname VARCHAR(30) NOT NULL,
    	phone_number VARCHAR(11) UNIQUE,
    	address VARCHAR(50) NOT NULL ,
    	id_card VARCHAR(20) NOT NULL UNIQUE
    );
    
    -- 添加一条数据
    INSERT INTO person(`name`,`phone_number`,`card_number`) VALUES 
    ('张三','13814381438','411411198311114123');
    
    



2.2.4 外键约束


  • 概念

    foreign key,让表与表产生关系,从而保证数据的正确性。
    

  • 数据准备

    -- 创建部门表(id,dep_name,dep_location)
    -- 一方,主表
    CREATE TABLE department(
    	id INT PRIMARY KEY AUTO_INCREMENT,
    	dep_name VARCHAR(20),
    	dep_location VARCHAR(20)
    );
    
    
    -- 创建员工表(id,name,age,dep_id)
    -- 多方,从表
    CREATE TABLE employee(
    	id INT PRIMARY KEY AUTO_INCREMENT,
    	NAME VARCHAR(20),
    	age INT,
    	dep_id INT, -- 外键对应主表的主键
    	-- CONSTRAINT dept_emp_fk_id  可以省略不写
    	CONSTRAINT dept_emp_fk_id FOREIGN  KEY (dep_id) REFERENCES department (id)
    	 
    );
    
    
    -- 添加 2 个部门
    INSERT INTO department VALUES(NULL, '研发部','广州'),(NULL, '销售部', '深圳');
    SELECT * FROM department;
    -- 添加员工,dep_id 表示员工所在的部门
    INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);
    INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);
    INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);
    INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2);
    INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2);
    INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2);
    SELECT * FROM employee;
    

  • 在创建表时,添加外键

    -- 语法
    create table 表名(
        ....
        外键列
        constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
    );
    

  • 创建表之后,添加外键

    ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
    

  • 删除外键

    ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
    

  • 级联操作

    CREATE TABLE pp(
    	pid INT PRIMARY KEY AUTO_INCREMENT,
    	pname VARCHAR(30) NOT NULL,
    	phone VARCHAR(11) NOT NULL UNIQUE,
    	p_fk_id INT
    	-- 创建表的时候,添加外键和级联操作,两个级联操作可以同时加上,也可以单独加
    	CONSTRAINT pp_p_fk FOREIGN KEY (p_fk_id) REFERENCES p1(id) ON UPDATE CASCADE  ON DELETE CASCADE
    );
    

  • 分类

    • 级联更新:ON UPDATE CASCADE
    • 级联删除:ON DELETE CASCADE

  • 添加级联

    ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE  
    
  • 总结:

    • 添加约束的时候,建议创建表的时候添加约束 , 不建议大家删除约束
    • 级联尽量避免设置级联 效率低
    • 设置外键 一般不设置外键(建立逻辑外键,不建立实际外键)



3.数据库的设计



3.1 多表之间的关系(了解)



3.1.1 分类


  • 一对一(了解)

    * 如:人和身份证
    * 分析:一个人只有一个身份证,一个身份证只能对应一个人
    

  • 一对多(多对一)

    * 如:部门和员工
    * 分析:一个部门有多个员工,一个员工只能对应一个部门
    

  • 多对多

    * 如:学生和课程
    * 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择
    



3.1.2 实现关系


  • 一对多(多对一)

    * 如:部门和员工
    * 实现方式:在多的一方建立外键,指向一的一方的主键。
    

  • 多对多

    * 如:学生和课程
    * 实现方式:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
    

  • 一对一(了解)

    * 如:人和身份证
    * 实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键。
    



3.1.3 案例


  • 创建旅游线路分类表 tab_category

    -- 创建旅游线路分类表 tab_category
    -- cid 旅游线路分类主键,自动增长
    -- cname 旅游线路分类名称非空,唯一,字符串 100
    CREATE TABLE tab_category (
        cid INT PRIMARY KEY AUTO_INCREMENT,
        cname VARCHAR(100) NOT NULL UNIQUE
    );
    		
    

  • 创建旅游线路表 tab_route

    -- rid 旅游线路主键,自动增长
    -- rname 旅游线路名称非空,唯一,字符串 100
    -- price 价格
    -- rdate 上架时间,日期类型
    -- cid 外键,所属分类
    CREATE TABLE tab_route(
        rid INT PRIMARY KEY AUTO_INCREMENT,
        rname VARCHAR(100) NOT NULL UNIQUE,
        price DOUBLE,
        rdate DATE,
        cid INT,
        FOREIGN KEY (cid) REFERENCES tab_category(cid)
    );  
    

  • 创建用户表 tab_user

	-- uid 用户主键,自增长
	-- username 用户名长度 100,唯一,非空
	-- password 密码长度 30,非空
	-- name 真实姓名长度 100
	-- birthday 生日
	-- sex 性别,定长字符串 1
	-- telephone 手机号,字符串 11
	-- email 邮箱,字符串长度 100
	
    CREATE TABLE tab_user (
        uid INT PRIMARY KEY AUTO_INCREMENT,
        username VARCHAR(100) UNIQUE NOT NULL,
        PASSWORD VARCHAR(30) NOT NULL,
        NAME VARCHAR(100),
        birthday DATE,
        sex CHAR(1) DEFAULT '男',
        telephone VARCHAR(11),
        email VARCHAR(100)
    );

  • 收藏表 tab_favorite

    -- rid 旅游线路 id,外键
    -- date 收藏时间
    -- uid 用户 id,外键
    -- rid 和 uid 不能重复,设置复合主键,同一个用户不能收藏同一个线路两次
    
    CREATE TABLE tab_favorite (
        rid INT, -- 线路id
        DATE DATETIME,
        uid INT, -- 用户id
        -- 创建复合主键
        PRIMARY KEY(rid,uid), -- 联合主键
        FOREIGN KEY (rid) REFERENCES tab_route(rid),
        FOREIGN KEY(uid) REFERENCES tab_user(uid)
    );		
    
  • 总结:

    • 一个用户可以收藏多条线路 , 线路也可以被多个用户所收藏 用户与收藏线路表: 多对多的关系,必须建立中间表
    • 线路分类中可以有多条线路 线路分类表 和 收藏表 一对多的关系



3.2 数据库设计的范式


  • 概念

设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。

目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)


- **分类**

- **第一范式(1NF)**:每一列都是不可分割的原子数据项

- **第二范式(2NF)**:在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)

  - **概念**

    - **函数依赖**:A-->B, 如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A
      **例如**:学号-->姓名。  (学号,课程名称) --> 分数

    - **完全函数依赖**:A-->B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。

      **例如**:(学号,课程名称) --> 分数

    - **部分函数依赖**:A-->B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。
      **例如**:(学号,课程名称) -- > 姓名

    - **传递函数依赖**:A-->B, B -- >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A

    ​        **例如**:学号-->系名,系名-->系主任

    - **码**:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码

      **例如**:该表中码为:(学号,课程名称)
       **主属性**:码属性组中的所有属性
       **非主属性**:除过码属性组的属性

- **第三范式(3NF)**:在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)




版权声明:本文为weixin_43842051原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。