0
点赞
收藏
分享

微信扫一扫

数据库增删改查的进阶

书呆鱼 2022-01-05 阅读 213

目录

一.数据库中创建表时的约束 

1.约束类型

2.约束类型的详细说明和例子

(1)为创建的每个数据设置约束类型

 (2)插入时注意自己设置的类型

二.表的结构

1.一对一

2.一对多

3.多对多

 三.查询进阶

1.聚合查询常用函数

 2.GROUP BY(分组查询)语句的使用

(1)说明

(2)语法

(3)例子

 3.HAVING的使用

(1)使用说明

(2)语法

(3)例子

四.联合查询

1.内连接

(1)语法

(2)例子

2.外连接

(1)引入

(2)语法

(3)例子

3.自连接

(1)说明

(2)语法

(3)例子

4.子查询

(1)说明

(2)语法

(3)例子

5.合并查询

(1)概念

(2)语法

(3)例子


一.数据库中创建表时的约束 

1.约束类型

类型含义
NOT NULL指示某列不能存储 NULL 值
 
UNIQUE保证某列的每行必须有唯一的值
 
DEFAULT规定没有给列赋值时的默认值
 
PRIMARY KEY主键约束,NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录
 
FOREIGEN KEY外键约束,保证一个表中的数据匹配另一个表中的值的参照完整性

2.约束类型的详细说明和例子

前提:需要在自己指定的库里面创建表(如果不太懂,可以看前面的博客)

例子:在创建学生对象的时候使用约束类型

(1)为创建的每个数据设置约束类型

drop table if exists classes;

create table classes(
    id int primary key auto_increment,
    class int
);

drop table if exists student;

create table student(
    id int primary key auto_increment,
    -- 主键约束(整型长搭配自增,每次插入省略给id,因为自动就会给值)
    stu_name  varchar(20)  default 'unknown',
    -- 默认值约束(这里默认约束为unknown) 
    qq_mail varchar(20) unique,
    -- 唯一约束,不重复
    class_id int not null,
    -- 非空约束
    foreign key (class_id) references classes(id)
);

 创建成功显示:

 (2)插入时注意自己设置的类型

因为在插入数据的时候就会用到这些类型约束。

正确插入代码:

insert into
    classes (class)
values
(1),
(2),
(3);

insert into
    student (stu_name, qq_mail, class_id)
values
    ('张三', '157@qq.com', 1),
    ('李四', '163@qq.com', 2),
    ('王五', '186@qq.com', 3);

成功演示:

 对于超过约束条件的就会插入失败,如下所示:

 代码:

-- 插入成功,名字默认unknow
insert into
    student (qq_mail, class_id)
values
('123@qq.com', 1);

-- 外键约束,插入失败
insert into
    student (qq_mail, class_id)
values
('123@qq.com', 4);

-- 查询插入后的表,这里的id是自增且唯一
select
    *
from
    student;

二.表的结构

通过外键来对表进行连接

1.一对一

2.一对多

3.多对多

 三.查询进阶

1.聚合查询常用函数

函数说明(不是数字没有意义)
COUNT([DISTINCT] expr)返回查询到的数据的 数量
SUM([DISTINCT] expr)返回查询到的数据的 总和
AVG([DISTINCT] expr)返回查询到的数据的 平均值
MAX([DISTINCT] expr)返回查询到的数据的 最大值
MIN([DISTINCT] expr)返回查询到的数据的 最小值
-- 聚合查询的练习
-- 查询学生总数
select
    COUNT(0) stu_count
from
    student;

-- 查询id的总和
select
    SUM(id) id_sum
from
    student;

-- 查询id中的最大值
select
    MAX(id) id_max
from
    student;

-- 查询id中的最小值
select
    MIN(id) id_min
from
    student;

-- 查询id的平均值
select
    AVG(id) id_avg
from
    student;

查询结果: 

 

 2.GROUP BY(分组查询)语句的使用

(1)说明

SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中。

(2)语法

select  列名或聚合函数,... from 表名 group by 依据的列名或聚合函数;

(3)例子

1.创建表

create table emp(
    id int primary key auto_increment,
    name varchar(20) not null,
    role varchar(20) not null,
    salary numeric(11, 2)
);

insert into
    emp(name, role, salary)
values
    ('张三', '服务员', 1000.27),
    ('李四', '游戏陪玩', 2000.98),
    ('王五', '游戏角色', 999.18),
    ('赵六', '游戏角色', 333.5),
    ('田七', '游戏角色', 700.45),
    ('刘备', '董事长', 12000.34);

