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. JVM调优2-远程监控

    监控远程JVM VisualJVM不仅是可以监控本地jvm进程,还可以监控远程的jvm进程,需要借助于JMX技术实现. 什么是JMX JMX(Java Management Extensions,即J ...

  2. 【小记录】cv::cuda::Stream中取出cudaStream_t并用于核函数的计算

    以下是找到的代码 1 cv::cuda::Stream stream; 2 cudaStream_t s = cv::cuda::StreamAccessor::getStream(stream); ...

  3. 【记录一个问题】macos下使用opencl, clSetEventCallback不生效

    一开始的调用顺序是这样: enqueueWriteBuffer enqueueNDRangeKernel enqueueReadBuffer SetEventCallback 执行后主程序用getch ...

  4. 短视频正当时,如何让你的App快速构建视频创作能力?

    视频编辑服务(Video Editor Kit)是华为开放给开发者快速构建视频编辑能力的服务,提供视频导入.编辑处理.特效渲染.视频导出.媒体资源管理等一站式视频处理能力.视频编辑服务为全球开发者提供 ...

  5. java IO 文件复制代码模型

    package com.xjtu.demo; import java.io.*; public class FileCopy { public static void main(String[] ar ...

  6. DBeaver下载安装与连接MySQL数据库

    一.Dbeaver下载 官网下载地址:Download | DBeaver Community 点击"Windows 64 bit (installer)"即可进行下载. 二.Db ...

  7. 函数的参数python教程

    一:函数 什么是函数? 函数就类似于工具 提前定义之后可以反复使用 代码冗余 结构清晰 修改繁杂等问题 二:函数的语法结构 def 函数名(参数1,参数2) '''函数注释''' 函数体代码 retu ...

  8. K8S配置多集群访问

    中文官档: http://docs.kubernetes.org.cn/823.html 背景:我们通过会有多个k8s集群,例如集群(cn-k8s)和集群(jp-k8s),那个就需要有一台服务器可以同 ...

  9. AWS SAA_C01 考试分享。

    Saa-c01 经验分享! 序言1.介绍自己的情况,我是一个做后台开发的初级java程序员.还是处于在写业务逻辑的阶段,我对aws可谓是啥都不懂,纯种的小白,完全是从0基础开始学习的.希望分享一些我的 ...

  10. from 表单上传多个文件?

    和单个上传文件基本相同,就是需要在后台控制器中,用数组来接收 jsp页面提交过来的file数据. 也分为三个部分演示. 一.jsp <%-- Created by IntelliJ IDEA. ...