MySQL快速入门(二)



约束条件

在上一篇说到建表语句的完整结构

create table t(字段 类型 约束条件);

约束条件:
unsigned 让数字没有正负号
zerofill 多余的使用数字0填充
not null 非空
default 默认值
unique 唯一值
primary key 主键
foreign key 外键
auto_increment 自增
# 无符号:id int unsigned
新增表数据的方式
方式1: 按照字段顺序一一传值
insert into t1 values(1,'Hammer');
方式2: 自定义传值顺序 甚至不传
insert into t1(name,id) values('Hammer',1);
insert into t1(id) values(1); # name没有传就为null
在MySQL中不传数据 会使用关键字NULL填充意思就是空 类似于python的None # 非空
create table t2(
id int,
name varchar(32) not null
); # 默认值:所有的字段都可以设置默认值,用户不给该字段传值则使用默认的,否则使用传了的
create table t3(
id int default 911,
name varchar(16) default 'Hammer'
); # 唯一值:unique
单列唯一 ->
create table t4(
id int,
name varchar(32) unique
);
联合唯一
create table t5(
id int,
host varchar(32),
port int,
unique(host,port)
);

自增

由于主键类似于数据的唯一标识,并且主键一般都是数字类型,一般将自增设置给序号类型的字段,比如id(主键),····

  • auto_increment
create table t6(
id int primary key auto_increment,
name varchar(32)
);

自增的特性

通俗的理解,序号删除了就会接着以前的序号往下排,或者插入了序号失败的就不计入,那么在mysql中,序号插入失败后台也会记录,比如插入id=1失败了,那么下次就会从2开始记··

自增不会因为删除操作而回退
delete from 无法影响自增
如果想要重置需需要使用truncate关键字
truncate 表名 # 清空表数据并且重置主键值

主键

主键通俗的理解为是not null+unique就是主键,由此可见主键的特征就是非空且唯一,必须有唯一性,比如id,每个人的id号唯一,那么就可以给它设置一个主键作为唯一标识;

主键的存在也加快了数据的查询速度;

'''
InnoDB存储引擎规定了一张表必须有且只有一个主键,因为InnoDB是通过主键的方式来构造表的
'''
如果没有设置主键,InnoDB内部会如何变化?
情况一:没有主键和其他约束条件
# InnoDB会采用隐藏的字段作为主键 不能加快数据的查询 情况二:没有主键但是有非空且唯一的字段
# InnoDB会自动将该字段升级为主键
create table t7(
id int not null unique,
name varchar(32)
);

外键

外键的存在解决了表内容重点不清晰,重复字段浪费空间,扩展性差等问题;

比如一个员工表内有员工的基本信息,也统计了员工所在部门的相关信息,这样表的重点就会不清晰,到底是统计员工信息还是部门信息,并且一个部门会对应多个员工,会导致字段重复浪费空间等问题····

解决方式就是,员工表写员工信息,部门表写部门信息,多表存在,使用外键来使得表与表之间确立对应关系,员工所在的部门有该部门的编号,例如dep_id对应了部门表的id;从而确立了表与表之间的数据关系!

级联更新/删除

用外键做了表与表的对应关系后,那么操作(增删改)一个表数据,是不允许的;

那么可以通过添加级联更新和删除来同步数据,添加在设置外键下边···

  • on update cascade:级联更新
  • on delete cascade:级联删除

表与表之间的关系

  • 一对多
  • 多对多
  • 一对一
  • 没有对应关系

ps:表关系没有'多对一'

如何判断两个表或者多个表之间存在关系?用“换位思考”的方法

一对多

# 判断是否为一对多关系:
-> 员工表和部门表举例
--->员工表的角度:
一个员工可以对应多个部门吗?
不可以!
--->部门表的角度:
一个部门可以对应多个员工吗?
可以!
'''
类似上面的这种关系,一个可以一个不可以,那么表关系就是'一对多'!
'''

SQL语句实现

