5 MySql
- 一、简介
- 二、SQL语言
- 2.1 导入外部SQL文件
- 2.2 显示表结构
- 2.3 与创建数据库相关的语句
- 2.4 与表相关的语句
- 2.5 操作表中的数据
- 2.6 7种基本的sql查询
- 三、SQL的注意点
- 3.1 与集合函数相关
- 3.2 SQL语句的书写与执行过程
- 四、约束 constraint
- 4.1 作用
- 4.2 功能分类
- 4.3 自增
- 五、视图
- 5.1 基本概念
- 5.2 优缺点
- 六、变量
- 6.1 系统变量
- 6.1.1 全局系统变量
- 6.1.2 会话系统变量
- 6.2 用户自定义变量
- 6.2.1 会话用户变量
- 6.2.2 局部变量
- 七、函数
- 7.1 语法格式
- 7.2 调用
- 八、存储过程
- 8.1 简介
- 8.2 语法格式
- 8.3 调用
- 8.4 对比
- 8.4.1 与视图的对比
- 8.4.2 与函数的对比
- 九、触发器
- 9.1 简介
- 9.2 语法格式
- 9.3 优缺点
- 十、流程控制
- 10.1 顺序结构
- 10.2 分支结构
- 10.2.1 if结构
- 10.2.2 CASE结构
- 10.3 循坏结构
- 10.3.1 loop循环
- 10.3.2 while循环
- 10.3.3 repeat循环
- 10.3.4 跳转语句
- 十一、游标
- 11.1 简介
- 11.2 使用
- 11.3 优缺点
- 十二、异常
- 12.1 定义
- 12.2 使用
一、简介
MySQL是一种开源的关系型数据库管理系统,是最流行和广泛使用的数据库之一
具有以下优点:
- 可靠性和稳定性:MySQL经过了长时间的发展和测试,被广泛用于各种规模和需求的应用程序。它被证明是一个可靠且稳定的数据库解决方案。
- 容易使用:MySQL具有直观的用户界面和易于理解的语法,使得开发人员和管理员能够轻松地使用和管理数据库。
- 多种编程语言支持:MySQL支持众多的编程语言,包括但不限于Java、Python、PHP等。这使得开发人员可以在自己熟悉的编程环境中轻松地连接和操作MySQL数据库。
- 高性能:MySQL以其高效的性能而闻名。它可以处理大量的并发请求,具有出色的读写性能和响应时间。
- 扩展性:MySQL支持水平和垂直扩展,可以根据需要增加服务器的处理能力,以适应不断增长的数据和用户负载。
- 安全性:MySQL提供了各种安全功能和机制,包括用户认证、权限管理和数据加密等,以确保数据的安全性和保密性。
- 社区支持和活跃的开发:MySQL有一个庞大的用户社区和开发者社区,提供了丰富的资源、文档和支持。它不断进行更新和改进,以适应不断变化的需求和技术。
二、SQL语言
2.1 导入外部SQL文件
关键字:source
source /zpyl/ywams.sql
2.2 显示表结构
关键字:desc
desc student
2.3 与创建数据库相关的语句
# 创建数据库
CREATE DATABASE IF NOT EXISTS my_student;
# 查看创建数据库的细节
SHOW CREATE DATABASE my_student;
#使用数据库
use my_student;
# 修改数据库字符集
ALTER DATABASE my_student CHARACTER SET 'gbk';
# 查看数据库中的表
SHOW tables;
# 删除数据库
DROP DATABASE my_student;
2.4 与表相关的语句
# 新建表
CREATE TABLE student(
id INTEGER,
`name` VARCHAR(20)
)
# 向表中添加字段
ALTER TABLE student ADD sex CHAR(1);
# 向表中修改字段N
ALTER TABLE student MODIFY sex CHAR(4);
# 重命名字段
ALTER TABLE student CHANGE sex age INTEGER;
# 向表中删除字段
ALTER TABLE student DROP age;
# 重命名表
RENAME TABLE student to stu;
# 在现有的表上创建新表
CREATE TABLE student AS
SELECT * FROM stu;
# 清空表
TRUNCATE TABLE stu;
# 删除表
DROP TABLE stu;
# 查看表信息
DESC student;
2.5 操作表中的数据
# 添加数据
INSERT INTO student(id,`name`) VALUE (1,2);
# 修改数据
UPDATE student set `name`=5 where id=4;
# 删除数据
DELETE FROM student where id=4;
2.6 7种基本的sql查询
三、SQL的注意点
3.1 与集合函数相关
- 聚合函数count,sum,avg等等在计算时会自动忽略字段中为null的值,在一些情况下可能会使计算结果不正确
- select中出现的非聚合函数的字段必须声明在group by中
- having和where的使用区别
- having的适用范围更广,having中的过滤条件不仅仅可以是非聚合函数,还可以是聚合函数的,而where中只能出现非聚合函数的过滤条件
- 当过滤条件为非聚合函数时,优先使用where,因为这样会提高SQL的执行效率
3.2 SQL语句的书写与执行过程
-
书写规范
-
执行过程
四、约束 constraint
4.1 作用
保证数据的完整性
- 实体完整性约束
- 域完整性约束
- 引用完整性约束
- 用户自定义完整性约束
4.2 功能分类
- not null:非空约束,不允许出现null
- unique:唯一约束,可以多次添加null
- primary key:逐渐约束,非空且唯一
- foreign key:外键约束
- check:检查约束,检查某个字段是否符合XX要求,注意MySQL5,7不支持,MySQL8支持
- default:默认值约束
4.3 自增
自增列 AUTO_INCREMENT
注意:
在MySQL5.7的时候,添加数据时的自增值是放在内存中的,重启服务后,会检查表中的自增的值,从最大的往后累加,而在MySQL8中,自增值是放在日志中的,不会检查表中的最大值
例如:
先添加俩条记录,此时自增值为1和2,在删除一条记录,之后在添加一条记录,此时自增值为3,在删除一条记录,重启服务,在MySQL5.7中在向里面添加记录,此时的自增值为2,在MySQL8中向里面添加记录,此时的自增值为4
五、视图
5.1 基本概念
视图是一种虚表,它是基于基本表创建出来的,本身不存储数据,对视图的创建和删除不会影响基本表中的数据,但对视图中的数据进行crud会相应的修改基本表
# 创建视图
CREATE VIEW stu(id,`name`) AS
SELECT * from student
注意:crud的操作和基本表一样,但注意对于视图并不是所有的crud都被允许
5.2 优缺点
优点:
- 操作简单
- 减少冗余代码
- 数据安全
- 适应灵活多变的需求,能够分解复杂的查询逻辑
缺点: - 由于视图是依赖基本表的,如果基本表的结构变更了,会让视图的维护变得很麻烦
六、变量
6.1 系统变量
6.1.1 全局系统变量
- 查询全局系统变量:SHOW GLOBAL VARIABLES;
- 查询指定的全局系统变量:SELECT @@global.max_connections
- 修改全局系统变量的值:SET @@global.max_connections =161
6.1.2 会话系统变量
- 查询会话系统变量:SHOW SESSION VARIABLES;
- 查询指定的会话系统变量:SELECT @@session.character_set_client
- 修改会话系统变量的值:SET SESSION character_set_client=‘gbk’
注意:
SELECT @@character_set_client:不指定是global还是session时,先查询会话系统变量,再查询全局系统变量
6.2 用户自定义变量
6.2.1 会话用户变量
- 以@ 开头,作用域为当前会话
- 声明 set @ 用户变量 = 值:SET @Test = ‘1’
- 使用 select @ 用户变量:SELECT @Test
6.2.2 局部变量
只能在存储过程和存储函数中使用并且需要指定类型
使用条件:
- 使用declare声明,并且必须放在begin中首行的位置上
- 声明并使用在begin … end 中
七、函数
7.1 语法格式
CREATE FUNCTION function_name (parameter1 data_type)
RETURNS return_type
[DETERMINISTIC | NOT DETERMINISTIC]
[CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA]
[COMMENT 'string']
[DETERMINISTIC | NO SQL | READS SQL DATA | MODIFIES SQL DATA]
BEGIN
-- 函数体代码
-- 可以包含多个语句或复杂的逻辑
RETURN expression;
END
- function_name:函数的名称,用于在调用函数时引用它。
- parameter1 data_type:函数的参数列表,每个参数由参数名和数据类型组成。可以有多个参数,如果没有参数则留空。需要注意的是在函数中总是默认为IN参数,其他参数类型只对存储过程适用
- RETURNS return_type:函数的返回类型,用于指定函数返回的结果的数据类型,在存储函数中必须带有返回值
- DETERMINISTIC | NOT DETERMINISTIC:函数的特性选项,用于指定函数的确定性。
- [CONTAINS SQL| NO SQL | READS SQL DATA | MODIFIES SQL DATA]:函数的SQL访问类型,用于指定函数对数据库的访问方式。
- COMMENT ‘string’:可选项,用于给函数添加注释。
- [DETERMINISTIC | NO SQL | READS SQL DATA | MODIFIES SQL DATA]:可选项,用于指定函数的语言。
- BEGIN … END:可选项,包含函数体的起始和结束标记。函数体包含函数的实际代码,可以是一段复杂的逻辑、多个语句和返回表达式。
CREATE FUNCTION add_name ( aa INT )
RETURNS VARCHAR ( 255 )
DETERMINISTIC
COMMENT '累加的函数'
CONTAINS SQL
NO SQL
BEGIN
RETURN ( SELECT `name` FROM my_student.student WHERE id = aa );
END
注意:如果有you might want to use the less safe log_bin_trust_function_creators variable异常,则添加SET GLOBAL log_bin_trust_function_creators = 1;
7.2 调用
select
set @dept =1 ;
select add_name(@dept);
八、存储过程
8.1 简介
含义:一组对经过预先编译的SQL语句的封装
执行过程:存储过程存储在MySQL服务器上,需要执行的时候向服务器发出调用命令即可
优点:
- 简化操作,提高SQL语句的重用性,减少了开发程序员的压力
- 减少了网络的传输量
- 减少了SQL语句暴露在网上的风险,提高了数据查询的安全性
8.2 语法格式
IN:表示参数为输入参数
OUT:表示参数为输出参数
INTO:表示参数既可以为输入又可以为输出
CREATE PROCEDURE procedure_name (parameter1 data_type)
BEGIN
-- 存储过程的具体代码
-- 可以包含多个语句或复杂的逻辑
END;
DELIMITER 标记新的结束标志
delimiter $
CREATE PROCEDURE getName(IN aa INT,OUT bb INT)
BEGIN
SELECT `name` INTO bb
FROM my_student.student where id=aa;
END $
delimiter ;
8.3 调用
CALL getName(3,@abc);
select @abc;
8.4 对比
8.4.1 与视图的对比
和视图一样有简单、清晰、安全的优点,但是视图是虚拟表,一般情况下是不能对基本表进行操作的,而存储过程是程序化的SQL,可以直接操作数据库
8.4.2 与函数的对比
存储函数可以放在查询语句中,而存储过程则不可以
九、触发器
9.1 简介
含义:触发器是和存储过程一样,是保存在服务器上的一段程序,触发器的执行是由事件来触发的,这些事件包括insert,update,delete事件
9.2 语法格式
CREATE TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF} {INSERT | UPDATE | DELETE}
ON table_name
[FOR EACH ROW]
[WHEN (condition)]
BEGIN
-- 触发器的具体代码
END;
- trigger_name:触发器的名称,用于在需要引用触发器时使用
- BEFORE | AFTER | INSTEAD OF:指定触发器是在被触发的操作之前还是之后执行
- INSERT | UPDATE | DELETE:指定触发器是在插入、更新还是删除操作时触发
- table_name:触发器所属的表名
- FOR EACH ROW:表示触发器是针对每一行的操作还是整个操作。如果不指定该子句,默认为针对每一行操作。
- WHEN (condition):触发器触发的条件,当条件满足时触发器才会执行。如果不指定条件,则触发器在每次被触发的操作时都会执行
CREATE TRIGGER insert_job
BEFORE INSERT ON student
FOR EACH ROW
BEGIN
INSERT INTO job (id,`name`,bz)
VALUES(NEW.id,NEW.`name`,'新增');
END
解释:创建触发器,向student中加入数据的同时向job中也添加数据,NEW是获取添加到job中的数据
CREATE TRIGGER delete_job
BEFORE DELETE ON student
FOR EACH ROW
BEGIN
INSERT INTO job (id,`name`,bz)
VALUES(OLD.id,OLD.`name`,'删除');
END
解释:创建触发器,从student中删除数据的同时,向job中保存被删除的数据,OLD是获取被删除的数据
9.3 优缺点
优点:
- 确保数据的完整性
- 帮助我们记录日志
- 用在操作数据前,对数据的合法性进行检查
缺点: - 可读性差
- 数据的变更可能导致触发器出错,而相关的SQL排错起来难度大
十、流程控制
10.1 顺序结构
程序从上往下依次执行
10.2 分支结构
10.2.1 if结构
声明存储过程,输入员工的编号,判断如果员工的薪资低于800,且入职时间超过5年,则涨薪500
判断如果员工的薪资低于800,且入职时间超过8年,则涨薪1000,其他涨薪100
并做好记录,记录为原来的工资,涨薪后的工资和时间
delimiter $
CREATE PROCEDURE updateEmploryee(IN emploryId INT)
BEGIN
# 保存当前员工的薪资
DECLARE oldSalary DOUBLE;
# 保存当前员工的年份
DECLARE yearOld DOUBLE;
# 查询员工的薪资 不能合并,一次只能保存一个变量
SELECT salary INTO oldSalary FROM emploryee where id=emploryId;
# 查询员工的工作年限
SELECT hireTime INTO yearOld FROM emploryee where id=emploryId;
IF oldSalary < 800 and yearOld>8
THEN
UPDATE emploryee SET salary=salary+1000 WHERE id=emploryId;
INSERT INTO job (id,oldSalary,newSalary,newTime,bz)
VALUES (emploryId,oldSalary,oldSalary+1000,now(),"涨薪1000");
ELSEIF oldSalary < 800 and yearOld>5
THEN
UPDATE emploryee SET salary=salary+500 WHERE id=emploryId;
INSERT INTO job (id,oldSalary,newSalary,newTime,bz)
VALUES (emploryId,oldSalary,oldSalary+500,now(),"涨薪500");
ELSE
UPDATE emploryee SET salary=salary+100 WHERE id=emploryId;
INSERT INTO job (id,oldSalary,newSalary,newTime,bz)
VALUES (emploryId,oldSalary,oldSalary+100,now(),"涨薪100");
END IF;
END $
delimiter ;
10.2.2 CASE结构
- 类似switch结构
输入1:显示优秀 输入2:显示一般 输入3:显示差 其他:显示输入本身
delimiter $
CREATE PROCEDURE switch(IN num INT)
BEGIN
CASE num
WHEN 1 THEN SELECT '优秀';
WHEN 2 THEN SELECT '一般';
WHEN 3 THEN SELECT '差';
ELSE
SELECT num;
END CASE;
END $
delimiter ;
- 类似多重if
输入1:显示优秀 输入2~6:显示一般 输入7~9:显示差 其他:显示输入本身
delimiter $
CREATE PROCEDURE enif(IN num INT)
BEGIN
CASE
WHEN num = 1 THEN SELECT '优秀';
WHEN 2 <= num AND num <= 6 THEN SELECT '一般';
WHEN 7 <= num AND num <= 9 THEN SELECT '差';
ELSE
SELECT num;
END CASE;
END $
delimiter ;
10.3 循坏结构
10.3.1 loop循环
是由标签、循环体、循坏条件、退出循环语句组成
delimiter $
CREATE PROCEDURE testLoop ( IN loopTime INT ) BEGIN
DECLARE id INT DEFAULT ( 0 );
DECLARE sum INT DEFAULT ( 0 );
looploop : # 标签
LOOP
# 循环体
SET id = id + 1;
SET sum = sum + id;
IF id >= loopTime # 循环条件
THEN SELECT '总数为:' + sum;
LEAVE looploop; # 退出循环
END IF;
END LOOP looploop;
END $
delimiter ;
10.3.2 while循环
先判断后执行
delimiter $
CREATE PROCEDURE testWhile(IN whileTime INT)
BEGIN
DECLARE id INT DEFAULT(0);
DECLARE sum INT DEFAULT(0);
WHILE id < whileTime DO
SET id = id + 1;
SET sum = sum + id;
END WHILE;
SELECT sum;
END $
delimiter ;
10.3.3 repeat循环
先执行后判断
delimiter $
CREATE PROCEDURE testRepeat(IN repearTime INT)
BEGIN
DECLARE id INT DEFAULT(0);
DECLARE sum INT DEFAULT(0);
REPEAT
SET id = id + 1;
SET sum = sum + id;
UNTIL id>= repearTime
END REPEAT;
SELECT sum;
END $
delimiter ;
10.3.4 跳转语句
- leave:表示跳出循环或者跳出程序体
- iterate:跳出当前循环执行下一次循环
十一、游标
11.1 简介
- 提供了对结果集中的记录进行操作的方式
- 游标是一种临时的数据库对象,可以对存储在数据库中的表,表中的数据进行行指针,一般应用在存储过程和函数中
11.2 使用
- 声明一个游标对象:首先需要声明一个游标变量,指定查询结果集和游标属性。
DECLARE cursor_name CURSOR FOR SELECT column1, column2 FROM table_name;
cursor_name
是游标的名称,column1
和 column2
是要查询的列,table_name
是要查询的表名。
2. 打开游标:打开游标以便开始访问结果集。
OPEN cursor_name;
- 声明和操作游标的变量:你可以声明一个或多个用于存储结果集中某一行数据的变量,并使用
FETCH
语句将数据从游标中读取到这些变量中。DECLARE variable1 datatype; DECLARE variable2 datatype; ... FETCH cursor_name INTO variable1, variable2;
variable1
和 variable2
是变量,datatype
是相应列的数据类型。
4. 处理当前行的数据:使用游标变量中的数据执行各种操作。完成后,可以使用 FETCH
语句获取下一行数据。
WHILE (condition) DO
-- 处理当前行的数据
FETCH cursor_name INTO variable1, variable2;
END WHILE;
condition
是循环条件,可以根据需求定义。
5. 关闭游标和释放资源:因为游标会占用系统资源,完成对结果集的处理后,应该关闭游标,并释放相关资源。
CLOSE cursor_name;
DEALLOCATE PREPARE cursor_name;
CLOSE
语句用于关闭游标,DEALLOCATE PREPARE
语句用于释放游标所占用的内存。
注意:游标只能在存储过程或函数中使用。此外,游标应该避免过度使用,因为它们可能会对性能产生负面影响。只有在必要时才使用游标,并且要优化查询以最大限度地减少数据访问量。
delimiter $
CREATE PROCEDURE testCursor()
BEGIN
DECLARE emId INT DEFAULT(0);
DECLARE emName VARCHAR(255);
DECLARE employSalary DOUBLE(8,2);
DECLARE repeatTime int DEFAULT(0);
# 1. 声明一个游标对象:首先需要声明一个游标变量,指定查询结果集和游标属性。
DECLARE employ CURSOR FOR SELECT id,employName,salary FROM emploryee;
# 2. 打开游标:打开游标以便开始访问结果集。
OPEN employ;
# 3. 声明和操作游标的变量:你可以声明一个或多个用于存储结果集中某一行数据的变量,并使用 `FETCH` 语句将数据从游标中读取到这些变量中。
REPEAT
FETCH employ INTO emId,emName,employSalary; # 游标的查询结果集中的字段数,必须跟INTO后面的变量数保持一致
SET repeatTime = repeatTime+1;
# 4. 处理当前行的数据:使用游标变量中的数据执行各种操作。完成后,可以使用 `FETCH` 语句获取下一行数据。
SELECT emId,emName,employSalary;
UNTIL repeatTime=5
END REPEAT;
# 5. 关闭游标和释放资源:因为游标会占用系统资源,完成对结果集的处理后,应该关闭游标,并释放相关资源。
CLOSE employ;
END $
delimiter ;
11.3 优缺点
优点:
为逐条获取结果集的数据提供了解决方案,在跟应用层实现相同的功能时,游标可以在存储程序中使用,效率高,程序也更加简洁
缺点:
在使用游标的过程中,会对数据进行加锁,在业务并发量大的时候,不仅会影响业务之间的效率,还会消耗系统资源,造成内存不足
十二、异常
12.1 定义
在 MySQL 中,异常是指在执行数据库操作过程中出现的错误或异常情况。当某个操作无法完成或遇到错误时,MySQL 可以抛出异常,以便应用程序能够捕获并处理这些异常情况。
MySQL 中的异常可以分为两类:预定义异常和自定义异常。
- 预定义异常:MySQL 提供了一些内置的异常,可以在特定情况下抛出。常见的预定义异常包括:
- SQLEXCEPTION:表示通用的 SQL 异常。
- SQLWARNING:表示 SQL 的警告异常。
- NOT FOUND:表示未找到指定的记录或结果集。
- DUP_KEY:表示违反唯一性约束的异常。
当某个操作引发这些异常时,MySQL 将自动抛出相应的异常,并将其传递给应用程序,应用程序可以通过异常处理机制来捕获和处理这些异常。
- 自定义异常:除了预定义异常,MySQL 也允许用户定义自己的异常。你可以使用
SIGNAL
语句来显式地抛出一个自定义异常。语法如下:
在这里,SIGNAL SQLSTATE 'state' SET MESSAGE_TEXT = 'message';
state
是一个自定义的 SQL 状态码,用于标识异常类型,message
是异常的描述信息。通过抛出自定义异常,你可以更好地控制和处理特定的异常情况。
注意:使用在存储过程或存储函数中
12.2 使用
MySQL_error_code
:数值类型错误代码sqlstate_value
:长度为5的字符串类型错误代码
- 自定义异常
delimiter $
CREATE PROCEDURE definitionCondition()
BEGIN
# SIGNAL 显示的抛出一个异常 SQLSTATE:错误代码 MESSAGE_TEXT:描述
SIGNAL SQLSTATE '10086' SET MESSAGE_TEXT = 'sql error';
SET @x=1;
INSERT INTO emploryee(id,salary) VALUES(NULL,NULL);
SET @x=2;
INSERT INTO emploryee(id,salary) VALUES(NULL,NULL);
SET @x=3;
END $
delimiter ;
CALL definitionCondition;
select @x; # 1
调用:
- 处理程序
定义了遇到问题时应采取的处理方式
语法
DECLARE 处理方式 HANDLER FOR 错误类型 处理语句
- 处理方式:
- continue:遇到错误不处理,继续执行
- exit:遇到错误马上退出
- undo:遇到错误后撤回到之前的操作,注意这个MySQL不支持
- 错误类型:
- SQLSTATE ‘字符串错误码’:表示长度为5的sqlstate_value类型的错误代码
- MySQL_error_code:匹配数值类型错误代码
- SQLWARNING:匹配所有以01开头的SQLSTATE错误代码
- NOT FOUND:匹配所有以02开头的SQLSTATE错误代码
- SQLEXCEPTION:所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码
- 处理语句:
- 可以是简单的set xxx=xx的简单语句,也可以是begin…end编写的复合语句
delimiter $
CREATE PROCEDURE processorCondition()
BEGIN
# 捕获的异常
DECLARE CONTINUE HANDLER FOR 1048 SET @xx =4;
SET @x=1;
INSERT INTO emploryee(id,salary) VALUES(NULL,NULL);
SET @x=2;
INSERT INTO emploryee(id,salary) VALUES(NULL,NULL);
SET @x=3;
END $
delimiter ;
CALL processorCondition;
select @xx; # 4
select @x; # 3
注意:使用在存储过程或存储函数中