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. SYCOJ304末尾0的个数

    https://oj.shiyancang.cn/Problem/304.html 首先数据范围不可能算出来的,那么就要看数的性质. 0是怎么来的首先我们知道,有一个0,就必然会有一个5和2. n!在 ...

  2. Redis 应用问题

    Redis 应用问题 1.缓存穿透 1.1.问题概述 key 对应的数据在数据源中不存在,每次针对此 key 的请求从缓存获取不到,请求都会压到数据源(也就是不断的去查数据库,从而使得数据库系统崩溃) ...

  3. 在asp.net webfrom 中完成用户自定义导出

    asp.net原生控件实现自定义列导出功能 自定义列实现 最近负责开发公司内部使用的人事信息化系统时,有一个需求是这样的,需要在页面中可以用户每次导出Excel时自定义需要导出哪些列,经过半天的琢磨和 ...

  4. WAFW00F waf识别工具 源码学习

    我实习工作的第一个任务根据已有的java waf识别工具 实现了一个python的waf识别工具 代码结构非常乱 仅仅达到了能用的水平. 顶头svp推荐这个项目当时我已经写好了开始用了自己的 稍微看了 ...

  5. Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  6. unittest测试框架

    unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果. 一.u ...

  7. 【reverse】逆向1 数据宽度

    [reverse]逆向1 数据宽度 前言 感觉学逆向的都是大佬,正好最近在看java视频的时候,发现讲课的老师居然是从逆向行业转行来的,顿时肃然起敬.于是想在暑假的最后发光发热,把逆向的基础知识学习稳 ...

  8. Solon Web 开发,十四、与Spring、Jsr330的常用注解对比

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  9. cesium结合geoserver利用WFS服务实现图层编辑(附源码下载)

    前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...

  10. javascript的AMD规法--esl与requirejs浅介。

    AMD规范,全称是Asynchronous Module Definition,即异步模块加载机制.从它的规范描述页面看,AMD很短也很简单,但它却完整描述了模块的定义,依赖关系,引用关系以及加载机制 ...