小言_互联网的博客

MySQL表的增删改查(进阶篇)

250人阅读  评论(0)

目录

1. 数据库约束

1.1 约束类型

1.2 not null 约束

1.3 unique约束 

1.4 primary key约束

1.5 default 约束

1.6  foreign key约束

 2. 新增

 3. 查询

3.1 聚合查询

         3.1.1 聚合函数

3.1.2 group by 子句

3.1.3 having

3.2 联合查询(多表查询)

         3.2.1 join on

3.3 内连接和外连接

3.4 自连接

3.5 子查询

3.6 合并查询


1. 数据库约束

1.1 约束类型

  • not null 指示某列不能存储 NULL 值。
  • unique - 保证某列的每行必须有唯一的值。
  • default - 规定没有给列赋值时的默认值。
  • primary key - not null  unique 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
  • foreign key - 保证一个表中的数据匹配另一个表中的值的参照完整性。
  • check - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是忽略check子句。

1.2 not null 约束

 简单易懂,在加上 not null限制后,这一列就不允许添加null了。

1.3 unique约束 

 同样很好理解,在加上unique约束后,对应列元素就不可以有重复。

1.4 primary key约束

约束是可以组合在一起使用的:

 这里的PRI也就是主键约束(primary key约束):not null + unique

(primary key和unique这样的列,会自动添加索引,来提高查询的速度。)

1.在实际开发中,大部分的表,一般都会带有一个主键,主键一般就会是一个表示整数的id。

2.在mysql中,一个表里,只能有一个主键!!!

3.我们常用mysql自带的 “自增主键” 作为主键的值。

 有了自增主键,在插入id时,我们既可以手动指定,也可以不手动指定,不手动指定时写为null,则会由mysql自动生成。注意此时的null不是设置为控制,而是由mysql本身来进行使用自增主键。

  由此可见:每一次插入数据的时候,mysql都会自动找到上一条记录的id,在此基础上进行自增,同时不会重复利用中间的空隙,可想而知如果这样的话效率也低。而是会依照之前的最大值,来继续往后自增。

1.5 default 约束

default约束便是设置默认名,简单易懂:

1.6  foreign key约束

foreign key (字段名) references 主表()

创建外键约束的时候,先创建父表,再创建子表。

外键约束,也就是针对两个表之间产生的约束。

例如有两个表,一个是班级表,一个是学生表,我们进行外键约束后,约束出插入学生表里的学生的classid应该在班级表里存在,否则就会插入失败。

 如图中,class表中id只有1,2,所以当在student表中创建以classid为3的学生的时候就会出现报错了。

从这个案例来看,班级表中的数据对学生表产生约束力,而学生表中的数据,则要依赖班级表的数据,此处起到约束作用的班级表,就称为 "父表" ,被约束的表,就称为 "子表" 。

实际上,子表也对父表有着约束作用:

当我们尝试去删除 class中 id 为1 的数据时,会发现删除不了。

 但删除未被引用的,是可以成功删除的。如删除刚创建未被引用的三年级三班:

 而且此时,删除父表也是失败的:

这就充分展示了子表对父表的约束力。 

如果想顺利删除,就应该先删除子表,再删除父表:

这里还有一个重点需要注意:在一开始操作的时候,创建完父表后,子表怎么都创建不了,这是因为想创建外键,就要求父表所对应的列,得有primary key 或者unique 约束。

原因是:每次给子表插入元素的时候,都需要在父表中进行查询,检查这个id是否存在,默认情况下检查是需要遍历表的,但在数据量庞大的情况下,遍历效率就十分低,所以就使用索引。 前面也提到过:primary key和unique这样的列,会自动添加索引,来提高查询的速度。

2. 新增

把查询的结果,插入到另一个表中。

要求 查询结果的临时表 的列数和列的类型,要和待插入表的一致。

由此可以看出,新增整张表,或者新增表中某一行中的一列也是可以的。这些都是可以通过条件判断来调整的。

 3. 查询

3.1 聚合查询

聚合查询本质上是在针对行和行之间进行运算。

而前面讲过的查询带表达式是指 列和列之间进行计算。

3.1.1 聚合函数

常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:
函数 说明
COUNT([DISTINCT] expr)
返回查询到的数据的 数量
SUM([DISTINCT] expr)
返回查询到的数据的 总和,不是数字没有意义
AVG([DISTINCT] expr)
返回查询到的数据的 平均值,不是数字没有意义
MAX([DISTINCT] expr)
返回查询到的数据的 最大值,不是数字没有意义
MIN([DISTINCT] expr)
返回查询到的数据的 最小值,不是数字没有意义

需要注意的是:求和,求平均值,求最大值,求最小值这几个操作都是需要针对数字类型的列进行的。

COUNT([DISTINCT] expr)

 由此可见count()的括号内填*或者是列名都是可以的,不影响查询结果。但有一种特殊情况:

 可以看出当值为null的时候,count(*)会把空值也算进去,而count(列)不会把null算进去。

还有一个易错点:

count和()之间必须紧挨着,不能有空格! 

SUM([DISTINCT] expr)

把该列的所有行进行加和,要求这个列得是数字,不能是字符串或者日期!!!

 由上图可以看出对于原来的规则:null与任何值进行计算都等于null在这里会被避免。

