MySQL概述(基础)
SQL
全称Structured Query Language,结构化察浑语言。操作关系型数据库的编程语言,定义了一套操作关系型数据库的统一标准。
SQL通用语法
SQL语言的统统用语法:
- SQL语句可以单行或多行书写,以分号结尾
- SQL语句可以使用空格/缩进来增强语句的可读性
- MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。
- 注释:
- 单行注释:–注释内容 或 # 注释内容
- 多行注释: /* 注释内容 */
SQL分类
SQL语句,根据功能,主要分为四类:DD、DML、DQL、DCL
分类 | 全称 | 说明 |
---|---|---|
DDL | Data Definition Language | 数据定义语言,用来定义数据库对象(数据库,表,字段) |
DML | Data Manipulation Language | 数据操作语言,用来对数据库表中的数据进行增删改查 |
DQL | Data Query Language | 数据查询语言,用来查询数据库中表的记录 |
DCL | Data Control Language | 数据控制语言,用来创建数据库用户、控制数据库的访问权限 |
DDL
Data Definition Language,数据定义语言,用来定义数据库对象(数据库,表,字段)
数据库操作
1、查询所有数据库
show databases;
2、查询当前数据库
select database();
3、创建数据库
create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则];
例子:
1、创建一个itcast数据库,使用数据库默认的字符集
create database itcast;
注意:在同一数据库服务器中,不能创建两个名称相同的数据库,否则将会报错。可以通过if not exists
参数来解决这个问题,数据库不存在,则创建该数据库,如果存在,则不创建。
create database if not exists itcast;
2、创建一个demo数据库,并且指定字符集
create database demo default charset utf8mb4;
4、删除数据库
drop database [if exists ] 数据库名;
如果删除一个不存在的数据库,将会报错。此时可以加上参数if exists
,如果数据库存在,再执行删除,否则不执行删除
5、切换数据库
use 数据库名;
表操作
表操作-查询创建
1、查询当前数据库中的所有表
show tables;
2、查看指定表结构
desc 表名;
通过这条指令,可以查看到指定表的字段、字段类型、是否可以为null、是否存在默认值等信息
3、查询指定表的建表语句
show create table 表名;
通过这条指定,主要用来查看建表语句的,而有部分参数在创建表的时候,并未指定也会查询到,因为部分是数据库的默认值,如:存储引擎、字符集等。
4、创建表结构
create table 表名{
字段1 字段1类型 [ comment 字段1注释 ],
字段2 字段2类型 [ comment 字段2注释 ],
字段3 字段3类型 [ comment 字段3注释],
…
字段n 字段n类型 [comment 字段n注释 ],
} [comment 表注释];
注意:[…] 内为可选参数,最后一个字段后面没有逗号
例子:
如:创建一张表tb_user,对应的结构如下,那么建表语句为:
id | name | age | gender |
---|---|---|---|
1 | 令狐冲 | 28 | 男 |
2 | 风清杨 | 68 | 男 |
3 | 东方不败 | 32 | 男 |
create table tb_user{
id int comment '编号',
name varchar(50) comment '姓名',
age int comment '年龄',
gender varchar(1) comment '性别'
} comment '用户表';
表操作-数据类型
MySQL中的数据类型有很多,主要有三类:数值类型、字符串类型、日期时间类型。
1、数值类型
类型 | 大小 | 有符号(SIGNED)范围 | 无符号(UNSIGNED)范围 | 描述 |
---|---|---|---|---|
TINYINT | 1bytes | (-128,127) | (0,255) | 小整数值 |
SMALLINT | 2bytes | (-32768,32767) | (0,65535) | 大整数值 |
MEDIUMINT | 3bytes | (-8388608,8388607) | (0,16777215) | 大整数值 |
INT/INTEGER | 4bytes | (-2147483648,2147483647) | (0,4294967295) | 大整数值 |
BIGINT | 8bytes | (-263,263-1) | (0,2^64-1) | 极大整数之 |
FLOAT | 4bytes | (-3.402823446E+38,3.402823466351E+38) | 0和(1.175494351E-38,3.402823466E+38) | 单精度浮点数值 |
DOUBLE | 8bytes | (-1.7976931348623157E+308,1.7976931348623157E+308) | 0和(2.2250738585072014E-308,1.7976931348623157E+308) | 双精度浮点数值 |
DECIMAL | 依赖于M(精度)和D(标度)的值 | 依赖于M(精度)和D(标度)的值 | 小数值(精确定点数) |
如:
- 年龄字段——不会出现负数,而且人的年龄不会太大
- age tinyint unsigned
- 分数——总分100分,最多出现一位小数
- Score double(4,1)
2、字符串类型
类型 | 大小 | 描述 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串(需要指定长度) |
VARCHAR | 0-65535 bytes | 变长字符串(需要指定长度) |
TINYBLOB | 0-255 bytes | 不超过255个字符的二进制数据 |
TINYTEXT | 0-255 bytes | 短文本字符串 |
BLOB | 0-65535 bytes | 二进制形式的长文本数据 |
TEXT | 0-65535 bytes | 长文本数据 |
MEDIUMBLOB | 0-16777215 bytes | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16777215 bytes | 中等长度文本数据 |
LONGBLOB | 0-4293967295 bytes | 二进制形式的极大文本数据 |
LONGTEXT | 0-4294967295 bytes | 极大文本数据 |
注意:char与varchar都可以描述字符串,char是定长字符串,指定长度多长,就占用多少个字符,和字段值的长度无关。而varchar是变长字符串,指定的长度为最大占用长度。相对来说,char的性能会稳定
例子:
用户名username-------> 长度不定,最长不会超过50
username varchar(50)
性别 gender---------->存储值,不是男,就是女
gender char(1)
手机号 phone------->固定长度为11
phone char(11)
3、日期时间类型
类型 | 大小 | 范围 | 格式 | 描述 |
---|---|---|---|---|
DATE | 3 | 1000-01-01 至 9999-12-31 | YYYY-MM-DD | 日期 |
TIME | 3 | -838:59:59 至 838:59:59 | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901 至 2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:01 至 2038-01-19 03:14:07 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值,时间戳 |
如:
生日字段birthday
birthday date
创建时间 createtime
creattime datetime
表操作——案例
设计一张员工信息表,要求如下:
- 编号(纯数字)
- 员工工号(字符串类型,长度不超过10位)
- 员工姓名(字符串类型,长度不超过10位)
- 性别(男/女,存储一个汉字)
- 年龄(正常人年龄不可能存储负数)
- 身份证号(二代身份证号均为18位,身份证中有x这样的字符)
- 入职时间(取值年月日即可)
对应的建表语句如下:
create table emp{
id int comment '编号',
workno varchar(10) comment '工号',
name varchar(10) comment '姓名',
gender char(1) comment '性别',
age tinyint unsigned comment '年龄',
idcard char(18) comment '身份证号',
entrydate date comment '入职时间'
} comment '员工表';
表操作-修改
1、添加字段
alter table 表明 add 字段名 类型(长度) [comment 注释] [ 约束 ];
例子:
alter table emp add nickname varchar(20) comment '昵称';
2、修改数据类型
alter table 表名 modify 字段名 型数据类型(长度);
3、修改字段名和字段类型
alter table 表名 change 旧字段名 类型(长度) [ comment 注释 ] [ 约束 ];
例子:
将emp表的nickname字段修改为username,类型为varchar(30)
alter table emp change nickname username varchar(30) comment '昵称';
4、删除字段
alter table 表名 drop 字段名;
例子:
将emp表的字段username删除
alter table emp drop username;
5、修改表名
alter table 表名 rename to 新表名;
例子:
将emp表的表名修改为employee
alter table emp rename to employee;
表操作-删除
1、删除表
drop table [ if exists ] 表名;
注意:可选项 if exists 代表,只有表名存在时才会删除,表明不存在,则不执行删除操作(如果不加该参数项,删除一张不存在的表,执行会报错)。
例子:
如果tb_user表存在,则删除tb_user表
drop table if exists tb_user;
2、删除指定表,并重新创建表
truncate table 表名;
注意:在删除表的时候,表中的全部数据也都会被删除。
图形化界面工具
通过DDL语句在命令行中进行操作,主要存在两点问题:
- 会影响开发效率
- 使用起来,并不直观,并不方便
mysql主流的图形化界面工具有:
DML
DML英文全称是Data Mainipulation Language(数据操作语言),用来对数据库中表的数据记录进行增删改操作。
- 添加元素(insert)
- 修改元素(update)
- 删除数据(delete)
添加元素
1、给定字段添加数据
insert into 表名(字段名1,字段名2,…) values(值1,值2,…);
案例:给employee表所有的字段添加数据
insert into employee(id, workno, name, gender, age, idcard, entrydate) values (1, '1', 'Itcast', '男', 10, '123456789012345678', '2000-01-01');
查看数据库的数据:
select * from employee;
案例:给employee表所有的字段添加数据
执行如下SQL,添加的年龄字段值为-1
insert into employee(id, workno, name, gender, age, idcard, entrydate) values (1, '1', 'Itcast', '男', -1, '123456789012345678', '2000-01-01');
执行上述sql语句时,报错了。原因:employee表的age字段类型为tinyint,而且还是无符号的unsigned,所以取值只能在0-255之间。
2、给全部字段添加数据
insert into 表名 values (值1,值2,…);
案例:插入数据到employee表,具体的sql如下:
insert into employee values(2,'2','张无忌','男',18,'123456789012345670','2005-01-01');
3、批量添加数据
insert into 表名(字段名1,字段名2,…) values (值1,值2,…),(值1,值2,…);
insert into 表名 values(值1,值2,…),(值1,值2,…);
案例:批量插入数据到employee表,具体的sql如下:
insert into employee values(3,'3','韦一笑','男',38,'123456789012345670','2005-01-
01'),(4,'4','赵敏','女',18,'123456789012345670','2005-01-01');
注意:
- 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
- 字符串和日期型数据应该包含在引号中
- 插入数据大小,应该在字段的规定范围内
4、修改数据
修改数据的具体语法为:
update 表名 set 字段名 = 值1,字段名2 = 值2,…[ where 条件 ];
案例:
修改id为1的数据,将name修改为demo
update employee set name = 'demo' where id = 1;
修改id为1的数据,将name修改为小赵,gender修改为女
update employee set name = '小赵', gender = '女' where id = 1;
将所有的员工入职日期修改为2008-01-01
update employee set entrydate = '2000-01-01';
注意:修改语句的条件可以有,也可以没有,如果没有条件,则会修改整张表的所有数据。
5、删除数据
删除数据的具体语法为:
delete from 表名 [ where 条件 ];
案例:
删除gender为女的员工
delete from employee where gender = '女';
删除所有员工
delete from employee;
注意:
- delete语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据
- delete语句不能删除某一个字段的值(可以使用update,将该字段值设置为null即可)
- 当进行删除全部数据操作时,datagrip会提示,询问是否确认删除,直接点击Execute即可
DQL
DQL英文全称是Data Query Languagte(数据查询语言),用来查询数据库中表的记录。
查询关键字:select
具体介绍在之前的博客:MySQL介绍及运用(基础篇)2.0_没办法,我就是这么菜的博客-CSDN博客
DCL
DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访问权限。
管理用户
1、查询用户
select * from mysql.user;
查询结果如下:
其中host代表当前用户访问的主机,如果为localhost,仅代表只能够在当前本机访问,是不可以远程访问的。user代表的是访问该数据库的用户名。在mysql中需要通过host和user来唯一标识一个用户。
2、创建用户
create user ‘用户名’@‘主要名’ identified by ‘密码’;
3、修改用户密码
alter user ‘用户名’@‘主机名’ identified with mysql_native_password by ‘新密码’;
4、删除用户
drop user ‘用户名’@‘主机名’;
注意:
- 在mysql中需要通过用户名@主机名的方式,来唯一标识一个用户
- 主机名可以使用%通配
- 这类sql开发人员操作的比较少,主要是DBA(Database Administrator 数据库管理员)使用
案例:
创建用户demo,只能在当前主机localhost访问,密码123456
create user 'demo'@'localhost' identified by '123456';
创建用户test,可以在任意主机访问数据库,密码123456
create user 'test'@'%' identified by '123456';
修改用户test的访问密码为1234
alter user 'test'@'%' identified with mysql_native_password by '1234';
删除demo@localhost用户
drop user 'demo'@'localhost';
权限控制
MySQL中定义了很多种权限,但是常用的就以下几种:
权限 | 说明 |
---|---|
ALL、ALL PRIVILEGES | 所有权限 |
SELECT | 查询数据 |
INSERT | 插入数据 |
UPDATE | 修改数据 |
DELETE | 删除数据 |
ALTER | 修改表 |
DROP | 删除数据库/表/视图 |
CREATE | 创建数据库/表 |
1、查询权限
show grants for ‘用户名’@‘主机名’;
2、授予权限
grant 权限列表 on 数据库名.表名 to ‘用户名’@‘主机名’;
3、撤销权限
remove 权限列表 on 数据库名.表名 from ‘用户名’@‘主机名’;
注意:
- 多个权限之间,使用逗号分割
- 授权时数据库名和表名可以使用
*
进行通配,代表所有。
案例:
查询’test’@'%'用户的权限
show grants for 'test'@'%';
授予’test’@'%'用户中demo数据库所有表的所有操作权限
grant all on demo.* to 'test'@'%';
撤销’test’@‘%’ 用户中demo数据库的所有权限
revoke all on demo.* from 'test'@'%';
函数
介绍
函数是指一段可以直接被另一段程序调用的程序或代码。也就意味着,这一段程序或代码在MySQL中已经提供了,我们只需要在合适的业务场景调用对应的函数完成对应的业务需求即可。
- 在企业的OA或其他的人力系统中,经常会提供这样一个功能,每一个员工登录之后都能看到当前员工入职的天数。而在数据库中,存储的都是入职日期,如2000-11-12。
- 在做报表这类的业务需求中,需要展示学员的分数等级分布。而在数据库中存储的都是学生的分数值,如98/75
这些需求可以通过Mysql中的函数都可以方便的实现。
MySQL中函数主要分为以下四类:字符串函数、数值函数、日期函数、流程函数。
字符串函数
Mysql中内置了很多字符串函数,常用的几个如下:
函数 | 功能 |
---|---|
concat(s1, s2, …sn) | 字符串拼接,将s1, s2, … sn拼接成一个字符串 |
lower(stt) | 将字符串str全部转为小写 |
upper(str) | 将字符串str全部转为大写 |
rpad(str, n, pad) | 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 |
trim(str) | 去掉字符串头部和尾部的空格 |
substring(str, start, len) | 返回从字符串str从start位置起的len个长度的字符串 |
演示:
concat:字符串拼接
select concat("hello",'MySQL');
lower:全部转小写
select lower('hello');
upper:全部转大写
select upper('hello');
lpad:左填充
select lpad('01', 5, '-');
rpad:右填充
select rpad('01', 5 , '-');
trim:去除空格
select trim('hello Mysql');
substring:截取子字符串
select substring('hello mysql', 1, 5);
案例:
由于业务需求,企业员工的工号,统一为5位数,目前不足5位数的全部在前面补0。
update emp set workno = lpad(workno, 5, '0');
数值函数
常见的数值函数如下:
函数 | 功能 |
---|---|
ceil(x) | 向上取整 |
floor(x) | 向下取整 |
mod(x,y) | 返回x/y的模 |
rand() | 返回0-1内的随机数 |
round(x,y) | 求参数x的四舍五入的值,保留y为位小数 |
演示:
ceil:向上取整
select ceil(1.1);
floor:向下取整
select floor(1.9);
mod:取模
select mod(7, 4);
rand:获取随机数
select rand();
round:四舍五入
select round(2.334, 2);
案例:
通过数据库的函数,生成一个六位数的随机验证码
思路:获取随机数可以通过rand()函数,但是获取出来的随机数是在0-1之间的,所以需要在其基础上乘以1000000,然后舍弃小数部分,如果长度不足6位,补0
select lpad(round(rand()*1000000, 0)), 6, '0');
日期函数
常见的日期函数如下:
函数 | 功能 |
---|---|
CURDATE() | 返回当前日期 |
CURTIME() | 返回当前时间 |
NOW() | 返回当前日期和时间 |
YEAR(date) | 获取指定date的年份 |
MONTH(date) | 获取指定date的月份 |
DAY(date) | 获取指定date的日期 |
DATE_ADD(date, INTERVAL exprtype) | 返回一个日期/时间值加上一个时间间隔expr后的时间值 |
DATEDIFF(date1, date2) | 返回起始时间date1和结束时间date2之间的天数 |
示例:
curdate:当前日期
select curdate();
curtime:当前时间
select curtime();
now:当前日期和时间
select now();
year,month,day:当前年、月、日
select year(now());
select month(now());
select day(now());
date_add:增加指定的时间间隔
select date_add(now(),interval 70 year);
datediff:获取两个日期相差的天数
select datediff('2021-10-01', '2021-12-01');
案例:
查询所有员工的入职天数,并根据入职天数倒序排序
思路:入职天数,就是通过当前日期 - 入职日期,所以需要使用datediff函数来完成
select name, datediff(curdate(), entrydate) as 'entrydays' from emp order by entrydays desc;
流程函数
流程函数也是很常用的一类函数,可以在SQL语句中实现条件筛选,从而提高语句的效率
函数 | 功能 |
---|---|
IF(value, t, f) | 如果value为true,则返回t,否则返回f |
IFNULL(value1, value2) | 如果value1不为空,返回value1,否则返回value2 |
CASE WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END | 如果val1为true,返回res1,… 否则返回default默认值 |
CASE [ expr ] WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END | 如果expr的值等于val1,返回res1,… 否则返回default默认值 |
示例:
if
select if (false, 'OK', 'Error');
ifnull
select ifnull('OK', 'Default');
select ifnull('', 'Default');
select ifnull(null, 'Default');
case when then else end
需求:查询emp表的员工姓名和工作地址(北京/上海---->一线城市,其他—>二线城市)
select
name,
(cass workaddress when '北京' then '一线城市' when '上海' then '一线城市' else '二线城市' end) as '工作地址'
from emp;
案例:
create table score(
id int comment 'ID',
name varchar(20) comment '姓名',
math int comment '数学',
english int comment '英语',
chinese int comment '语文'
) comment '学员成绩表';
insert into score(id, name, math, english, chinese) values (1, 'Tom', 67, 88, 95), (1, 'Rose', 67, 88, 95), (1, 'Jack', 67, 88, 95);
具体的sql语句如下:
select
id,
name,
(case when math >= 85 then '优秀' when math >= 60 then '及格' end) '数学',
(case when english >= 85 then '优秀' when english >= 60 then '及格' end) '英语',
(case when chinese >= 85 then '优秀' when chinese >= 60 then '及格' end) '语文'
from score;
约束
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据
目的:保证数据库中数据的正确、有效性和完整性
分类:
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为null | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一、不重复 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束(8.0.16版本之后) | 保证字段值满足某一个条件 | CHECK |
外键约束 | 用来让两张表的数据之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
注意:约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束
约束演示
案例:
需求:
字段名 | 字段含义 | 字段类型 | 约束条件 | 约束关键字 |
---|---|---|---|---|
id | id唯一标识 | int | 主键,并且自动增长 | PRIMARY KEY, AUTO_INCREMENT |
name | 姓名 | varchar(10) | 不为空,并且唯一 | NOT NULL, UNIQUE |
age | 年龄 | int | 大于0,并且小于等于120 | CHECK |
status | 状态 | char(1) | 如果没有指定该值,默认为1 | DEFAULT |
gender | 性别 | char(1) | 无 |
建表语句为:
create table tb_user(
id int auto_increment primary key comment 'ID唯一标识',
name varchar(10) not null unique comment '姓名',
age int check(age > 0 && age <= 120) comment '年龄',
status char(1) default '1' comment '状态',
gender char(1) comment '性别'
);
在为字段添加约束时,只需要在字段之后添加约束的关键字即可,需要关注语法。
验证:
insert into tb_user(name,age,status,gender) values ('Tom1',19,'1','男'),
('Tom2',25,'0','男');
insert into tb_user(name,age,status,gender) values ('Tom3',19,'1','男');
insert into tb_user(name,age,status,gender) values (null,19,'1','男');
insert into tb_user(name,age,status,gender) values ('Tom3',19,'1','男');
insert into tb_user(name,age,status,gender) values ('Tom4',80,'1','男');
insert into tb_user(name,age,status,gender) values ('Tom5',-1,'1','男');
insert into tb_user(name,age,status,gender) values ('Tom5',121,'1','男');
insert into tb_user(name,age,gender) values ('Tom5',120,'男');
外键约束
介绍
外键:用来让两个表的数据之间建立连接,从而保证数据的一致性和完整性。
左侧的emp表是员工表,里面存储员工的基本信息,包含员工的id、姓名、年龄、职位、薪资、入职日期、上级主管ID、部门id、在员工的信息中存储的是部门的ID——dept_id,而这个部门的id是关联的部门表dept的主键id,那emp表的dept_id就是外键,关联的是另一张表的主键。
注意:目前上述两张表,只是在逻辑上存在这样的一层关系;在数据库层面,并未建立外键关联,所以无法保证数据的一致性和完整性。
在没有数据库外键关联的情况下,如果删除id为1的部门信息,这时就会出现数据的不完整性。因为在执行删除语句后,部门表中就不存在id为1的部门,而在emp表中还有很多的员工,关联的id为1的部门。
语法
1、添加外键
create table 表名(
字段名 数据类型
...
[constraint] [外键名称] foreign key (外键字段名) references 主表(主表列名)
);
alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表 (主表列名);
案例:
为emp表的dept_id字段添加外键约束,关联dept表的主键id
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
删除外键
alter table 表名 drop foreign key 外键名称;
案例:
删除emp表的外键fk_emp_dept_id。
alter table emp drop foreign key fk_emp_dept_id;
删除/更新行为
添加了外键之后,再删除父表数据时产生的约束行为,就称为删除/更新行为。具体的删除/更新行为有以下几种:
行为 | 说明 |
---|---|
NO ACTION | 当在父表删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新。(与RESTRICT一致)默认行为 |
RESTRICT | 当在父表中删除/更新对应记录时,首先检查该记录是否有对象外键,如果有则不允许删除/更新。(与NO ACTION一致)默认行为 |
CASCADE | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在子表中的记录 |
SET NULL | 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(这就要求该外键允许取null) |
SET DEFAULT | 父表有变更时,子表将外键列设置成一个默认值(Innodb不支持) |
具体语法为:
alter table 表名 add constraint 外键名称 foreign key (外键字段) references 主表名(主表字段名) on update cascade on delete cascade;
演示:
CASCADE
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update cascade on delete cascade;