# 使用sql语句实现,先建立不含外键的表
create table dep(
id int primary key auto_increment,
dep_name varchar(32),
dep_desc varchar(254)
);
create table emp(
id int primary key auto_increment,
name varchar(11),
age int,
dep_id int,
foreign key(dep_id) references dep(id)
); insert into dep(dep_name,dep_desc) values('财务部','财政大权'),('人事部','人才引进'),('销售部','商品出售');
mysql> select *from dep;
+----+-----------+--------------+
| id | dep_name | dep_desc |
+----+-----------+--------------+
| 1 | 财务部 | 财政大权 |
| 2 | 人事部 | 人才引进 |
| 3 | 销售部 | 商品出售 |
+----+-----------+--------------+
insert into emp(name,age,dep_id) values('Hammer',18,1),('Hans',28,2),('jason',38,3),('he',18,1);
mysql> select * from emp;
+----+--------+------+--------+
| id | name | age | dep_id |
+----+--------+------+--------+
| 1 | Hammer | 18 | 1 |
| 2 | Hans | 28 | 2 |
| 3 | jason | 38 | 3 |
| 4 | he | 18 | 1 |
+----+--------+------+--------+
# 这样插入表数据的时候,需要依据外键规定的部门编号来插入数据,部门编号是固定的,插入没有的部门编号报错
mysql> insert into emp(name,age,dep_id) values('Hammer',18,5);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key

多对多关系

# 同样使用换位思考的方法
书籍表和作者表举例
->书籍表的角度
---> 一本书可以对应多个作者吗?
可以
---> 一个作者可以写多本书吗?
可以
'''
类似这种双方都可以的情况,就是多对多的关系!
'''
# 注意!!!!
1、多对多关系创建表的时候,不能像"一对多"关系那样创建,因为两边有对应关系,需要都写入外键,那么创建一个表另外一个表没有创建,写入外键就会报错
2、此时,需要第三张表来存储对应关系

SQL语句实现

create table book(
id int primary key auto_increment,
book_name varchar(32),
price float(6,2)
);
create author(
id int primary key auto_increment,
name varchar(11),
age int
);
create table bookandauthor(
id int primary key auto_increment,
author_id int,
book_id int,
foreign key(author_id) references author(id)
on update cascade
on delete cascade,
foreign key(book_id) references book(id)
on update cascade
on delete cascade,
);

一对一关系

# 换位思考的方法
游戏人物表和任人物详细信息表
->游戏人物表角度
---> 一个人物可以对应多个详细信息吗?
不可以
--->一个详细信息可以对应多个人物吗?
不可以
# 通俗理解为一个人一个身份证这种关系,就类似"9527"是你的编号一样~~~
'''
类似这种关系,双向不可以(×),就是一对一的关系或者没关系!
'''

注意

  • 外键字段建在任何一方都可以,但是推荐建在查询频率较高的表中

SQL语句实现

create table peo(
id int primary key auto_increment,
name varchar(11),
height int,
info_id int unique,
foreign key(info_id) references det_info(id)
on update cascade
on delete cascade
);
create table det_info(
id int primary key auto_increment,
color varchar(32),
skill varchar(32)
);

外键约束

  • 在创建表的时候,需要注意先创建没有设置外键的表
  • 在插入数据的时候,要确保被关联表中有数据
  • 在插入新数据的时候,外键字段只能填写被关联表中已经存在的数据
  • 在修改和删除被关联表中的数据的时候,无法直接操作,需要添加级联更新/删除

操作表方法

方法如下

方法名 说明 格式
rename 修改表名 ALTER TABLE 表名 RENAME 新表名;
add 增加字段(默认在尾部追加,可以通过first和after来指定字段添加的位置) ALTER TABLE 表名 ADD 字段名 数据类型 [完整性约束条件…],
ALTER TABLE 表名 ADD 字段名 数据类型 [完整性约束条件…] FIRST;
ALTER TABLE 表名 ADD 字段名 数据类型 [完整性约束条件…] AFTER 字段名;
drop 删除字段 ALTER TABLE 表名 DROP 字段名;
modify 修改字段 ALTER TABLE 表名 MODIFY 字段名 数据类型 [完整性约束条件…];
change 修改字段 ALTER TABLE 表名 CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…];