只计算非null值的和。

 除了计算数字类,其他类会得到0,并且会有警告。

AVG([DISTINCT] expr)

 这里除了针对某一列进行计算,也可以针对表达式进行聚合计算。

MAX([DISTINCT] expr)

MIN([DISTINCT] expr)

聚合函数这一块都是一些比较简单的运用~

3.1.2 group by 子句

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

 在很多种情况下,我们都需要进行分组,比如老板的月收入与程序员的月收入,以及老师的月收入是很一定的差别的,我们单单进行平均工资,那与真实值就会有些偏差,所以需要进行分组求平均值才是贴切实际的。

 用group by (身份)来对身份不同进行分类求平均工资。

跟分组查询一样。也是可以用一些限制条件的: 

3.1.3 having

分组查询,也是可以指定条件的。

指定条件有两种情况:

1.分组之前,指定条件:先筛选,再分组-where

2.分组之后,指定条件:先分组,再筛选-having

3.分组之前和分组之后,都指定条件。

1.分组之前,指定条件:先筛选,再分组-where

统计每个身份的平均薪资,抛开阿陈程序员的不谈:

 2.分组之后,指定条件:先分组,再筛选-having

查询每个身份的平均薪资,排除平均薪资50w以上的:

 3.分组之前和分组之后,都指定条件。

3.2 联合查询(多表查询)

多表查询的基本执行过程:笛卡尔积:就是将两个表放到一起去进行计算

 

 可以看出笛卡尔积后得到一个更大的表:列数为两表列数之和,行数为两表行数之积。而实际上里面的数据大多数是无意义的,不相匹配的,所以要进行筛选:

利用  . 成员运算符:

 选择语句也是可以进行修改的:

 样例分析:

先建立如下四个表:

 

  1> 查询许仙同学的成绩

       1.分析问题,要完成上述查询,就应该把学生表和分数表进行联合查询,所以先进行笛卡尔积计算:得到数据160行

       2.通过前面的讲解也可以指定,这160行中有很多是重复冗杂的,所以加条件进行排除。

        3.再根据需求,加入必要的条件即可

         4.再把不关注的列去掉,保留关注列。

  2> 查询所有同学的总成绩,及同学的个人姓名

       1.分析可以知道,要列出每个同学的姓名和总分,也就是用学生表和分数表进行联合查询,先求出笛卡尔积:

       2.加上选择条件

      3.由于要算总分,就需要用到聚合查询,限制要求列。

3>查询所有同学的成绩,及同学的个人信息

      1.分析要查询个人信息,所有同学,成绩,所以需要学生表,分数表,课程表,算出笛卡尔积

      2.加上选择条件

      3.针对要求的列进行精简

 这一块,初学者还是要尽量多练习~~

 3.2.1 join on

联合查询,还有一种写法就是使用join……on 来查询,或者写成inner join……on

 

join……on也可以进行多表查询

正常使用的时候,from 会更方便,但是from多个表只能实现内连接,而join……on可以实现内连接也可以实现外连接。

 3.3 内连接和外连接

内连接和外连接大多数情况下都没有什么区别。

例如:要连接的两个表内,里面的数据都是一一对应的,这个时候没什么区别,如果不是一一对应的,此时内连接和外连接就有区别了。

对于下图的两个表  

 

使用内连接可以得到:

 而查询出的结果,是两个表都具有的数据。

如果使用外连接:

由结果可以说明:左外连接,会把左表的结果尽可能显示出来,没有的话就用NULL表示,右外连接也是一个道理。

3.4 自连接

简而言之,就是自己和自己笛卡尔积。

自连接的效果就是把行转换成列,因为在SQL中无法进行针对行和行之间使用条件比较,所以就可以使用自连接,把行转换成列来比较。 

还是刚刚样例分析的四个表:

要求显示出"计算机原理"成绩比"java"成绩高的成绩信息。 

 

(进行自连接要给两个表起别名)

     1.添加条件筛选

 得到每个同学的各科成绩的组合排列。

    2.根据要求进行加条件,只保留两科成绩的组合

 这样就可以得出结果啦~

3.5 子查询

子查询本质上,就是把多条SQL语句组成一个,子查询一般复杂且不好理解,对于代码的可读性也有打击,所以一般都建议不用。

单行子查询: 返回一行记录的子查询

 还是刚刚的四个表来进行讲述:

  要查询与"不想毕业"同学的同班同学:

正常操作是这样的,而子查询就是把上述两个操作合并:

 注意上述黄框画出的等号必须要后面的子查询只返回一条记录的时候,才可以写 = !!! 

多行子查询:返回多行记录的子查询

还是刚刚的四个表来进行讲述:

  要查询 “语文” 或者 “英语”课程的成绩信息:

正常操作下:

子查询操作:

当返回多条记录的时候就不再用 = 了,而是用 in 。

3.6 合并查询

合并查询是个简单易懂的查询,本质上就是把两个查询的结果表,合并起来。

用union关键字或者union all关键字;

union all可以保留多份不去重;

union去重;

依旧是刚刚的四个表:

 查询id小于3,或者名字为英文的课程: 

讲到这里,SQL的基本用法,也就告一段落啦, 写SQL始终要追究高内聚,低耦合,这才是好代码~多练习,熟能生巧~


转载:https://blog.csdn.net/weixin_69417428/article/details/128482690
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场