diff --git "a/22 \346\226\275\346\231\237\345\256\270/20231019\344\272\213\345\212\241\347\254\224\350\256\260\345\222\214sql\347\273\203\344\271\240.md" "b/22 \346\226\275\346\231\237\345\256\270/20231019\344\272\213\345\212\241\347\254\224\350\256\260\345\222\214sql\347\273\203\344\271\240.md" new file mode 100644 index 0000000000000000000000000000000000000000..fb31b4697c0b2fab8c133a9365e043b4fd2b2a4e --- /dev/null +++ "b/22 \346\226\275\346\231\237\345\256\270/20231019\344\272\213\345\212\241\347\254\224\350\256\260\345\222\214sql\347\273\203\344\271\240.md" @@ -0,0 +1,161 @@ +````sql +笔记 + +```sql +事务的特性 +原子性 一致性 隔离性 持久性 +事务分为隐式事务和显式事务 +## 方法1:通过set autocommit = 0关闭事务自动提交 +# 查询是否开启事务自动提交,1:事务自动提交;2:事务不自动提交 +SELECT @@autocommit; +# 关闭事务自动提交 +SET autocommit = 0; +## 方法2: START TRANSACTION命令 +# 开启一个事务,使用这个命令之后,事务要使用commit或者commit work命令才会提交 +START TRANSACTION; +只读事务 +start transaction read only; + +savepoint关键字 +可以将一大批操作分为几个部分,然后指定回滚某个部分。可以使用savepoin来实现 + +隔离级别分为4种: +读未提交:READ-UNCOMMITTED +读已提交:READ-COMMITTED +可重复读:REPEATABLE-READ +串行:SERIALIZABLE +``` + +```sql +create table dept1( + deptno int primary key auto_increment, -- 部门编号 + dname varchar(14) , -- 部门名字 + loc varchar(13) -- 地址 +) ; + + +insert into dept1 values(10,'财务部','北京'); +insert into dept1 values(20,'研发部','上海'); +insert into dept1 values(30,'销售部','广州'); +insert into dept1 values(40,'行政部','深圳'); + +SELECT * FROM dept1; + +set autocommit=0; + +DELETE FROM dept1 WHERE deptno in(10,20); + +ROLLBACK; + +COMMIT; + +start transaction; + +SAVEPOINT d1; + +DELETE FROM dept1 WHERE deptno=30; + +ROLLBACK to d1; + +start transaction read only; +``` + +```sql +CREATE DATABASE a charset utf8; +use a; + +-- 部门表 +create table dept( + deptno int primary key auto_increment, -- 部门编号 + dname varchar(14) , -- 部门名字 + loc varchar(13) -- 地址 +) ; +-- 员工表 +create table emp( + empno int primary key auto_increment,-- 员工编号 + ename varchar(10), -- 员工姓名 - + job varchar(9), -- 岗位 + mgr int, -- 直接领导编号 + hiredate date, -- 雇佣日期,入职日期 + sal int, -- 薪水 + comm int, -- 提成 + deptno int not null, -- 部门编号 + foreign key (deptno) references dept(deptno) +); +insert into dept values(10,'财务部','北京'); +insert into dept values(20,'研发部','上海'); +insert into dept values(30,'销售部','广州'); +insert into dept values(40,'行政部','深圳'); +insert into emp values(7369,'刘一','职员',7902,'1980-12-17',800,null,20); +insert into emp values(7499,'陈二','推销员',7698,'1981-02-20',1600,300,30); +insert into emp values(7521,'张三','推销员',7698,'1981-02-22',1250,500,30); +insert into emp values(7566,'李四','经理',7839,'1981-04-02',2975,null,20); +insert into emp values(7654,'王五','推销员',7698,'1981-09-28',1250,1400,30); +insert into emp values(7698,'赵六','经理',7839,'1981-05-01',2850,null,30); +insert into emp values(7782,'孙七','经理',7839,'1981-06-09',2450,null,10); +insert into emp values(7788,'周八','分析师',7566,'1987-06-13',3000,null,20); +insert into emp values(7839,'吴九','总裁',null,'1981-11-17',5000,null,10); +insert into emp values(7844,'郑十','推销员',7698,'1981-09-08',1500,0,30); +insert into emp values(7876,'郭十一','职员',7788,'1987-06-13',1100,null,20); +insert into emp values(7900,'钱多多','职员',7698,'1981-12-03',950,null,30); +insert into emp values(7902,'大锦鲤','分析师',7566,'1981-12-03',3000,null,20); +insert into emp values(7934,'木有钱','职员',7782,'1983-01-23',1300,null,10); + + + + + +-- 1、列出最低薪金大于1500的各种工作。 +-- +SELECT empno FROM emp WHERE sal>1500 +SELECT job,min(sal) FROM emp WHERE empno in(SELECT empno FROM emp WHERE sal>1500 +) GROUP BY job +-- 2、列出在部门 "销售部" 工作的员工的姓名,假定不知道销售部的部门编号。 +-- +SELECT deptno FROM dept WHERE dname='销售部' +SELECT ename FROM emp WHERE deptno in(SELECT deptno FROM dept WHERE dname='销售部' +); +-- 3、列出薪金高于公司平均薪金的所有员工。 +-- +SELECT avg(sal) FROM emp; +SELECT ename,sal FROM emp HAVING sal>(SELECT avg(sal) FROM emp +) +-- 4、列出与"周八"从事相同工作的所有员工。 +-- +SELECT job FROM emp WHERE ename='周八' + +SELECT * FROM emp WHERE job in(SELECT job FROM emp WHERE ename='周八' +); +-- 5、列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金。 +-- +SELECT sal FROM emp WHERE deptno=30 +SELECT ename,sal FROM emp WHERE sal in(SELECT sal FROM emp WHERE deptno=30 +)and deptno!=30; +-- 6、列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金。 +-- +SELECT emp.ename,emp.sal FROM emp WHERE emp.sal >(SELECT max(sal) FROM emp WHERE deptno=30 +)and emp.deptno!=30; +-- 7、列出在每个部门工作的员工数量、平均工资、平均服务年限。 +-- +SELECT count(empno),avg(DATEDIFF(NOW(),hiredate))/365,avg(sal) FROM emp right join dept on emp.deptno=dept.deptno GROUP BY dname +-- 8、列出所有员工的姓名、部门名称和工资。 +-- +SELECT ename,dname,sal FROM emp right join dept on emp.deptno=dept.deptno + +-- 9、列出所有部门的详细信息和部门人数。 +-- +SELECT dept.*,count(empno) FROM emp right join dept on emp.deptno=dept.deptno GROUP BY deptno + +-- 10、列出各种工作的最低工资。 +-- +SELECT job,min(sal) FROM emp GROUP BY job; +-- 11、列出各个部门的 经理 的最低薪金。 +-- +select deptno,min(sal) from emp where job="经理" group by deptno; +-- 12、列出所有员工的年工资,按年薪从低到高排序。 +select ename,(sal+ifnull(comm,0))*12 yearsal from emp order by yearsal; + + +``` + +```` diff --git "a/22 \346\226\275\346\231\237\345\256\270/20231024\345\244\215\344\271\240\347\254\224\350\256\260.md" "b/22 \346\226\275\346\231\237\345\256\270/20231024\345\244\215\344\271\240\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..1a0590872da7bb35e10504499a9b1dc72918d3c8 --- /dev/null +++ "b/22 \346\226\275\346\231\237\345\256\270/20231024\345\244\215\344\271\240\347\254\224\350\256\260.md" @@ -0,0 +1,297 @@ +# 笔记 + +## 数值函数 + +```MySQL + -- 随机数 +select rand(); -- 返回一个0-1之间的浮点数 +select floor(rand()); -- 返回值做向下取整 +select ceil(rand()); -- 返回值做向上取整 + + -- 求余 +select mod(5,2); -- 求5除以2的余数,结果显示1 + + -- 四舍五入 +select round(6.6666); -- 四舍五入,默认只保留整数,结果为7 +select round(6.6666,3); -- 四舍五入,3表示保留到第三位,结果为6.667 +``` + +## 字符串函数 + + + +```mysql +-- 返回该字符串的长度 +select length('apple'); -- 我猜是五 + +-- 拼接括号内所有字符串 +select concat?('木','木'); -- 结果是2号的姓氏 话说为什么横杆对不齐,我要受不了了 + +-- 替代文字 +select replace('我草','草','日'); -- 结果是‘我日’ 骂人是不好的 + +-- 有奖竞猜 ‘lower’/‘upper’ 哪个是转大写哪个是转小写,猜对奖励你一个大拇指 +select lower('ABC'); -- 转小写 +select upper('abc'); -- 转大写 + +-- 填充 l在前r在后 +select lpad('apple',10,'a'); -- 在字符串前面填充a达到10个字符 +select rpad('apple',10,'e'); -- 在字符串后面填充e达到10个字符 + +-- 提取字符串前后字符 (真有人左右不分?) +select left('apple',2); -- 提取字符串前两位字符 +select right('apple',2); -- 提取字符串后两位字符 + +-- 去除空格 l是左r是右,t是全部 +select trim(' apple '); -- 去除字符串所有空格 +select ltrim(' apple '); -- 去除字符串前面的空格 +select rtrim(' apple '); -- 去除字符串后面的空格 + +-- 字符串之中提取字符 +select substring('apple',3,2); -- 从字符串第三位开始向后取值两个字符 结果是pl + +-- 返回一部分字符 +SELECT SUBSTRING_INDEX("www.w3schools.com", ".", 2); -- 返回第二个.之前的字符 +``` + +## 日期函数 + +```mysql +-- date+time=now~~~~~~~~~~~~ +select curdate(); -- 返回当前日期 +select curtime(); -- 返回当前时间 +select now(); -- 返回当前日期和时间 + +-- 英语写啥提取啥 +select year('2012-12-2'); -- 提取当前年份(需保证时间准确性) +select month('2012-12-2'); -- 提取当前月份(需保证时间准确性) +select day('2012-12-2'); -- 提取当前日期(需保证时间准确性) + +-- 没理解,但是我先抄下来再说 +SELECT DATE_ADD(NOW(), interval 20 your/month/day); -- 返回当前时间经过20年/月/日的时间 + +-- 同上 +select datediff('2022-12-2','2022-1-2'); -- 返回两个时间之间的天数 +``` + +## 存储过程 + +```mysql +delimiter && -- 将分界符从;改为&& +create procedure one() -- 创建存储过程 名字为‘one’ +begin -- 开始语句 +select * from ljy; -- 准备执行的代码 +end && -- 结束存储过程 +delimiter; -- 将分界符从&&改为; + +call one; -- 打电话喊one开始咯 +``` + +## 函数 + +```sql +substring_index(str,'分界字符',n) -- 返回从字符串str截取到第n个分界符的字符串,当n大于1从左到右,小于1从右到左 +curdate() -- 返回当前日期 +curtime() -- 返回当前时间 +now() -- 返回当前时间日期 +year(date) -- 获取指定date的年份 +month(date) -- 获取指定date的月份 +day(date) -- 获取指定date的日期 +``` + +## 存储过程 + +```sql +概念: +用于完成一次完整的业务处理,没有返回值,可通过传出参数给多个值 + +基本语法: +存储过程分为有参、无参存储过程 + +delimiter // -- 修改定界符为//(符号可以自定义,只要不是 \ ) +CREATE PROCEDURE 存储过程名称 ([ in/out/inout 参数名 参数数据类型 ]) +BEGIN +-- 真正要执行的sql语句集合(集合的意思是sql语句可以是N条,可以是查询、插入、修改、删除语句,基本DDL)每句sql语句都用 ; 结束 +END // +delimiter ; -- 将定界符还原为 ; +调用 +call 名称 ([ 参数 ]); -- 如果()里没有参数,可以把()省略 +查看 +SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'xxx'; +-- 查询指定数据库的存储过程及状态信息 +SHOW CREATE PROCEDURE 存储过程名称 ; +-- 查询某个存储过程的定义 +-- 删除 + + DROP PROCEDURE [ IF EXISTS ] 存储过程名称; + -- 存储过程不支持直接修改过程的语法,需要先删除原有的过程,再重新建一个同名的,删除时不需要加() +注意: 在命令行中,执行创建存储过程的SQL时,需要通过关键字 delimiter 指定SQL语句的结束符。 + +(4)定义一个参数的语法包括参数模式、参数名称、参数数据类型 + +IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量) +OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量) +INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量) +存储过程可以有0个或多个参数,用于存储过程的定义。 + + +delimiter // +create procedure 存储过程名称(in myid int,out myname varchar(20)) -- 传入编号传出名称 +begin +select first_name into myname from employees where employee_id=myid; +end // +delimiter ; +call 存储过程名称 (100,@newname); +select @newname; +③ inout 入参出参 + +delimiter // +create procedure 存储过程名称(inout myname varchar(20)) -- 传入含有空格的名字传出去除空格的名字 +begin +set myname=trim(myname); +end // +delimiter ; +set @name1=' 李小龙 ' +call 存储过程名称 (@name1); +select @name1; +``` + + + +## RBAC + +```sql +基于角色的权限访问控制 + +通过将用户分配到不同的角色,从而赋予用户相应的权限。 + +RBAC模型的核心是角色,而不是用户,角色扮演者可以是用户、组织机构、应用程序等,而权限则是分配给角色,而非用户。 + +一个商品有多种规格 + +由不同属性构成了一个规格,不同的商品属性组合而成的最小单位 + +表与表之间的关系 +1.一对一的关系:将其中任一表中的主键,放到另一表当外键 +2.一对多的关系:将一所在的表的主键,放到多的表中当外键 +3.多对多的关系:必须第三张表,将前面两张表的主键放进往外键 + +数据库设计方法: +1.直观设计法 +2.规范设计法 +3.计算机辅助设计法 + +E-R图 +实体:画矩形,写里面的实体的名称 +属性:椭圆或圆形,里面写属性名称,用线条与实体相连,如果是主属性名称下加下划线 +关系:用线条将两个实体相连,中间可以用菱形表示中间的关系 + +数据库设计的三大范式: + +1、第一范式:每个属性,也就是字段要求不可分割,也就要求有原子性。 + +2、第二范式:在满足第一范式的基础上,要求非主键字段要完全依赖主键(有联合主键时,非主键要同时完全依赖这两个主键,而不能部分依赖。 + +3、第三范式:在满足第二范式的基础上,要求非主键字段要直接依赖于主键。 + + + + +``` + +## 触发器 + +```sql +创建触发器 +create trigger 触发器名称 +before/after(触发时机) insert/update/delete(触发类型) +on 表名 for each row -- 行级触发器 +begin + 触发的语句... +end; + +查看触发器 +show triggers; +删除触发器 +drop trigger 触发器名称; + +窗口函数的语法结构是: +函数 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子句:为分区中的某个子集定义规则,可以用来作为滑动窗口使用。 +``` + +## 索引 + +```sql +创建索引(普通索引) +1.直接在已有表中创建索引 +create index 索引名 on 表名(列名) -- 直接删除索引 drop index 索引名 on 表名; 这种不能用来创建主键索引 +2.修改表结构追加普通索引 +alter table 表名 add index 索引名(列名); -- 修改表结构删除索引 alter table 表名 drop index 索引名; +3.创建表的时候直接指定 +create table 表名( + aaa int primary key, + bbb varchar(20), + index 索引名 (列名) -- 以这种模式定义的索引,可以不指定索引名称。 + primary key(列名) +); + +查看表的索引 +show index from 表名; +删除索引 +drop index 索引名 on 表名; +唯一索引 +create unique index 索引名 on 表名(列名); +在已存在的表上追加唯一索引 +alter table 表名 add unique 索引名 (列名) +删除主键 +alter table 表名 drop primary key; +联合索引(执行最左原则) +create index 索引名 on 表名(列名1,列名2....) -- 普通的联合索引 +create unique index 索引名 on 表名(列名1,列名2....) -- 联合唯一索引 +``` + +## 事务 + +```sql +ACID属性: +原子性(Automicity) +原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 +一致性(Consistency) +事务必须使数据库从一个一致性状态变换到另外一个一致性状态。 +隔离性(Isolation) +事务的隔离性是指一个事务的执行不能被其他事务干扰,执行的各个事务之间不能互相干扰。 + 隔离级别:读未提交、读已提交、可重复读、串行化 +持久性(Durability) +持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。 + +rollback:回滚操作,回滚具有附加确认的效果,一旦回滚事务就结束了。 +查看自动提交的状态: show variables like "autocommit"; +关闭自动提交: set autocommit = off; set autocommit = 0; +打开自动提交: set autocommit = on; set autocommit = 1; +autocommit = 0 隐式事务是开启状态,也就是事务的操作由系统自动操作。 +start transaction; 不管显式,隐式,都可以临时手动开启一次事务。 +savepoint 字段名:设置一个保存点 +start transaction read only; 只读的事务,手动开启 +``` + +## 公共表达式 + +```sql +1.普通公用表表达式 +WITH CTE名称 +AS (子查询) +SELECT|DELETE|UPDATE 语句; + +2.递归公用表表达式 +WITH RECURSIVE +CTE名称 AS (子查询) +SELECT|DELETE|UPDATE 语句; +``` \ No newline at end of file