mysql进阶

1 数据完整性

1.1 保证实体完整性(如:表中行数据无法区分)
  • 1.主键约束
  • 2.唯一键约束
  • 3.自动增长列
1.2 保证域完整性(如:表中列数据类型错误)
  • 1.数据类型约束
  • 2.非空约束
  • 3.默认值约束
1.3 保证引用完整性
  • 1.外键约束

2 外键

2.1 外键作用
  • 1.主表没有的,从表无法插入
  • 2.从表中有的,主表无法删除
  • 3.先删除从表,再删除主表
2.2 外键的创建
方法1
//主表
create table stu(
  id int primary key,
  name varchar(20) not null,
);

//从表
create table stu_score(
  num int primary key,
  score int unsigned,
  foreign key (num) references stu(id),
);

方法2
alter table stu_score add foreign key(num) references stu(id);

2.3 外键的删除
alter table 从表 drop foreign key 外键名 ;

2.4 外键的操作
1.严格操作(前面讲的都是严格操作)
2.级联(set null):如果主表记录删除或更新,从表置空
3.置空:如果主表记录删除或更新,从表级联

语法:
foreign key (从表字段) references 主表名(字段) [on delete set null] [on update cascade];

3 数据库设计

3.1 实体与实体的关系

1.一对多(表的主键和其他表的非主键建立关系)
2.一对一(表的主键和其他表的主键建立关系)
3.多对多(表的主键和其他表的主键建立关系)

3.2 数据库规范化

1.第一范式:确保每个字段(列)不可再分

id address
1 中国北京
2 美国纽约

应该拆分为

id country city
1 中国 北京
2 美国 纽约

2.第二范式:非键字段必须依赖键字段
或者说,非主键字段都应该和主键有关系,如果没有关系则可以拆分
下面的天气和主键id没关系,应该删除

学生id 姓名 年龄 天气
1 小红 10
2 小军 21

3.第三范式:消除传递依赖
传递依赖只发生在非主键与非主键之间

3.3 查询语句
//语法:
select [选项] 列名 [from 表名] [where 条件] [order by 排序] [group by 分组] [having 条件] [limit 限制]

  1. as 给字段取别名
//as可省略
select  列名 [as] 别名;
  1. dual伪表
    为了保证语句的完整性,添加一个不存在的伪表

  2. where子句
    支持的运算 > , < , >= , <= , != , = , not , and , or

  3. in | not in

select * from stu where address = '上海' or address='北京';
等价于
select * from stu where address in ( '上海','北京');
  1. between...and | not between...and
select * from stu where age >= 18  and age <= 20;
等价于
select * from stu where age between 18 and 20;
  1. is null | is not null
//这里不能用math = null
select * from stu where math is null;
  1. 聚合函数
select sum(math) '数学总分', avg(math) '数学平均分', max(math) '数学最高分',min(math) '数学最低分', count(*) '总人数' from stu;
  1. 模糊查询
通配符
1.`_`(下划线)表示任意一个字符
2.`%`表示任意个字符
//查找姓张的学生
select * from stu where name like '张%';
  1. 排序
1.asc:升序(默认)
2.desc:降序
//单列排序
select * from stu where order by math [asc];
//多列排序(按年龄升序,年龄相同的按总分降序)
select *,(math + ch) as '总分' from stu where order by age asc,(math + ch) desc;
  1. 分组查询
1.如果是分组查询,查询字段必须是分组字段和聚合函数
2.如果查询字段是普通字段,只取第一个值
3.group_concat(name),能连接查询到的分组数据
4.group by后面如果带有多个字段,叫多列分组(会按字段的排列组合分组)

select avg(age) as '年龄' ,address from stu group by address;
|年龄 |address|
| --- | --- |
| 30.0000 |北京|
| 50.0000 |河北|

//查询字段都是普通字段,那么只会查到数据中出现的第一条相关数据
//只查到第一个男生,和第一个女生
select name ,sex from stu group by sex;

select group_concat(name) ,sex from stu group by sex;
| group_concat(name) |sex|
| --- | --- |
|小红,小绿,小紫 |女|
|小黑,小灰,小军 |男|
  1. having条件(对查询结果表再次筛选)
having 和 where区别
where是从数据库中的原始数据进行查找,having是对查询结果集中进行筛选
//此处不能用where,原始数据没有total字段
select sex,count(*) total from stu group by sex having total > 5;
  1. limit条件(有点像截取数据)