2.查询要求

查询每个角色的最高工资和最低工资 

SELECT
    role,
    MIN(salary) min_salary,
    MAX(salary) max_salary
FROM
    emp
GROUP BY
    role;

 注意:因为select后是显示的结果集,如果上面还需要显示名字,不会报错,但是会出现与所要结果有很大的差异。

 3.HAVING的使用

(1)使用说明

如果分组以后还需要对结果进行过滤,不能使用where,只能使用having来进行过滤。

(2)语法

group by 分组后跟having。

(3)例子

显示平均工资低于1500的角色和他的平均工资

select
    role,
    avg(salary)
from
    emp
group by
    role
having
    avg(salary) < 1500;

 注意:having中的内容必须在select查询的结果集中,否则会出现错误。

四.联合查询

联合查询是根据多表进行查询,而多表查询是对数据取笛卡尔积。

笛卡尔积:如果有两个表,第一个表(M)的每一行与另一张表(N)的每一行都进行匹配,最终的结果集中有M*N行。但是有些数据是无效的,所以需要一些条件来过滤这些无效信息。

1.内连接

(1)语法

1.select  字段 from 表1 别名 ,[inner] join 表2 别名 on连接条件 and 其他 条件;

2.select 字段 from 表1 别名,表2 别名 where 连接条件 and 其他条件;

(2)例子

准备查询的数据

DROP TABLE IF EXISTS classes;
-- 创建班级表
CREATE TABLE classes (
    id INT PRIMARY KEY auto_increment,
    name VARCHAR(20),
    `desc` VARCHAR(100)
);

DROP TABLE IF EXISTS student;
-- 创建学生表
CREATE TABLE student (
    id INT PRIMARY KEY auto_increment,
    sn INT UNIQUE,
    name VARCHAR(20) DEFAULT 'unkown',
    qq_mail VARCHAR(20),
    classes_id int,
    FOREIGN KEY (classes_id) REFERENCES classes(id)
);

DROP TABLE IF EXISTS course;
-- 创建课程表
CREATE TABLE course (
    id INT PRIMARY KEY auto_increment,
    name VARCHAR(20)
);


DROP TABLE IF EXISTS score;
-- 创建课程学生中间表:考试成绩表
CREATE TABLE score (
    id INT PRIMARY KEY auto_increment,
    score DECIMAL(3, 1),
    student_id int,
    course_id int,
    FOREIGN KEY (student_id) REFERENCES student(id),
    FOREIGN KEY (course_id) REFERENCES course(id)
);

insert into
    classes(name, `desc`)
