MySQL基础
1.MySQL服务
1.1 MySQL服务的启动和停止
方式一:计算机——右击管理——服务
方式二:通过管理员身份运行
net start 服务名(启动服务)
net stop 服务名(停止服务)
1.2 MySQL服务的登录和退出
登录:mysql 【-h 主机名 -P 端口号】 -u 用户名 -p密码
退出:exit或ctrl+C
2.DQL(Data Query Language)数据查询语言
2.1 基础查询
语法:
SELECT 查询列表 FROM 表名; |
特点:
- 通过select查询完的结果 ,是一个虚拟的表格,不是真实存在
- 要查询的东西 可以是常量值、可以是表达式、可以是字段、可以是函数
2.2 条件查询
语法:
SELECT 查询列表 FROM 表名 WHERE 筛选条件; |
分类:
条件表达式
示例:salary>10000
条件运算符:>、< 、>=、 <=、 = 、!=、 <>逻辑表达式
示例:salary>10000 && salary<20000
逻辑运算符:
- and(&&):两个条件如果同时成立,结果为true,否则为false
- or(||):两个条件只要有一个成立,结果为true,否则为false
- not(!):如果条件成立,则not后为false,否则为true
模糊查询
示例:last_name like ‘a%’
2.3 排序查询
语法:
SELECT 查询列表 FROM 表名 ORDER BY 排序列表 【asc||desc】; |
特点:
asc :升序,如果不写默认升序
desc:降序
排序列表 支持 单个字段、多个字段、函数、表达式、别名
order by的位置一般放在查询语句的最后(除limit语句之外)
2.4 常见函数
语法:
SELECT 函数名(实参列表); |
分类:
单行函数
字符函数
concat:连接
SELECT CONCAT('Hello','_','World');
#结果:Hello_Worldsubstr:截取子串
#注意:索引从1开始
#截取从指定索引处后面所有字符
SELECT SUBSTR('Hello World',7);
#结果:World
#截取从指定索引处指定字符长度的字符
SELECT SUBSTR('Hello World',1,3);
#结果:Helupper:变大写
SELECT UPPER('john');
#结果:JOHNlower:变小写
SELECT LOWER('joHn');
#结果:johnreplace:替换
SELECT REPLACE('Hello World','l','i');
#结果:Heiio Woridlength:获取字节长度
SELECT LENGTH('john');
#结果:4trim:去前后空格
SELECT LENGTH(TRIM(' Hello '));
#结果:5lpad:左填充
SELECT TRIM('l' FROM 'llllllllHellolllll');
#结果:Hellorpad:右填充
SELECT LPAD('john',6,'*');
#结果:**johninstr:获取子串第一次出现的索引
SELECT INSTR('Hello World','o');
#结果:5
数学函数
ceil:向上取整
SELECT CEIL(-1.02);
#结果:-1round:四舍五入
SELECT ROUND(-1.55);
#结果:-2
SELECT ROUND(1.567,2);
#结果:1.57mod:取模
SELECT MOD(10,-3);
#结果:1
SELECT 10%3;
#结果:1floor:向下取整
SELECT FLOOR(-9.99);
#结果:-10truncate:截断
SELECT TRUNCATE(1.69999,1);
#结果:1.6rand:获取随机数,返回0-1之间的小数
SELECT RAND();
#结果:0.2870596892079894
日期函数
now:返回当前日期+时间
SELECT NOW();
#结果:2020-02-10 16:05:07curdate:返回当前日期
SELECT CURDATE();
#结果:2020-02-10curtime:返回当前时间
SELECT CURTIME();
#结果:16:05:07year:返回年
SELECT YEAR(NOW()) 年;
#结果:2020
SELECT YEAR('1998-1-1') 年;
#结果:1998month:返回月
SELECT MONTH(NOW()) 月;
#结果:2monthname:以英文形式返回月
SELECT MONTHNAME(NOW()) 月;
#结果:Februaryday:返回日
SELECT DAY(NOW()) 日;
#结果:10hour:小时
SELECT HOUR(NOW()) 小时;
#结果:16minute:分钟
SELECT MINUTE(NOW()) 分钟;
#结果:6second:秒
SELECT SECOND(NOW()) 秒;
#结果:50date_format:将日期转换成字符
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日');
#结果:20年02月10日str_to_date:将字符转换成日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d');
#结果:1998-03-02datediff:返回两个日期相差的天数
SELECT DATEDIFF('2020-12-30','2020-12-29');
#结果:1
流程控制函数
if(条件表达式,表达式1,表达式2):
如果条件表达式成立,返回表达式1,否则返回表达式2
SELECT IF(10<5,'大','小');
#结果:小case情况1
case 变量或表达式或字段
when 常量1 then 值1
when 常量2 then 值2
...
else 值n
end
#示例
SELECT salary 原始工资,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工资
FROM employees;case情况2
case
when 条件1 then 值1
when 条件2 then 值2
...
else 值n
end
#示例
SELECT salary,
CASE
WHEN salary>20000 THEN 'A'
WHEN salary>15000 THEN 'B'
WHEN salary>10000 THEN 'C'
ELSE 'D'
END AS 工资级别
FROM employees;
其他函数
version:当前数据库服务器的版本
SELECT VERSION();
#结果:5.7.18-logdatabase:当前打开的数据库
SELECT DATABASE();
#结果:joeychatuser:当前用户
SELECT USER();
#结果:root@localhostpassword(‘字符’):返回该字符的密码形式
SELECT PASSWORD('Hello');
#结果:*FCA02337EEB51C3EE398B473FD9A9AFD093F9E64md5(‘字符’):返回该字符的md5加密形式
SELECT MD5('Hello');
#结果:8b1a9953c4611296a827abf8c47804d7
分组函数
函数
sum:求和
SELECT SUM(salary) FROM employees;
max:最大值
SELECT MAX(salary) FROM employees;
min:最小值
SELECT MIN(salary) FROM employees;
avg:平均值
SELECT AVG(salary) FROM employees;
count:计数
SELECT COUNT(salary) FROM employees;
特点
- 以上五个分组函数都忽略
null
值,除了count(*) - sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型
- 可以搭配distinct使用,用于统计去重后的结果
- count的参数可以支持:字段、*、常量值,一般放1
- 效率:
- MYISAM存储引擎下 ,COUNT(*)的效率高
- INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
- 以上五个分组函数都忽略
2.5 分组查询
语法:
SELECT 查询列表 FROM 表名 GROUP BY 分组的字段 HAVING 分组后的筛选 ORDER BY 排序列表; |
特点:
可以按单个字段分组
和分组函数一同查询的字段最好是分组后的字段
分组筛选 针对的表 位置 关键字 分组前筛选 原始表 group by的前面 where 分组后筛选 分组后的结果集 group by的后面 having 可以按多个字段分组,字段之间用逗号隔开
可以支持排序
having后可以支持别名
2.6 连接查询
sql99语法:
SELECT 字段,... |
2.7 子查询
含义:
一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询。
在外面的查询语句,称为主查询或外查询。
特点:
子查询都放在小括号内
子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
子查询优先于主查询执行,主查询使用了子查询的执行结果
子查询根据查询结果的行数不同分为以下两类:
单行子查询
结果集只有一行,一般搭配单行操作符使用:> < = <> >= <=
非法使用子查询的情况:
- 子查询的结果为一组值
- 子查询的结果为空
多行子查询
结果集有多行,一般搭配多行操作符使用:any、all、in、not in
in: 属于子查询结果中的任意一个就行
any和all往往可以用其他查询代替
2.8 分页查询
语法:
SELECT 查询列表 |
特点:
起始条目索引从0开始
limit子句放在查询语句的最后
公式:select * from 表 limit (page-1)*sizePerPage,sizePerPage,
说明:
sizePerPage:每页显示条目数
page:要显示的页数
2.9 联合查询
语法:
SELECT 字段|常量|表达式|函数 FROM 表 WHERE 条件 UNION all |
特点:
- 多条查询语句的查询的列数必须是一致的
- 多条查询语句的查询的列的类型几乎相同
- union代表去重,union all代表不去重
3. DML(Data Manipulate Language)数据操作语言
3.1 插入
语法:
#方式一 |
特点:
- 字段类型和值类型一致或兼容,而且一一对应
- 可以为空的字段,可以不用插入值,或用null填充
- 不可以为空的字段,必须插入值
- 字段个数和值的个数必须一致
- 字段可以省略,但默认所有字段,并且顺序和表中的存储顺序一致
3.2 修改
语法:
#单表更新 |
3.3 删除
语法:
#使用DELETE |
4.DDL(Data Define Language)数据定义语言
4.1 库的管理
创建库
CREATE DATABASE 【IF NOT EXISTS】 库名【 CHARACTER SET 字符集名】
修改库
ALTER DATABASE 库名 CHARACTER SET 字符集名;
删除库
DROP DATABASE 【IF EXISTS】 库名;
4.2 表的管理
创建表
CREATE TABLE IF NOT EXISTS stuinfo(
stuId INT,
stuName VARCHAR(20),
gender CHAR,
bornDate DATETIME
);修改表
语法:
ALTER TABLE 表名 ADD|MODIFY|DROP|CHANGE COLUMN 字段名 【字段类型】;
添加字段
ALTER TABLE 表名 ADD COLUMN 列名 类型 【First|After 字段名】;
修改字段名
ALTER TABLE 表名 CHANGE COLUMN 旧列名 新列名 类型;
修改字段的类型或约束
ALTER TABLE 表名 MODIFY COLUMN 列名 新类型 【新约束】;
删除列
ALTER TABLE 表名 DROP COLUMN 列名;
修改表名
ALTER TABLE 表名 RENAME 【to】 新表名;
删除表
DROP TABLE [IF EXISTS] studentinfo;
复制表
复制表结构
CREATE TABLE 表名 LIKE 旧表;
复制表结构+数据
CREATE TABLE 表名
SELECT 查询列表 FROM 旧表 【WHERE筛选】;
4.3 数据类型
整型
类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 byte (-128,127) (0,255) 小整数值 SMALLINT 2 bytes (-32 768,32 767) (0,65 535) 大整数值 MEDIUMINT 3 bytes (-8 388 608,8 388 607) (0,16 777 215) 大整数值 INT或INTEGER 4 bytes (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值 BIGINT 8 bytes (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值 FLOAT 4 bytes (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值 DOUBLE 8 bytes (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值 DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值 依赖于M和D的值 小数值 浮点型
类型 DECIMAL(M,D) FLOAT DOUBLE 长度 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 4 8 字符型
类型 大小 用途 CHAR 0-255 bytes 定长字符串 VARCHAR 0-65535 bytes 变长字符串 TINYBLOB 0-255 bytes 不超过 255 个字符的二进制字符串 TINYTEXT 0-255 bytes 短文本字符串 BLOB 0-65 535 bytes 二进制形式的长文本数据 TEXT 0-65 535 bytes 长文本数据 MEDIUMBLOB 0-16 777 215 bytes 二进制形式的中等长度文本数据 MEDIUMTEXT 0-16 777 215 bytes 中等长度文本数据 LONGBLOB 0-4 294 967 295 bytes 二进制形式的极大文本数据 LONGTEXT 0-4 294 967 295 bytes 极大文本数据 日期型
类型 大小 ( bytes) 范围 格式 用途 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:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳
4.4 常见的约束
常见约束
- NOT NULL:非空,该字段的值必填
- UNIQUE:唯一,该字段的值不可重复
- DEFAULT:默认,该字段的值不用手动插入有默认值
- CHECK:检查,MYSQL不支持
- PRIMARY KEY:主键,该字段的值不可重复并且非空 NIQUE+NOT NULL
- FOREIGN KEY:外键,该字段的值引用了另外的表的字段
其中,主键和唯一
- 区别:
- 一个表至多有一个主键,但可以有多个唯一
- 主键不允许为空,唯一可以为空
- 相同点
- 都具有唯一性
- 都支持组合键,但不推荐
外键
用于限制两个表的关系,从表的字段值引用了主表的某字段值
外键列和主表的被引用列要求类型一致,意义一样,名称无要求
主表的被引用列要求是一个KEY(一般就是主键)
插入数据,先插入主表
当设置有外键的时候,可以通过一下两种方式实现删除主表的记录:
方式一:级联删除
alter table stuinfo add CONSTRAINT fk_stu_major FOREIGN KEY(majorid) REFERENCES major(id) on DELETE CASCADE;
说明:这样删除主表中的数据的时候,引用他外键的表的数据也都会进行删除,当然这种做法有点残忍,但是在实际的业务中,进行数据维护的时候,确实也有这么干的
方式二:级联置空
alter table stuinfo add CONSTRAINT fk_stu_major FOREIGN KEY(majorid) REFERENCES major(id) on DELETE set null;
说明:这样删除主表中的数据的时候,引用他外键的表的数据不会进行删除,对应的引用外键的那一列会置为空,这种方法比较好。
综上所述,要结合具体的业务场景进行选择。
创建表时添加约束
CREATE TABLE 表名(
字段名 字段类型 NOT NULL,#非空
字段名 字段类型 PRIMARY KEY,#主键
字段名 字段类型 UNIQUE,#唯一
字段名 字段类型 DEFAULT 值,#默认
CONSTRAINT 约束名 FOREIGN KEY(字段名) REFERENCES 主表(被引用列)
)注意:
列级约束可以在一个字段上追加多个,中间用空格隔开,没有顺序要求
对比:
支持类型 可以起约束名 列级约束 除了外键 不可以 表级约束 除了非空和默认 可以,但对主键无效 修改表时添加或删除约束
非空
添加非空
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 NOT NULL;
删除非空
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 ;
默认
添加默认
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 DEFAULT 值;
删除默认
ALTER TABLE 表名 MODIFY COLUMN 字段名 字段类型 ;
主键
添加主键
ALTER TABLE 表名 ADD【 CONSTRAINT 约束名】 PRIMARY KEY(字段名);
删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;
唯一
添加唯一
ALTER TABLE 表名 ADD【 CONSTRAINT 约束名】 UNIQUE(字段名);
删除唯一
ALTER TABLE 表名 DROP INDEX 索引名;
外键
添加外键
ALTER TABLE 表名 ADD【 CONSTRAINT 约束名】 FOREIGN KEY(字段名) REFERENCES 主表(被引用列);
删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 约束名;
自增长列
特点:
不用手动插入值,可以自动提供序列值,默认从1开始,步长为1
AUTO_INCREMENT_INCREMENT
如果要更改起始值:手动插入值
如果要更改步长:更改系统变量 SET AUTO_INCREMENT_INCREMENT=值;
一个表至多有一个自增长列
自增长列只能支持数值型
自增长列必须为一个KEY
创建表时设置自增长列
CREATE TABLE 表(
字段名 字段类型 约束 AUTO_INCREMENT
)修改表时设置自增长列
ALTER TABLE 表 MODIFY COLUMN 字段名 字段类型 约束 AUTO_INCREMENT
删除自增长列
ALTER TABLE 表 MODIFY COLUMN 字段名 字段类型 约束
5.TCL(Transaction Control Language)事务控制语言
5.1含义
事务:
一条或多条sql语句组成一个执行单位,一组sql语句要么都执行要么都不执行
5.2 特点(ACID)
- A 原子性:一个事务是不可再分割的整体,要么都执行要么都不执行
- C 一致性:一个事务可以使数据从一个一致状态切换到另外一个一致的状态
- I 隔离性:一个事务不受其他事务的干扰,多个事务互相隔离的
- D 持久性:一个事务一旦提交了,则永久的持久化到本地
5.3 使用步骤
了解:
隐式(自动)事务:没有明显的开启和结束,本身就是一条事务可以自动提交,比如insert、update、delete
显式事务:具有明显的开启和结束
使用显式事务:
①开启事务
set autocommit=0;
start transaction;#可以省略
②编写一组逻辑sql语句
注意:sql语句支持的是insert、update、delete
设置回滚点:
savepoint 回滚点名;
③结束事务
提交:commit;
回滚:rollback;
回滚到指定的地方:rollback to 回滚点名;
5.4 并发事务
事务的并发问题是如何发生的?
多个事务同时操作 同一个数据库的相同数据时并发问题都有哪些?
脏读:一个事务读取了其他事务还没有提交的数据,读到的是其他事务“更新”的数据
不可重复读:一个事务多次读取,结果不一样
幻读:一个事务读取了其他事务还没有提交的数据,只是读到的是 其他事务“插入”的数据如何解决并发问题
通过设置隔离级别来解决并发问题隔离级别
脏读 不可重复读 幻读 READ UNCOMMITTED:读未提交 × × × READ COMMITTED:读已提交 √ × × REPEATABLE READ:可重复读 √ √ × SERIALIZABLE:串行化 √ √ √ 设置和查看隔离级别
设置隔离级别
set session|global transaction isolation level 隔离级别名;
查看隔离级别
select @@tx_isolation;
6.其他
6.1 视图
含义:
mysql5.1版本出现的新特性,本身是一个虚拟表,它的数据来自于表,通过执行时动态生成。
好处:
- 简化sql语句
- 提高了sql的重用性
- 保护基表的数据,提高了安全性
语法
创建
create view 视图名
as
查询语句;修改
方式一
create or replace view 视图名
as
查询语句;方式二
alter view 视图名
as
查询语句;
删除
drop view 视图1,视图2,...;
查看
desc 视图名;
show create view 视图名;使用
1.插入
insert
2.修改
update
3.删除
delete
4.查看
select注意
视图一般用于查询的,而不是更新的,所以具备以下特点的视图都不允许更新
①包含分组函数、group by、distinct、having、union、
②join
③常量视图
④where后的子查询用到了from中的表
⑤用到了不可更新的视图视图和表的对比
关键字 是否占用物理空间 使用 视图 view 占用较小,只保存sql逻辑 一般用于查询 表 table 保存实际的数据 增删改查
6.2 变量
系统变量
说明:变量由系统提供的,不用自定义。
全局变量
服务器层面上的,必须拥有super权限才能为系统变量赋值,作用域为整个服务器,也就是针对于所有连接(会话)有效
会话变量
服务器为每一个连接的客户端都提供了系统变量,作用域为当前的连接(会话)
语法:
查看系统变量
#如果没有显式声明global还是session,则默认是session
show 【global|session 】variables like '';查看指定的系统变量的值
#如果没有显式声明global还是session,则默认是session
select @@【global|session】.变量名;为系统变量赋值
方式一
#如果没有显式声明global还是session,则默认是session
set 【global|session 】 变量名=值;方式二
set @@global.变量名=值;
set @@变量名=值;
自定义变量
用户变量
作用域:针对于当前连接(会话)生效
位置:begin end里面,也可以放在外面
使用:
声明并赋值
set @变量名=值;或
set @变量名:=值;或
select @变量名:=值;更新值
set @变量名=值;或
set @变量名:=值;或
select @变量名:=值;
select xx into @变量名 from 表;使用
select @变量名;
局部变量
作用域:仅仅在定义它的begin end中有效
位置:只能放在begin end中,而且只能放在第一句
使用:
声明
declare 变量名 类型 【default 值】;
赋值或更新
set 变量名=值;或
set 变量名:=值;或
select @变量名:=值;
select xx into 变量名 from 表;使用
select 变量名;
6.3 存储过程
创建
create procedure 存储过程名(参数模式 参数名 参数类型)
begin
存储过程体
end注意:
1.参数模式:in、out、inout,其中in可以省略
2.存储过程体的每一条sql语句都需要用分号结尾
调用
call 存储过程名(实参列表)
#举例:
#调用in模式的参数:call sp1(‘值’);
#调用out模式的参数:set @name; call sp1(@name);select @name;
#调用inout模式的参数:set @name=值; call sp1(@name); select @name;查看
show create procedure 存储过程名;
删除
drop procedure 存储过程名;
6.4 函数
创建
create function 函数名(参数名 参数类型) returns 返回类型
begin
函数体
end注意:函数体中肯定需要有return语句
调用
select 函数名(实参列表);
查看
show create function 函数名;
删除
drop function 函数名;
6.5 流程控制结构
6.5.1 分支结构
IF函数
功能:实现简单双分支
语法:
if(条件,值1,值2)
位置:可以作为表达式放在任何位置
CASE结构
功能:实现多分支
语法:
#第一种
case 表达式或字段
when 值1 then 语句1;
when 值2 then 语句2;
..
else 语句n;
end [case];
#第二种
case
when 条件1 then 语句1;
when 条件2 then 语句2;
..
else 语句n;
end [case];IF结构
功能:实现多分支
语法:
if 条件1 then 语句1;
elseif 条件2 then 语句2;
...
else 语句n;
end if;位置:只能放在begin end中
6.5.2 循环结构
WHILE
语法:
【名称:】while 循环条件 do
循环体
end while 【名称】;LOOP
语法:
【名称:】loop
循环体
end loop 【名称】;REPEAT
语法:
【名称:】repeat
循环体
until 结束条件
end repeat 【名称】;对比
这三种循环都可以省略名称,但如果循环中添加了循环控制语句(leave或iterate)则必须添加名称
- leave:类似于break,用于跳出所在的循环
- iterate:类似于continue,用于结束本次循环,继续下一次
loop 一般用于实现简单的死循环
while 先判断后执行
repeat 先执行后判断,无条件至少执行一次