起始位置默认从0开始,不是从1开始
select * from stu limit 0,2;

13.选项

1.默认是all
2.distinct 去除重复数据

select distinct address from stu;

14.union

作用:将多个select语句结果集纵向联合起来

语法:
select 语句 union [选项] select 语句  union [选项] select 语句

//只要查询的字段数量一致就行,类型可以不一致
select id , name1 from stu1 union select uid , name2 from stu2;

union中的选项默认是distinct

4 多表联查

分类:

  1. 内连接
  2. 外连接
    • 2.1 左外连接
    • 2.2 右外连接
  3. 交叉连接
  4. 自然连接
4.1 内连接(Inner join)

取各个表中公共字段相等的数据

//语法1
select 列名  from 表1 inner join 表2 on 表1.公共字段 = 表2.公共字段;
//语法2
select 列名  from 表1,表2 where 表1.公共字段 = 表2.公共字段;

//3表联查
select 列名  from 表1 inner join 表2 on 表1.公共字段 = 表2.公共字 inner join 表3 on 表3.公共字段 = 表2.公共字段 ;
4.2 外连接
  1. 左外连接(left join)
    以左边的表为标准,如果右边的表没有对应的记录,用NULL填充
//语法
select 列名 from 表1 left join 表2 on 表1.公共字段 = 表2.公共字段;
  1. 右外连接(right join)
    以右边的表为标准,如果左边的表没有对应的记录,用NULL填充
//语法
select 列名 from 表1 right join 表2 on 表1.公共字段 = 表2.公共字段;
4.3 交叉连接
  1. 如果没有连接表达式,返回的是笛卡尔积
select * from t1 cross join t2;
  1. 如果有连接表达式,返回的是内连接
select * from t1 cross join t2 where t1.id = t2.id;
4.4 自然连接

自动的判断连接条件,它是通过同名字段来简化内连接和外连接
结论:

  1. 表连接通过同名字段来连接的
  2. 如果没有同名字段,返回笛卡尔积
  3. 会对结果进行整理,整理规则如下:
    • 连接字段保留一个
    • 连接字段放在最前面
    • 左外连接,左表在前;右外连接,右表在前

自然连接分为:

  1. 自然内连接 natural join
select * from t1 natural join t2;
  1. 自然左外连接 natural left join
select * from t1 natural left join t2;
  1. 自然右外连接 natural right join
select * from t1 natural right join t2;
4.5 using()
  1. 用来指定连接字段
  2. using()也会对连接字段进行整理,整理方式和自然连接一样
//当有多个同名字段时,不能用自然连接,可通过内连接指定连接字段
select * from t1 inner join t2 using(id);
4.6 子查询

子查询的结果作为父查询的条件
1.外面的查询是父查询,括号中的是子查询
2.子查询为父查询提供查询条件

//语法
select 语句 where 条件 (select ... from 表)

例:

  1. 下面的例题中子查询返回一个结果,可以用=
//找出笔试成绩等于80分的学生
select * from stu_info where id = (select id from stu_score where score = 80);
//查找分数最高的学生
select * from stu_info where id = (select id from stu_score order by score desc limit 1);
select * from stu_info where id = (select * from stu_score where score = (select max(score) from stu_score));
  1. 下面的例题中子查询返回多个结果,需要用in,不能用=
//找出笔试成绩大于等于80分的学生
select * from stu_info where id in (select id from stu_score where score >= 80);
//找出不及格的学生(不包含缺考的)
select * from stu_info where id in (select id from stu_score where score < 60);
//找出没通过的(包含缺考的)
select * from stu_info where id not in (select id from stu_score where score >= 60);
  1. esists 和 not exists
//如果有人超过80分就显示所有学生
select * from stu_info where exists (select * from stu_score where score >= 80);
//如果没有超过80分就显示所有学生
select * from stu_info where not exists (select * from stu_score where score >= 80);
  1. 子查询分类
  • 标量子查询:子查询返回一个结果
  • 列子查询:子查询结果返回一个列表
  • 行子查询:子查询结果返回多行
  • 表子查询:子查询结果当成一个表(必须设置别名)
//子查询返回行
select * from stu where (sex , math) in (select sex,max(math) from stu group by sex);

//子查询返回一个表
select * from (select * from stu order by math desc) as t1 group by sex;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容