复习{
表连接查询:
sql92:
内连接:
等值连接
不等值连接
自连接
sql99:
内连接: 取两个表交集部分
等值连接 inner join on =
不等值连接 inner join on 非等号
自连接 将当前表 当成两个表来使用 ,A, B
on A.empno = B.mgr
外连接: 外连接 = 内连接 + 主表有 从表没有
左外连接 left join on
右外连接 rigth join on
全外连接 mysql不支持
交叉连接 cross join
查询三个表的数据:
select * from A a inner join B b
on a.id = b.id
join C c on c.id = a.id
逻辑上的外键: 逻辑外键
真是外键: 不加, 只要保证 从表中有主表的主键,作为当前表的外键
模糊查询: where , having
像... like '%A%'; % 通配符 _ 占位符
不像... not like 'A%';
子查询:
一个sql中 包含一个 sql语句
可以使用在 where , having , from
count()函数的区别:
count(1) , count(*) ,count('张三') count(comm);
avg() , sum() , max(), min() }
=========================================================================
mysql中的函数 (方法):
1.数学函数:
ABS(); 绝对值
PI(); 返回值PI
POW(); 平方
2.字符串函数:
|-- ASCII(''); 返回第一个字符的对应的数字
|-- char_length(''); 返回字符个数
|-- length(''); 返回字符个数
|-- concat('str1','str2','str3'....); 拼接多个字符串 StringBuffer append()
|-- format('小数',2); 格式化保留2位小数 ,四舍五入
|-- insert(s,off,len,x1); 使用x1 替换到s ,从off开始,替换len长度
|-- locate(str1,str); 返回str1 在str 中的位置 从 1
|-- lower(); 变小写 upper(); 变大写
|-- ltrim(); rtrim(); trim(); 去掉左右两边空格
|-- position(s in s1); 返回 s 在 s1 中的位置
|-- reverse(s); 将字符串反转
|-- SUBSTR(s, start, length)
substring(s,start,length);
|-- replace(str,oldStr,newStr); 将oldStr 替换为 newStr
3.日期函数:
|-- ADDDATE('2021-01-30',INTERVAL 1 month); 将当前日期 加上指定日期
DATE_SUB(date,INTERVAL expr type); 将当前日期 减去指定间隔的值
|-- CURDATE(); 返回当前日期 年-月-日
CURRENT_DATE();
|-- now(); 返回当前日期 年-月-日 时分秒
|-- datediff(); 返回两个日期的差值
例如:select DATEDIFF('2021-08-27','2021-08-31') from dual;
TIMEDIFF(time1, time2);返回相差多少
|-- year(); month(); day(), hour(), minute(); second();
4.格式化函数: 2 SimpleDateFormat parse(String str) Date date
format(Date date); String
str_to_Date('字符串的日期格式','%Y-%m-%d');
案例: select STR_TO_DATE('1999-09-09','%Y-%m-%d') from dual;
date_format(curdate(),'%y-%m-%d %h:%i:%s');
案例: select DATE_FORMAT(now(),'%y-%m-%d %h:%i:%s') from dual;
5.条件语句函数:
if( a , b , c);
案例: select ename,if(comm,'有佣金','没有佣金') from emp;
判断comm 是否为0 或 null, 如果有值 就输出第一个参数
如果为0 或null , 就输出第二个参数
ifnull(a, b);
select ename, IFNULL(comm,'没有佣金') from emp;
判断a 是否为null ,如果是 null 就直接返回 b的结果
如果不为null 就返回 自己本身的值;
|-- case when then else end;
简单语句:
case 字段名
when '固定值1' then 结果1
when '固定值2' then 结果2
when '固定值3' then 结果3
else 结果 end;
select productName,
case color
when 'white' then '白色'
when 'red' then '红色'
when 'black' then '黑色'
else '不知道' end
from product;
select uname,
case when age < 18 then '未成年'
when age > 18 and age <= 30 then '青年'
when age > 30 and age < 60 then '中年'
when age > 60 and age < 100 then '老年' end
from tb_user;
复杂语句:
行变列 案例:
select
`name`,
sum((case when `subject`='英语' then score else 0 end)) 英语 ,
sum((case when `subject`='语文' then score else 0 end)) 语文,
sum((case when `subject`='数学' then score else 0 end)) 数学
from grade group by `name`;
联合查询: 集合查询
应用场景:
在两个表没有任何关联关系的时候,
需要将两个表的数据 整合成 一个结果集,过程就是 联合查询
前提: 表字段个数,顺序,类型 必须要一致,否则查询出来没意义
union 去重
union all 不去重
不添加过滤条件:
select * from chinese
union all
select * from american
添加过滤条件:
select * from chinese where score > 80
union all
select * from american where score > 80
---------------------------------------------------------------------------
***
事务: 真所有数据库, 关系型数据库 和 非关系型数据库
什么是事务?
事务 是 一件 或 多件 事件的集合,
这些事儿 要么全做 ,要么全不做
事务 是 一条 或多条 sql 语句的集合
这些sql 语句 要么都执行, 要么 都不执行
Account 表:
1 张三 9000
2 李四 10000
张三 给 李四 转账 1000 元
update account set balance = balance - 1000 where id = 1;
update account set balance = balance + 1000 where id = 2;
mysql中的事务默认 是 自动提交的
所以为了演示案例 我们要修改 mysql的 默认提交功能;
try{
update account set balance = balance - 1000 where id = 1;
int i = 1/0;
update account set balance = balance + 1000 where id = 2;
}catch(Excpetion e){
conn.rollback()
}finally{
conn.commit();
}
设置手动提交:
show variables like 'autocommit';
set autocommit = 0; -- 手动提交
commit; 永久提交, 永久提交后 ,不能回滚
rollback; 回滚 回复到最初的状态
savepoint; 保存点
savepoint a;
rollbacke to 保存点;
如果回滚的是最初的保存点 那么 子保存点则 取消;
update account set balance = balance - 1000 where id = 1;
update account set balacne = balance + 1000 where id = 2;
什么东西保证了 事务的正常执行呢?
MySQL的事务 离不开 四个特性 :
原子性: 一个事务 是 最小的执行单位,不可在分成多个部分
也就是说事务在执行时,不可以过半终止,所以这些sql
要么都执行,要么都不执行
一致性: 事务开启 到 事务结束 ,数据库中的数据的状态要保持一致
1.当前表中有两条数据,这两条数据在一个事务中,
那么这两条数据的 状态要一致
2.主表 从表 ,假设主表的主键 更新了,那你从表的外键
字段也必须更新;
隔离性: 体现的是在 并发情况下的 ,在一个事务操作一条数据时
其他事务不可以访问这条记录
1.读未提交数据: read uncommited
2.读已提交数据: read commited oracle数据库
3.可重复读: repeatable read mysql默认是
4.串行化: Serializtion
如何查看mysql的 隔离级别:
select @@tx_isolation;
如果 mysql 中没有隔离级别 那么 在并发情况下 读取数据时就会出现
以下情况:
1.脏读:
假设T1和T2两个事务,此时T1修改了数据库表中的某一条数据
但 没提交,这时T2读取了当前修改后的记录,这时T1 遇到问题
回滚了,这时T2读取的数据和 数据库表中的数据不一致
那就是 脏读
假设张三李四两个人,张三对一条记录进行修改,
但是没提交,这时李四查看了这条记录,完了张三
遇到问题回滚了,那李四拿的数据和 数据库的
数据不一致, 那么李四的数据 就是脏数据
2.不可重复读:
假设T1 和T2 两个事务, T1不断的读取当前表中的 某条记录
在读取 过程中 T2对当前记录进行了修改操作 ,并且提交了
这时T1 ,在一个事务中读取的数据不一致了,
这个现象就是 不可重复读
T2 做了 update操作
3.幻读 体现的时 insert 操作
T1 和 T2两个事务, 假设T1查询工资为 5000元的员工总数是10
T2 执行 inert into 操作 ,总记录数11 ,
T1 查询的总记录数和 数据库中记录数不一致,幻读
读未提交数据:
会出现 脏读,不可重复读,幻读
读已提交数据:
会解决 脏读问题, 但是有可能出现 不可重复读, 和幻读
可重复读;
会解决 脏读,不可重复度,会出现 幻读
串行化:
会解决 脏读, 不可重复读, 幻读
只的是事务 一个 接着一个的 执行,效率极低
还有哪些技术可以 解决 并发问题:
1.事务隔离界别:
2.悲观锁: 必须修改隔离级别 读 未提交数据
set session transaction isolation level read uncommitted;
select @@tx_isolation;
select ... for update 设置手动提交事务
5.5以前 myISAM 表锁
myISAM 不支持事务
现在 INNODB 行锁 表锁
INNODB 支持事务
3.乐观锁:
版本号 和 时间戳来 判断是否出现并发问题
是在你的当表上 加一个字段
time
1 张三 10000 16:14:13
2 李四 10000 1
T1 T2
now(); 16:12:33
select * from account version +1
持久性: 如果事务执行 commit 提交操作,那么对数据库永久有效
不可回滚
mysql的事务 指针对一下三种类型sql语句:
insert into
delete from
update
============================================================