From 46e1bc99c91a9dff426045a4c51f0fe09daad3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E6=99=9F=E8=BE=89?= <11764051+strange-nianqian@user.noreply.gitee.com> Date: Wed, 25 Oct 2023 15:13:12 +0000 Subject: [PATCH 1/2] 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 林晟辉 <11764051+strange-nianqian@user.noreply.gitee.com> --- .../20231024 \346\200\273\347\273\223.md" | 444 ++++++++++++++++++ 1 file changed, 444 insertions(+) create mode 100644 "06 \346\236\227\346\231\237\350\276\211/20231024 \346\200\273\347\273\223.md" diff --git "a/06 \346\236\227\346\231\237\350\276\211/20231024 \346\200\273\347\273\223.md" "b/06 \346\236\227\346\231\237\350\276\211/20231024 \346\200\273\347\273\223.md" new file mode 100644 index 0000000..302e022 --- /dev/null +++ "b/06 \346\236\227\346\231\237\350\276\211/20231024 \346\200\273\347\273\223.md" @@ -0,0 +1,444 @@ +## 表与表之间的关系 + +1. ​ 一对一的关系 将其中任一表中的主键,放到另一个表当主键 +2. ​ 一对多的关系 将一所在的表的主键放到多的表当外键 +3. ​ 多对多的关系 必须第三张表,将前面两个表的主键放进来当外键 + +## 数据库的三大范式: + +1. 第一范式:第一范式就是每个属性,也就是字段要求不可再分割,也就要求有原子性 + +2. 第二范式:在满足第一范式的基础上,要求非组件字段要完全依赖组件字段,有联合组件时,非组件要同时完成依赖这两个组件,而不能部分依赖 唯一性。 +3. 第三范式: 独立性 消除传递依赖非组件值不依赖于另一个非组件值。简单的说,就是确保每列都和主键列直接相关,而不是间接相关 + +## 数据库三大模型 + +1. 概念模型cdm 人的角度 + +2. 逻辑模型Ldm 计算机的角度 + +3. 物理模型pdm 从具体的数据库角度 + + +## RBAC的概念 + +RBAC即基于角色的访问控制,是一种流行的访问控制模型,它通过将用户分配到不同的角色,从而赋予用户相应的权限,保证了系统的安全性和完整性。RBAC模型的核心是角色,而不是用户,角色扮演者可以是用户、组织机构、应用程序等,而权限则是分配给角色,而非用户 + +## 函数 + +### 字符串函数 + +CONCAT(S1,Sn) 字符串拼接,将S1,S2,... Sn拼接成一个字符串 + +LOWER(str) 将字符串转为小写 + +UPPER(str) 将字符串转为大写 + +LPAD(str,n,pad) 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 + +RPAD(str,n,pad) 右填充,用字符串pad对str的右边进行填充,达到n个字符串长度 + +TRIM(str) 去掉字符串头部和尾部的空格 + +SUBSTRING(str,start,len) 返回从字符串str从start位置起的len个长度的字符串 + +### 数值函数 + +CEIL(x) 向上取整 + +FLOOR(x) 向下取整 + +MOD(x,y) 整除 + +RAND() 返回0~1的随机数 + +ROUND(x,y) 求参数x的四舍五入的值,保留y位小数 + +### 日期函数 + +CURDATE() 返回当前日期 + +CURTIME() 返回当前时间 + +NOW() 返回当前日期和时间 + +YEAR(date) 获取指定的年份 + +MONTH(date) 获取指定的月份 + +DAY(date) 获取指定的日期 + +DATEDIFF(a,b) 返回a-b的天数 +timestampdiff(返回日期类型,日期1,日期2); 后面的日期减前面的日期,返回日期类型:year:年,month:月,day:日 + +### 流程函数 + +IF(条件, 执行内容1 , 执行内容2) + +IFNULL(字段, 替换内容) + +CASE WHEN [ 数据] THEN [执行内容1] ELSE [ 执行内容2 ] END + +CASE [ 数据] WHEN [ 数值1] THEN [执行内容1] ELSE [ 执行内容2] END + +## 视图 + +视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。 + +```mysql +-- 创建视图 +create or replace view stu_v_1 as select id,name from student where id <= 10; +-- 查询视图 +show create view stu_v_1; +select * from stu_v_1; +-- 修改视图 +alter view stu_v_1 as select id,name from student where id <= 10; +-- 删除视图 +drop view if exists stu_v_1; +``` + +## 存储过程 + + +存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。 + +```mysql +-- 创建存储过程 +CREATE PROCEDURE 存储过程名称 () -- out输出in输入inout输入且输出 +BEGIN +-- SQL语句 +END ; +-- 调用存储过程 +CALL 名称 ([ 参数 ]); + +-- 查看存储过程 + SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'xxx'; -- 查询指定数据库的存储过程及状态信息 +SHOW CREATE PROCEDURE 存储过程名称 ; -- 查询某个存储过程的定义 + +-- 删除存储过程 + DROP PROCEDURE [ IF EXISTS ] 存储过程名称; + + -- 修改定界符 + delimiter // + +``` + +## 变量 + +在MySQL中变量分为三种类型: 系统变量、用户定义变量、局部变量。 + +```mysql +-- 查看系统变量 +SHOW [ SESSION | GLOBAL ] VARIABLES ; -- 查看所有系统变量 +SHOW [ SESSION | GLOBAL ] VARIABLES LIKE '......'; -- 可以通过LIKE模糊匹配方式查找变量 + +SELECT @@[SESSION | GLOBAL] 系统变量名; -- 查看指定变量的值 + +全局变量(GLOBAL): 全局变量针对于所有的会话。 +会话变量(SESSION): 会话变量针对于单个会话,在另外一个会话窗口就不生效了。 + +-- 局部变量 +DECLARE 变量名 变量类型 [DEFAULT ... ] ; +-- 赋值 +SET 变量名 = 值 ; +SET 变量名 := 值 ; +SELECT 字段名 INTO 变量名 FROM 表名 ... ; +``` + +## 条件判断 + +```mysql +-- if判断 +IF 条件1 THEN (执行语句) +ELSEIF 条件2 THEN (执行语句) +ELSE (执行语句) +END IF; +-- 在if条件判断中,ELSEIF 结构可以有多个,也可以没有。 ELSE也一样。 + +-- CASE判断 +-- 语法 +CASE 条件名 +WHEN 条件值 THEN 执行语句 +WHEN 条件值 THEN 执行语句 +ELSE 执行语句 +END CASE; +--------------------------------------------- +CASE +WHEN 条件值 THEN 执行语句 +WHEN 条件值 THEN 执行语句 +ELSE 执行语句 +END CASE; +``` + +## 循环 + +```mysql +-- repeat是有条件的循环控制语句, 当满足声明的条件的时候退出循环 +-- while 循环是有条件的循环控制语句 +-- 先判定条件 +WHILE 条件 DO +SQL语句 +END WHILE; +repeat +-- 先执行一次 +REPEAT +SQL语句 +END REPEAT; + +LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。 +LEAVE :配合循环使用,退出循环。 +ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。 + +[begin_label:] LOOP +SQL语句 +END LOOP; + +LEAVE label; -- 退出指定标记的循环体 +ITERATE label; -- 直接进入下一次循环 +``` + +## 游标 + +游标(CURSOR)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进 +行循环的处理。游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE,其语法分别如下。 + +```mysql +-- 声明游标 +DECLARE 游标名称 CURSOR FOR 查询语句 ; +-- 打开游标 +OPEN 游标名称 ; +-- 获取游标记录 +FETCH 游标名称 INTO 变量 [, 变量 ] ; + +-- 关闭游标 +CLOSE 游标名称 ; + +条件处理程序 +条件处理程序(Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。具体 +语法为 +DECLARE handler_action HANDLER FOR condition_value [, condition_value] +... statement ; +handler_action 的取值: +CONTINUE: 继续执行当前程序 +EXIT: 终止执行当前程序 +condition_value 的取值: +SQLSTATE sqlstate_value: 状态码,如 02000 +SQLWARNING: 所有以01开头的SQLSTATE代码的简写 +NOT FOUND: 所有以02开头的SQLSTATE代码的简写 +SQLEXCEPTION: 所有没有被SQLWARNING 或 NOT FOUND捕获的SQLSTATE代码的简写 + +存储函数 +存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。具体语法如下: +CREATE FUNCTION 存储函数名称 ([ 参数列表 ]) +RETURNS type [characteristic ...] +BEGIN +-- SQL语句 +RETURN ...; +END ; + +characteristic说明: +DETERMINISTIC:相同的输入参数总是产生相同的结果 +DETERMINISTIC:相同的输入参数总是产生相同的结果 +READS SQL DATA:包含读取数据的语句,但不包含写入数据的语句。 +``` + +## 触发器 + +触发器(trigger)是与表有关的数据库对象,指在insert/update/delete之前(BEFORE)或之后(AFTER),触发并执行触发器中定义的SQL语句集合。 +事件A 对user表新增一条数据 姓名name 年龄age 性别sex +事件B 对userlogs记录一条user表的操作 new.name,new.age +触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作。 +使用别名OLD和NEW来引用触发器中发生变化的记录内容,这与其他的数据库是相似的,触发器只支持行级触发 + +~~~mysql +# 触发器的类型 + +| 类型 | NEW和OLD | +| ------ | -------------------------------------| +| insert | new代表将要新增或已新增的数据 | +| update | old代表更新前的数据、new代表更新后的数据 | +| delete | old代表将要删除或已删除的数据 | + +-- 创建触发器 + +create trigger 触发器名称 +before/after(触发时机) insert/update/delete(触发类型) +on 表名 for each row -- 行级触发器 +begin + sql语句 +end; + +-- 查看触发器 +show triggers; + +-- 删除触发器 +drop trigger 触发器名称; + + + +~~~ + +公用表表达式 +公用表表达式(或通用表表达式)简称为CTE(Common Table Expressions)。CTE是一个命名的临时结 果集,作用范围是当前语句。CTE可以理解成一个可以复用的子查询,当然跟子查询还是有点区别的, CTE可以引用其他CTE,但子查询不能引用其他子查询。所以,可以考虑代替子查询。 + +```mysql +依据语法结构和执行方式的不同,公用表表达式分为 普通公用表表达式 和 递归公用表表达式 2 种。 +1.普通公用表表达式 +with + a as ( select department_id, min(hire_date) a1 from employees GROUP BY department_id ), + b as ( select department_id, max(hire_date) b1 from employees GROUP BY department_id ) +select a.department_id,a1 最早入职,b1 最晚入职 from a,b where a.department_id = b.department_id; + +普通公用表表达式类似于子查询,不过,跟子查询不同的是,它可以被多次引用,而且可以被其他的普 通公用表表达式所引用。 +2.递归公用表表达式 +递归公用表表达式也是一种公用表表达式,只不过,除了普通公用表表达式的特点以外,它还有自己的特点,就是可以调用自己。它的语法结构是: +WITH RECURSIVE +CTE名称 AS (子查询) +SELECT|DELETE|UPDATE 语句; +递归公用表表达式由 2 部分组成,分别是种子查询和递归查询,中间通过关键字 UNION [ALL]进行连接。 这里的种子查询,意思就是获得递归的初始值。这个查询只会运行一次,以创建初始数据集,之后递归 查询会一直执行,直到没有任何新的查询数据产生,递归返回。 + +``` + + + +## 窗口函数 + +函数 OVER([PARTITION BY 字段名 ORDER BY 字段名 ASC|DESC]) + +函数 OVER 窗口名 … WINDOW 窗口名 AS ([PARTITION BY 字段名 ORDER BY 字段名 ASC|DESC]) + +OVER 关键字指定函数窗口的范围。 + +如果省略后面括号中的内容,则窗口会包含满足WHERE条件的所有记录,窗口函数会基于所有满足WHERE条件的记录进行计算。 + +如果OVER关键字后面的括号不为空,则可以使用如下语法设置窗口。 + +窗口名:为窗口设置一个别名,用来标识窗口。 + +PARTITION BY子句:指定窗口函数按照哪些字段进行分组。分组后,窗口函数可以在每个分组中分别执行。 + +ORDER BY子句:指定窗口函数按照哪些字段进行排序。执行排序操作使窗口函数按照排序后的数据记录的顺序进行编号。 + +FRAME子句:为分区中的某个子集定义规则,可以用来作为滑动窗口使用。 + +```mysql +-- 序号函数 +row_number()、rank()、dense_rank() +-- 开窗聚合函数 +sum()|avg()|min()|max()|count()| over (partition by ... order by...) +-- 比例函数 返回<= 或 >= 当前行的所有数占总行数的比率 +cume_dist() over(order by 字段 desc) -- 大于 +-- 分组函数 +ntile(组的数量) over(partition by 分组字段 order by 分组依据) +-- 前后函数 +lag(字段,n) over(partition by 分组字段 order by 排序字段) -- 前n行 +lead(字段,n) over(partition by 分组字段 order by 排序字段) -- 后n行 +-- 窗口大小 +函数() over(partition by 字段 rows between 起始行 and 结束行) +-- rows 启用窗口大小 +-- between ... and ... 范围区间 +-- unbounded preceding 起始行 +-- n preceding 前n行 +-- current row 当前行 +-- n following 后n行 +-- unbounded following 最终行 +``` + +## 索引 + +索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足 +特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数据结构 +上实现高级查找算法,这种数据结构就是索引。 + +索引分类 + +主键索引 针对于表中主键创建的索引默认自动创建, 只能有一 PRIMARY + +唯一索引 避免同一个表中某数据列中的值重复 可以有多个 UNIQUE + +常规索引 快速定位特定数据 可以有多个 + +~~~MySQL +-- 单列索引 +-- 创建索引(普通索引) +-- 方式一:直接在已有表中创建索引 +create index 索引名 on 表名(列名) -- 直接删除索引 drop index 索引名 on 表名; 这种不能用来创建主键索引 +-- 方式二:修改表结构追加普通索引 +alter table 表名 add index 索引名(列名); -- 修改表结构删除索引 alter table 表名 drop index 索引名; + +-- 方式三:创建表的时候直接指定 +create table 表名( + a int primary key, + b varchar(5), + index 索引名 (列名) -- 以这种模式定义的索引,可以不指定索引名称。 + primary key(列名) +); +-- 查看表的索引 +show index from 表名; +-- 删除索引 +drop index 索引名 on 表名; -- 并且删除表时,会一并删除表上的全部索引。 +alter table 表名 drop index 索引名; +-- 唯一索引:它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一 +-- 创建索引 +create unique index 索引名 on 表名(列名); -- 创建普通索引的基础上。多了unique关键字在已存在的表上追加唯一索引 +alter table 表名 add unique 索引名 (列名) -- 创建表的时候直接指定 +~~~ + +## 事务 + + +数据库中的事务是指对数据库执行一批操作,在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。 + +事务特性(ACID) :一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。当事务提交之后,数据会持久化到硬盘,修改是永久性的。 + +mysql中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务。 + +是否开启隐式事务是由变量autocommit控制的。 + +只读事务:表示在事务中执行的是一些只读操作,如查询,但是不会做insert、update、delete操作,数据库内部对只读事务可能会有一性能上的优化。 + +更新丢失:丢失更新就是两个不同的事务(或者Java程序线程)在某一时刻对同一数据进行读取后,先后进行修改。导致第一次操作数据丢失。 + +第一类丢失更新 :A,B 事务同时操作同一数据,A先对改数据进行了更改,B再次更改时失败然后回滚,把A更新的数据也回滚了。(事务撤销造成的撤销丢失) + +第二类丢失更新:A,B 事务同时操作同一数据,A先对改数据进行了更改,B再次更改并且提交,把A提交的数据给覆盖了。(事务提交造成的覆盖丢失) + +脏读 +一个事务在执行的过程中读取到了其他事务还没有提交的数据。 这个还是比较好理解的。 + +读已提交 +从字面上我们就可以理解,即一个事务操作过程中可以读取到其他事务已经提交的数据。 + +事务中的每次读取操作,读取到的都是数据库中其他事务已提交的最新的数据(相当于当前读) + +不可重复读 +在同一事务中,多次读取同一数据返回的结果有所不同,换句话说,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读” 在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据。 +可重复读 +一个事务操作中对于一个读取操作不管多少次,读取到的结果都是一样的。 + +幻读 + +脏读、不可重复读、可重复读、幻读,其中最难理解的是幻读 + +事务的隔离级别 + +隔离级别分为4种: + +读未提交:READ-UNCOMMITTED + +读已提交:READ-COMMITTED + +可重复读:REPEATABLE-READ + +串行:SERIALIZABLE + +```mysql +set autocommit=0; +-- 执行事务操作 +commit|rollback; +-- savepoint关键字 +savepoint part1;//设置一个保存点 +rollback to part1;//将savepint = part1的语句到当前语句之间所有的操作回滚 +-- 查看隔离级别 +show variables like 'transaction_isolation'; +``` \ No newline at end of file -- Gitee From 1a8dc2b7d499867ded3a6e34f6cdf1c30f83f64a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E6=99=9F=E8=BE=89?= <11764051+strange-nianqian@user.noreply.gitee.com> Date: Wed, 25 Oct 2023 15:15:02 +0000 Subject: [PATCH 2/2] 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 林晟辉 <11764051+strange-nianqian@user.noreply.gitee.com> --- .../20231023 \347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) create mode 100644 "06 \346\236\227\346\231\237\350\276\211/20231023 \347\254\224\350\256\260.md" diff --git "a/06 \346\236\227\346\231\237\350\276\211/20231023 \347\254\224\350\256\260.md" "b/06 \346\236\227\346\231\237\350\276\211/20231023 \347\254\224\350\256\260.md" new file mode 100644 index 0000000..da21bf0 --- /dev/null +++ "b/06 \346\236\227\346\231\237\350\276\211/20231023 \347\254\224\350\256\260.md" @@ -0,0 +1 @@ +substring_index(str,'分界字符',n) -- 返回从字符串str截取到第n个分界符的字符串,当n大于1从左到右,小于1从右到左 curdate() -- 返回当前日期 curtime() -- 返回当前时间 now() -- 返回当前时间日期 year(date) -- 获取指定date的年份 month(date) -- 获取指定date的月份 day(date) -- 获取指定date的日期 \ No newline at end of file -- Gitee