ps:modify只能改字段数据类型完整约束,不能改字段名,但是change可以!

查询关键字

练习数据

# 数据准备
create table emp(
id int primary key auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一个部门一个屋子
depart_id int
); #插入记录
#三个部门:教学,销售,运营
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('Hammer','male',18,'20170301','CEO',7300.33,401,1), #以下是教学部
('tom','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tony','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jack','female',18,'20110211','teacher',9000,401,1),
('jenny','male',18,'19000301','teacher',30000,401,1),
('sank','male',48,'20101111','teacher',10000,401,1),
('哈哈','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('呵呵','female',38,'20101101','sale',2000.35,402,2),
('西西','female',18,'20110312','sale',1000.37,402,2),
('乐乐','female',18,'20160513','sale',3000.29,402,2),
('拉拉','female',28,'20170127','sale',4000.33,402,2),
('僧龙','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3);

select··from

  • select * from 表名 :查询该所有数据
  • select 字段名1,字段2 from 表名:查询该表指定字段
select * from emp;
select id,name from emp;

where 筛选

where功能主要是针对查询出来的数据在分组前进行筛选

示例

1.查询id大于等于3小于等于6的数据
select * from emp where id>=3 and id<=6;
select * from emp where id between 3 and 6;
2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary in (20000,18000,17000);
select * from emp where salary=18000 or salary=17000 or salary=20000;
3.查询员工姓名中包含o字母的员工姓名和薪资
select name,salary from emp where name like '%o%';
4.查询员工姓名是由四个字符组成的员工姓名与其薪资
select name,salary from emp where name like '____';
select name salary from emp where char_length(name)=4;
5.查询id小于3或者大于6的数据
select * from emp where id<3 or id>6;
select * from emp where id not between 3 and 6;
6.查询薪资不在20000,18000,17000范围的数据
select * from emp where salary not in (20000,18000,17000);
7.查询岗位描述为空的员工名与岗位名 (针对null不能用等号,只能用is)
select name,post from emp where post_comment is null;

group by 分组

分组是按照指定的条件,将个体归为一个个整体

需要注意的是,如果在不适用函数的情况下,按哪个字段分组, 那么查询的时候只能操作该字段相关的数据,比如按post分组,那么name,id等字段不可直接获取

针对5.6需要自己设置sql_mode
set global sql_mode = 'only_full_group_by,STRICT_TRANS_TABLES,PAD_CHAR_TO_FULL_LENGTH';
# 重新连接客户端

聚合函数

聚合函数主要就是配合分组一起使用

  • max:最大
  • min:最小
  • sum:总和
  • count:个数
  • avg:平均
1.按部门分组
select * from emp group by post;
# 分组后取出的是每个组的第一条数据
mysql> select id,name,sex from emp group by post;
+----+--------+--------+
| id | name | sex |
+----+--------+--------+
| 1 | Hammer | male |
| 14 | 僧龙 | male |
| 9 | 哈哈 | female |
| 2 | tom | male |
+----+--------+--------+ """
设置sql_mode为only_full_group_by,意味着以后但凡分组,只能取到分组的依据,
不应该在去取组里面的单个元素的值,那样的话分组就没有意义了,因为不分组就是对单个元素信息的随意获取
""" # 设置了之后再取数据,就得取和分组相关的数据,不然会报错
select * from emp group by post; # 报错
select id,name,sex from emp group by post; # 报错 # 只要分组了,就不能够再“直接”查找到单个数据信息了,只能获取到组名
select post from emp group by post; # 获取部门信
+-----------+
| post |
+-----------+
| CEO |
| operation |
| sale |
| teacher |
+-----------+

分组只能获取组名,那么想获取到其它信息可以通过聚合函数来获取

1.获取每个部门的最高工资
mysql> select post,max(salary) from emp group by post;
+-----------+-------------+
| post | max(salary) |
+-----------+-------------+
| CEO | 7300.33 |
| operation | 20000.00 |
| sale | 4000.33 |
| teacher | 1000000.31 |
+-----------+-------------+
mysql> select post as '部门',max(salary) as '工资' from emp group by post;
+-----------+------------+
| 部门 | 工资 |
+-----------+------------+
| CEO | 7300.33 |
| operation | 20000.00 |
| sale | 4000.33 |
| teacher | 1000000.31 |
+-----------+------------+
# as 可以给查询结果起别名,来指定更明确的意思 2、每个部门的最低工资
mysql> select post as '部门',min(salary) as '工资' from emp group by post;
+-----------+----------+
| 部门 | 工资 |
+-----------+----------+
| CEO | 7300.33 |
| operation | 10000.13 |
| sale | 1000.37 |
| teacher | 2100.00 |
+-----------+----------+
3、每个部门的平均工资
mysql> select post,avg(salary) from emp group by post;
+-----------+---------------+
| post | avg(salary) |
+-----------+---------------+
| CEO | 7300.330000 |
| operation | 16800.026000 |
| sale | 2600.294000 |
| teacher | 151842.901429 |
+-----------+---------------+
4、每个部门的工资总和
mysql> select post,sum(salary) from emp group by post;
+-----------+-------------+
| post | sum(salary) |
+-----------+-------------+
| CEO | 7300.33 |
| operation | 84000.13 |
| sale | 13001.47 |
| teacher | 1062900.31 |
+-----------+-------------+
5、每个部门的人数
mysql> select post,count(id) from emp group by post;
+-----------+-----------+
| post | count(id) |
+-----------+-----------+
| CEO | 1 |
| operation | 5 |
| sale | 5 |
| teacher | 7 |
+-----------+-----------+

group_concat 和 concat函数

group_concat函数用于分组后,获取该字段的数据

mysql> select post,age,name from emp group by post; # 不使用group_concat函数报错
ERROR 1055 (42000): 'oldboy.emp.age' isn't in GROUP BY' # 使用了group_concat函数
mysql> select post,group_concat(name,age) from emp group by post;
+-----------+----------------------------------------------------------+
| post | group_concat(name,age) |
+-----------+----------------------------------------------------------+
| CEO | Hammer18 |
| operation | 程咬铜18,程咬银18,程咬金18,僧龙28,程咬铁18 |
| sale | 呵呵38,拉拉28,乐乐18,西西18,哈哈48 |
| teacher | jack18,sank48,owen28,tony73,kevin81,tom78,jenny18 |
+-----------+----------------------------------------------------------+ # group_concat函数还可以美化
mysql> select post,group_concat('{',name,':',age,'}') from emp group by post;
+-----------+-------------------------------------------------------------------------+
| post | group_concat('{',name,':',age,'}') |
+-----------+-------------------------------------------------------------------------+
| CEO | {Hammer:18} |
| operation | {程咬铜:18},{程咬银:18},{程咬金:18},{僧龙:28},{程咬铁:18} |
| sale | {呵呵:38},{拉拉:28},{乐乐:18},{西西:18},{哈哈:48} |
| teacher | {jack:18},{sank:48},{owen:28},{tony:73},{kevin:81},{tom:78},{jenny:18} |
+-----------+-------------------------------------------------------------------------+

concat函数 不分组就可以使用

mysql> select concat('{',name,':',age,'}') from emp;

Having 过滤

where与having都是筛选功能区别在于:

where在分组前使用,having在分组后使用

# 获取部门所有年龄大于30平均薪资大于10000的员工名字
mysql> select post,group_concat(name) from emp where age>30 group by post having avg(salary>30);
+---------+---------------------+
| post | group_concat(name) |
+---------+---------------------+
| sale | 哈哈,呵呵 |
| teacher | tom,kevin,tony,sank |
+---------+---------------------+

Distinct 去重

去重操作,一定有重复数据,如果一列有重复数据,另一列没有,同时操作这两列也是不去重的

select distinct id,age from emp;  # NO
select distinct post from emp; # YES

ORDER BY 排序

单列排序

按照单个字段或者表达式的值进行排序称为单列排序

SELECT col1, col2, ...
FROM t
ORDER BY col1 [ASC | DESC]; # ORDER BY 用于指定排序的字段;ASC升序排序,DESC 降序排序
# 获取部门编号为3的员工信息,并将工资从高到低排序
SELECT emp_name, salary
FROM employee
WHERE dept_id = 3
ORDER BY salary DESC; # 统计各部门年龄在20岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资进行排序
select post,avg(salary) from emp where age>10 group by post having avg(salary)>1000 order by avg(salary) desc;

多列排序

多列排序是指基于多个字段或表达式的排序,使用逗号进行分隔

SELECT col1, col2, ...
FROM t
ORDER BY col1 ASC, col2 DESC, ...;
# 首先基于第一个字段进行排序;对于第一个字段排序相同的数据,再基于第二个字段进行排序;依此类推
# 获取部门编号为3的员工信息,并且按照月薪从高到低排序,月薪相同时再按照入职先后进行排序
SELECT emp_name, salary, hire_date
FROM employee
WHERE dept_id = 4
ORDER BY salary DESC, hire_date;

空值排序

空值(NULL)在 SQL 中表示未知或者缺失的值,MySQL认为空值最小,升序时空值排在最前,降序时空值排在最后

insert into empinfo values(3,'hans','','2022-2-1');
select salary from empinfo order by salary;
+--------+
| salary |
+--------+
| |
| 10000 |
| 20000 |
+--------+

limit 分页

MySQL支持使用 LIMIT 实现分页的效果

SELECT emp_name, salary
FROM emp
ORDER BY salary DESC
LIMIT 5 OFFSET 0; # ORDER BY 按照月薪从高到低进行排序;OFFSET 表示跳过 0 行,LIMIT 返回前 5 条数据,也就是月薪 Top-5 的员工。另外,OFFSET 可以省略,

MySQL支持两种写法:

  • LIMIT 5 OFFSET 10
  • LIMIT 10, 5
  • 都表示跳过 10 行,返回随后的 5 行数据

MySQL快速入门(二)的更多相关文章

  1. Mysql快速入门(二)

    多表关联查询 JOIN 按照功能大致分为如下三类: CROSS JOIN(交叉连接) INNER JOIN(内连接或等值连接). OUTER JOIN(外连接) 交叉连接 交叉连接的关键字:CROSS ...

  2. MySql基础笔记(一)Mysql快速入门

    Mysql快速入门 一)基本概念 1)表 行被称为记录,是组织数据的单位.列被称为字段,每一列表示记录的一个属性. 2)主键 主键用于唯一的标识表中的每一条记录.可以定义表中的一列或者多列为主键, 但 ...

  3. MySQL 快速入门教程

    转:MySQL快速 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据 ...

  4. MySQL 快速入门(一)

    目录 MySQL快速入门 简介 存储数据的演变过程 数据库分类 概念介绍 MySQL安装 MySQL命令初始 环境变量配置 MySQL环境变量配置 修改配置文件 设置新密码 忘记密码的情况 基本sql ...

  5. python3.5+django2.0快速入门(二)

    昨天写了python3.5+django2.0快速入门(一)今天将讲解配置数据库,创建模型,还有admin的后台管理. 配置数据库 我们打开mysite/mysite/settings.py这个文件. ...

  6. Mysql快速入门(看完这篇能够满足80%的日常开发)

    这是一篇mysql的学习笔记,整理结合了网上搜索的教程以及自己看的视频教程,看完这篇能够满足80%的日常开发了. 菜鸟教程:https://www.runoob.com/mysql/mysql-tut ...

  7. SQL快速入门 ( MySQL快速入门, MySQL参考, MySQL快速回顾 )

    SQL 先说点废话,很久没发文了,整理了下自己当时入门 SQL 的笔记,无论用于入门,回顾,参考查询,应该都是有一定价值的,可以按照目录各取所需.SQL数据库有很多,MySQL是一种,本文基本都是SQ ...

  8. mysql快速入门

    一.下载并解压 $ wget http://cdn.mysql.com/Downloads/MySQL-5.5/MySQL-5.5.42-1.el6.x86_64.rpm-bundle.tar 解压后 ...

  9. 阿里云RDS for MySQL 快速入门——笔记

    1初始化配置 1.1设置白名单 创建RDS实例后,需要设置RDS实例的白名单,以允许外部设备访问该RDS实例.默认的白名单只包含默认IP地址127.0.0.1,表示任何设备均无法访问该RDS实例. 设 ...