values
    ('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
    ('中文系2019级3班', '学习了中国传统文学'),
    ('自动化2019级5班', '学习了机械自动化');

insert into
    student(sn, name, qq_mail, classes_id)
values
    ('09982', '张三', 'zhangsan@qq.com', 1),
    ('00835', '李四', null, 1),
    ('00391', '王五', null, 1),
    ('00031', '赵六', 'xuxian@qq.com', 1),
    ('00054', '田七', null, 1),
    ('51234', '小明', 'say@qq.com', 2),
    ('83223', '小李', null, 2),
    ('09527', '老外', 'foreigner@qq.com', 2);

insert into
    course(name)
values
    ('Java'),
('中国传统文化'),
('计算机原理'),
('语文'),
('高阶数学'),
('英文');

insert into
    score(score, student_id, course_id)
values
    -- 张三
    (70.5, 1, 1),
(98.5, 1, 3),
(33, 1, 5),
(98, 1, 6),
    -- 李四
    (60, 2, 1),
(59.5, 2, 5),
    -- 王五
    (33, 3, 1),
(68, 3, 3),
(99, 3, 5),
    -- 赵六
    (67, 4, 1),
(23, 4, 3),
(56, 4, 5),
(72, 4, 6),
    -- 田七
    (81, 5, 1),
(37, 5, 5),
    -- 小明
    (56, 6, 2),
(43, 6, 4),
(79, 6, 6),
    -- 小李
    (80, 7, 2),
(92, 7, 6);

要求:查询赵六同学的成绩

这里通过内连接将表关联后再通过id进行过滤

-- 查询赵六的所有成绩,结果集中显示每个课程名和对应的成绩
select
    cou.name,
    sco.score
from
    student stu
    join score sco on stu.id = sco.student_id
    join course cou on cou.id = sco.course_id
where
    stu.name = '赵六';

结果显示:

2.外连接

外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示我们就说是右外连接。

(1)引入

查询要求:查询所有同学的成绩及个人信息

-- 查询所有同学的成绩及个人信息
select
    stu.id,
    stu.sn,
    stu.name,
    stu.qq_mail,
    sco.score,
    cou.id,
    cou.name
from
    student stu
    join score sco on stu.id = sco.student_id
    join course cou on cou.id = sco.course_id
order by
    stu.id;

 

如果内连接中某个表中的数据中存在null则在最终查询后则不会显示,如上面查询所有同学成绩和个人信息,因为老外没有成绩,所以最后查询的结果,没有显示老外,如果我们还要该同学,那么就需要外连接来进行实现。

(2)语法

1.左外连接

select  字段名 from  表名 left join 表名 on 连接条件;

2.右外连接

select 字段名 from 表名 right join 表名 on 连接条件;

(3)例子

实现所有学生成绩及个人信息查询

-- 查询所有同学的成绩及个人信息
select
    stu.id,
    stu.sn,
    stu.name,
    stu.qq_mail,
    sco.score,
    cou.id,
    cou.name
from
    student stu
    left join score sco on stu.id = sco.student_id
    left join course cou on cou.id = sco.course_id
order by
    stu.id;

注意:这里的两张表都需要左外连接,否则还是不会显示老外同学的成绩。 

3.自连接

(1)说明

在同一张表连接自身进行查询,这里是对于同一张表的不同行进行比较,通过与自身连接从而简单了查询过程。

(2)语法

select 字段 from 表名1 别名1 join on 表名1 别名2 on 连接条件 and其他条件;

(3)例子

查询java成绩比计算机原理成绩高的学生

-- 查询java成绩比计算机原理成绩高的成绩信息(查询的前提是已知java和计算机原理的课id)
select
    stu.name,
    sc1.student_id,
    sc1.score 'java成绩',
    sc2.score '计算机原理成绩'
from
score sc1
    join score sc2 on sc1.student_id = sc2.student_id
    join student stu on sc1.student_id = stu.id
    and sc1.course_id = 1
    and sc2.course_id = 3
    and sc1.score > sc2.score;

 

4.子查询

(1)说明

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。相当于select中嵌套了select。

(2)语法

select 字段名 from 表1  where  条件=(select 字段名 from 表2);

注意:里面的select 查询相当于一个临时表,如果需要表1的字段需要与临时表返回的结果集进行比较,则临时表需要有别名。下面通过例子来进行理解子查询。

(3)例子

1.查询class_id为1的所有学生的信息

-- 查询和张三同学是同班同学的所有信息
select
    stu.*
from
    student stu
where
    stu.classes_id = (
        select
            classes_id
        from
            student
        where
            name = '张三'
    );

 2.查询所有比中文系2019级3班平均分高的所有班级

-- 查询所有比中文系2019级3班平均分高的所有班级
select
    score.*
from
    score,
    (
        select
            avg(sco.score) avg_score
        from
            student stu
            join classes cla on stu.classes_id = cla.id
            join score sco on sco.student_id = stu.id
        where
            cla.name = '中文系2019级3班'
    ) tmp
where
    score.score > tmp.avg_score;

 

 注意:子查询中还使用了内连接,因为这里设计到了3张表,其中学生表和另外两张表进行关联。

5.合并查询

(1)概念

通过union 和union all 合并多个select查询结果,条件是前后查询的结果集字段需要一致。

union合并查询会自动去重;union all合并查询并不会去重。

(2)语法

select 字段名 from 表名... and 其他条件 union select 字段名 from 表名... and 其他条件;

select 字段名 from 表名... and 其他条件 union all select 字段名 from 表名... and 其他条件;

(3)例子

使用合并查询课程id<3或者是英文的课程信息

1.union使用

-- 查询课程id小于3或者课程为英文的所有课程
select
    *
from
    course
where
    id < 3
union
select
    *
from
    course
where
    name = '英文';

 

注意:这里也可以or也可以进行实现,在实际中使用哪种方法来进行查询,只要能将指定结果集查询出来都可以。 

 2.union all 使用

查询课程id小于3或者课程为java的课程信息

-- 查询课程id<3 或者课程为java的课程信息(结果集不去重,使用union all)
select
    *
from
    course
where
    id < 3
union
all
select
    *
from
    course
where
    name = 'Java';

 

 

举报

相关推荐

0 条评论