diff --git "a/\345\256\213\345\207\257/20241021\346\225\260\346\215\256\345\272\223\351\253\230\347\272\2472\347\273\223.md" "b/\345\256\213\345\207\257/20241021\346\225\260\346\215\256\345\272\223\351\253\230\347\272\2472\347\273\223.md" new file mode 100644 index 0000000000000000000000000000000000000000..30cdf2f485db1472acfc86e9f0409689497bd060 --- /dev/null +++ "b/\345\256\213\345\207\257/20241021\346\225\260\346\215\256\345\272\223\351\253\230\347\272\2472\347\273\223.md" @@ -0,0 +1,544 @@ +# 笔记 + +## 数据库设计: + +表与表之间的关系: + +1.一对一:A表之中的数据,在B表中只能找到一条数据关 联,反之亦然。 + +2.一对多:A表中的数据,在B表能找到多条数据关联。 + +3.多对多:A表中的数据,在B表能找到多条数据关联。反之亦然。 + +三大范式: + +1.第一范式:确保每个表格中的字段都包含原子值,即每个字段只能存储一个单一的值,不允许出现重复的组。 + +2.第二范式:确保每个非主属性完全依赖于主键,而不是主键的一部分。解决了部分依赖的问题。 + +3.第三范式:确保每个非主属性既不依赖于主键的部分,也不依赖于其他非主属性(消除传递依赖)。 + +RBAC:基于角色的访问控制 + +spu 和sku 关系:一对多 + +## 视图: + +视图是一个虚拟存在的表,视图并不在数据库中存在。 + +创建视图: + +create view 视图名 as select 查询语句; + +查询是基表还是视图: + +show full tables; + +查看表、视图结构: + +desc 表/视图名; + +如何查看建表结构: + +show create table 表名; + +修改视图结构: + +create or replace view 视图名 as select 查询语句; + +修改视图名字: + +rename table 原视图名 to 新视图名; + +修改视图内容: + +update 视图名 set 字段名 =" "条件语句; + +删除视图: + +drop view 视图名; + +## 存储过程: + +存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行. + +### 优点 + +- 存储过程可封装,并隐藏复杂的商业逻辑。 +- 存储过程可以回传值,并可以接受参数。 +- 存储过程无法使用 SELECT 指令来运行,因为它是子程序,与查看表,数据表或用户定义函数不同。 +- 存储过程可以用在数据检验,强制实行商业逻辑等。 + +## 语法: + +创建存储过程: + +``` +create procedure 存储过程名() +begin +sql 语句集; +end; +``` + +查询存储过程: + +``` +show procedure status where 条件; +``` + +调用存储过程: + +``` +call 存储过程名; +``` + +删除存储过程 + +``` +drop procedure 存储过程名; +``` + +mysql 没法修改存储过程。 + +mysql一个语句的结束,,默认以;号结束,可以先修改分隔符。 + +例: + +``` +delimiter // +create procedure 存储过程名() +begin +sql 语句集; +end // +delimiter ; +``` + +变量: 1.系统变量 2.自定义变量 + +1.系统变量 + +1.会话系统变量 : 次连接,当前连接有效 @@session + +2.全局系统变量:跨链接,但重启可能失效 @@global + +2.自定义变量 + +1.用户变量:当前连接有效 @ 变量名 + +2.局部变量: 只在begin 和end范围内有效 + +关键字: declare + +declare 变量名 数据类型 + +传参的三种方式: + +in、out、inout + +### 判断和循环 + +if条件判断: + +if表达式:if(expr1,expr2,expr3)如果expr1 为true,则if()返回值为expr2 ,否则为expr3. + +ifnull 表达式: + +ifnull(expr1,expr2),假设expr1不为null则返回expr1,否则返回expr2; + +**如果null值参与计算结果也是null** + +if....else 语句: + +IF 条件1 THEN + +..... ELSEIF 条件2 THEN -- 可选 + +..... ELSE -- 可选 + +..... END IF; + +case ...when 条件判断: + +单值判断: + +begin + +CASE case_value + +``` +WHEN 值1 THEN statement_list1 +WHEN 值2 THEN statement_list2 ... +ELSE select 语句; +end case; +end; +``` + +范围区间判断: + +begin + +CASE + +``` +WHEN 输入的数字>or<值1 THEN select 语句; +WHEN 输入的数字>or<值2 THEN select 语句 ... +ELSE select 语句; +end case; +end; +``` + +while 循环: + +begin + +WHILE 条件 DO + +sql 语句 + +END WHILE; + +end; + +repeat循环: + +-- 先执行一次逻辑,然后判定UNTIL条件是否满足,如果满足,则退出。 -- 如果不满足,则继续下一次循环 + +REPEAT + +sql语句; + +until 条件判断 + +END REPEAT; + +loop+leave循环: + +begin_label: LOOP + +sql语句; + +END LOOP begin_label ; + +end; + +## 普通函数: + +普通函数分为数值函数和字符串函数还有时间函数。 + +数值函数: + +1.abs(x)函数,取绝对值 + +select abs(-10); ——10 + +2.floor(x)函数,返回小于或者等于x的最大整数,即向下取整 + +select floor(3.9415) ——3 + +3.rand()函数,返回0~1之间的小数【0,1) + +select floor(rand()*14+1)+1000;——1001~1014之间的随机数 + +4.PI()函数 圆周率 + +select PI(); ——3.1415926 + +5.truncate(x,y)函数,截取x后y位小数的值 + +select truncate(3.1415926,3);——3.141 + +6.round(x) 函数和round(x,y)函数,前面四舍五入到整数后面四舍五入到x的y位小数 + +select round(3.14159);——3 + +select round(3.14159);——3.142 + +7.ceil(x)函数向上取整 + +select ceil(3.65);——4 + +字符串函数: + +1.insert (s1,x,len,s2)函数,将s1中x位置开始长度为len的字符串替换为s2 + +2.upper(x)所有字母大写 + +3.lower(x)所有字母小写 + +4.left(x,n),字符串x的前n个字符 + +5.concat(x1,x2,x3...)拼接字符串 + +6.rtrim(x)函数去右侧空格 ltrim(x)函数去左侧空格 trim(x)去两侧空格 + +7.substring(x,n,len),从字符串x的第n个位置获取长度为len的字符串 + +8.recerse(x)函数,将字符串x的顺序反过来 + +9.substring_index(str,delim,count) str:要处理字符串 delim:分隔符 count:计数,负数反向取 + +## 窗口函数 + +窗口函数(Window Function)是 SQL 的一种功能,它允许您在 SQL 查询中执行复杂的计算,如运行总和、平均值、排名等,而不需要重复扫描数据表。窗口函数在数据分析和报表生成中非常有用。 + +以下是窗口函数的一些基本概念和常用的窗口函数: + +### 基本概念 + +1. **窗口**:窗口函数定义了一个数据子集,称为窗口,窗口函数在这些子集上进行计算。 +2. **分区**:窗口可以按照某个条件(如 `PARTITION BY` 子句)将数据分为多个分区,每个分区内部的数据相互独立地进行计算。 +3. **排序**:使用 `ORDER BY` 子句定义窗口内数据的排序方式,这影响某些窗口函数的计算结果。 +4. **框架**:通过 `ROWS` 或 `RANGE` 子句定义窗口的框架,指定窗口内应该包含哪些行。 + +### 常用的窗口函数 + +1. **`ROW_NUMBER()`**:为每个分区内的行分配一个唯一的连续整数。 +2. **`RANK()`**:为每个分区内的行分配一个排名,相同值的行会有相同的排名,排名之间会有间隔。 +3. **`DENSE_RANK()`**:与 `RANK()` 类似,但排名之间不会有间隔。 +4. **`LEAD()`**:返回当前行之后的下一行的值。 +5. **`LAG()`**:返回当前行之前的上一行的值。 +6. **`SUM()`**:计算分区内所有值的总和。 +7. **`AVG()`**:计算分区内所有值的平均值。 +8. **`MIN()`**:返回分区内的最小值。 +9. **`MAX()`**:返回分区内的最大值。 +10. first_value(): 第一个极值 +11. last_value():最后一个极值 + +## 存储函数: + +存储函数: + +create function 函数名(参数名 数据类型) + +returns 返回的值的数据类型 + +determinstic/no sql/reads sql data 视情况选择 + +begin + +declare a varchar(20); + +函数体; + +return a; + +end; + +select 函数名(); + +删除存储函数: + +drop function 存储函数名; + +查看所有存储函数: + +show function status; + +查看存储函数创建语句: show create function 存储函数名; + +## 游标: + +游标:在mysql中游标(光标,指标)是一个数据库对象,用于在查询结果集上执行逐行的数据操作。 + +一般用于存储过程和函数中,但也可以在sql语句中使用。 + +主要作用: + +1.逐行处理数据 + +2.浏览大型结果集 + +3.控制数据访问 + +游标的使用方式: + +1.声明游标 cursor + +declare 游标名称 cursor for select 语句; + +2.打开游标: + +open 游标名称; + +3.读取数据 + +fetch 游标名称 into 变量; + +4.处理数据 + +5.关闭数据 + +close 游标名称; + +## 触发器: + +触发器: + +触发器(Trigger)是一种特殊类型的存储程序,它会在满足特定条件时自动执行。触发器与表紧密相关,并且会在对这些表执行特定类型的数据操作(如 INSERT、UPDATE 或 DELETE)之前或之后自动触发。触发器可以用来实现复杂的业务规则、数据验证、自动更新汇总信息等。 + +格式: + +create trigger 触发器名字,触发时间(before,after),触发事件(insert,update,delete) on 监控的表 for each row + +begin + +要被触发的操作 + +end; + +## 事务: + +事务: + +事务就是用户给数据库操作序列,要么全做,要么全不做,是一个整体,不可分割。 + +支持事务的数据库拥有4个特性: + +原子性,一致性,隔离性,持久性。 + +set @@autocommit=0;将系统中的自动提交关闭 + +start transaction;开启事务 + +rollback;回滚,撤销整个事务的所有操作,隐式的结束事务。 + +commit;提交,不能反悔 + +replease savepoint s1;删除s1这个保存点 + +回滚部分事务: + +start transction; + +select *from bank; + +INSERT INTO `bank` VALUES (1, '张三', 100); + +savepoint s1; + +INSERT INTO `bank` VALUES (2, '李四', 200); + +savepoint s2; + +INSERT INTO `bank` VALUES (3, '李五', 200); + +rollback to s2; + +commit; + +隔离四个级别:(isolation) + +1.读未提交(read uncommitted) + +a 没提交 ,b可以读a还没提交的东西 + +2.读已提交(read committed) + +3.可重复读(repeatable read) + +4.序列化读/串行化读(serializable) + +可解决所有问题,但是效率最低 + +## 索引: + +索引:索引是一种数据结构,它的出现就是为了提高数据查询的效率。 + +以文本的形式存在磁盘中。 + +如何创建一个普通的索引(单列) + +create index idx_username on user_list(user_name); + +添加索引: + +alter table user_list add index idx_phone(phone); + +查看一个表的索引: + +show index fromuser_list; + +在建表的时候指定索引: + +create table aa( + +ID int + +index idx_id(id) + +); + +删除索引: + +drop index idx_id on aaa; + +alter table use_list drop index idx_phone; + +如何创建一个普通索引(多列) + +create index idx_uname_phone on user_list (user_name,phone); + +建立一个唯一索引(单列) + +create index idx_aaa on aaa(id); + +explain:可以查看有没有用到索引 + +## 综合练习: + +1. 利用另外一个文件`initDb.sql`,完成以下题目: + + 1.1. (10分) 对学生姓名创建普通索引(`idx_StudentName`) + + ``` + create INDEX idx_StudentName on student(StudentName); + ``` + + 1.2. (10分) 创建视图`V_StudentHobbyInfo`,其中包含姓名(`StudentName`),爱好(`Hobby`),特长(`Specility`)列,并分别取别名为`vw_StudentName`,`vw_Hoppy`,`vw_Speclitiy` + + ``` + create view V_StudentHobbyInfo as SELECT + StudentName vw_StudentName,Hobby vw_Hoppy,Speciality vw_Speclitiy from student st join studentextinfo sx on st.StudentCode=sx.StudentCode; + ``` + + `1.4. (5分) 查询学生`马又云`的生源地,要求显示:姓名(`StudentNameame`),生源地(`OriginPosition`)` + + ``` + SELECT StudentName 姓名,OriginPosition 生源地 from student st join studentextinfo sx on st.StudentCode=sx.StudentCode WHERE StudentName="马又云"; + ``` + + 1.5. (5分) 查询学生表(`StudentInfo`)中还未还书的读者的学号(`StudentCode`)和姓名(`StudentName`),以及借书时间(`BorrowTime`) + + ``` + SELECT sx.StudentCode 学号,StudentName 姓名,BorrowTime 借书时间 from studentextinfo sx join student st on sx.StudentCode=st.StudentCode join borrowrecord bo on bo.StudentCode=st.StudentCode WHERE ReturnTime is null; + ``` + + 1.6. (5分) 查询借阅过书籍《射雕英雄传》的学生,要求显示:学生姓名(`StudentName`),学院(`School`),图书名(`BookName`),借阅时间(`BorrowTime`) + + ``` + SELECT StudentName 学生姓名,School 学校,BookName 图书名,BorrowTime 借阅时间 from student st + join borrowrecord bd on st.StudentCode=bd.StudentCode + join bookextinfo bx on bx.Barcode=bd.Barcode + join bookinfo bo on bo.ISBN=bx.ISBN + WHERE bx.Barcode="I247.56" or bx.Barcode="I247.59"; + ``` + +2. (30分)某医院病房计算机管理中心需要如下信息: + + ``` + 科室:科编号、科名、科地址、科电话、医生姓名 + 病房:病房号、床位号、所属科室名 + 医生:姓名、职称、所属科室名、年龄、工作证号 + 病人:病历号、姓名、性别、诊断、主治医生、病房号 + ``` + + 2.1. (10分)其中,一个科室有多个病房、多个医生;一个病房只能属于一个科室,一名医生只属于一个科室,但可负责多名病人的诊治,一个病人的主主治生只有一个。科编号是标识列,从1开始自增长,步进值为1,医生职称有:实习,初级,中级,高级。 请设计该表关系模式结构(数据库物理模型),要求: + + ``` + a. 中文名和英文名称清晰(可借助有道翻译工具,不允许开网页) + b. 表关系准确,包括主键,外键,标识列 + c. 将完成的设计截图,并且保存物理模型文件,命名为恰当的名称 + d. 将截图和物理模型文件放在自己的文件夹中 + ``` + + 2.2. (10分)创建存储过程实现:传入病历号,查询其对应的主治医生及其所在的病房号、床位号。 2.3. (10分)创建触发器实现:当医生离职时,检查其是否还有未完成医治的病人,如果还存在病人则不予离职,否则可以离职。 \ No newline at end of file