随机推荐

  1. HTML5元素

    1.1结构元素 HTML5定义了一组新的语义化标签,目前主流浏览器均已支持,语义化标签使用标记元素的内容,虽然可以使用原有标签替换,但是它可以简化HTML页面设计,并且也为搜索引擎在抓取和索引网页的时 ...

  2. HDU 1754 I Hate It(线段数-单点更新)

    原题链接:I Hate It 题目分析:这个是线段树的基本操作--更新和查询,属于基础题,也就相当于一个模板吧,这里就不再多说了. 代码如下:(PS:特别注意--输入输出用  不然会超时) #incl ...

  3. 2021最新Termux安装Metasploit

    前言 因为某些脚本小子的用Termux搞破坏,所以Termux软件源移除了对Metasploit的支持,所以就不能直接用pkg和apt直接安装了. 但是不用担心,noob-hacker大大写了一个工具 ...

  4. ES6随笔D1

    1.数值解构赋值 ES6 允许按照一定模式,可以从数组中提取值,按照对应位置,对变量赋值,这被称为解构. 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象.由于undefined和n ...

  5. Java Selenide 介绍&使用

    目录 Selenide 介绍 官方快速入门 元素定位 元素操作 浏览器操作 断言 常用配置 Selenide 和 Webdriver 对比 Selenide 介绍 Selenide github Se ...

  6. 浅析Java中的线程池

    Java中的线程池 几乎所有需要异步或并发执行任务的程序都可以使用线程池,开发过程中合理使用线程池能够带来以下三个好处: 降低资源消耗 提高响应速度 提高线程的可管理性 1. 线程池的实现原理 当我们 ...

  7. 用Python实现一个Picgo图床工具

    PyPicGo PyPicGo 是一款图床工具,是PicGo是Python版实现,并支持各种插件自定义插件,目前PyPicGo自带了gitee.github.SM.MS和七牛云图传,以及rename. ...

  8. gin框架中中间件的编写与使用

    概念 一个完整的系统可能包括鉴权认证.权限管理.安全检查.日志记录等多维度的系统支持. 中间件位与服务器和实际业务处理程序之间,其含义就相当于在请求和具体的业务处理逻辑之间增加某些操作,这种以额外增加 ...

  9. 在Chrome中打开网页时出现以下问题 您的连接不是私密连接 攻击者可能会试图从 x.x.x.x 窃取您的信息(例如:密码、通讯内容或信用卡信息)

    现象:在Chrome中打开网页时出现以下问题 您的连接不是私密连接 攻击者可能会试图从 x.x.x.x 窃取您的信息(例如:密码.通讯内容或信用卡信息). 当点开"了解详情"后显示 ...

  10. 使用 Kubeadm+Containerd 部署一个 Kubernetes 集群

    本文独立博客阅读地址:https://ryan4yin.space/posts/kubernetes-deployemnt-using-kubeadm/ 本文由个人笔记 ryan4yin/knowle ...