Mysql05隔離級別,檢視,索引,事務,左右連線
Mysql資料庫day05
行內檢視子查詢
l 子查詢在from後面
l 從一個查詢的查詢結果,再查詢
select … from (select …) t
l 行內檢視後面必須起一個別名
Select欄位列表中的子查詢
l select a,b,c,(select …) from …
多表關聯查詢
l 多張表,按條件連線成一張表
l Select 表1.欄位列表, 表2.欄位列表
from 表1,表2
where 表1.欄位1=表2.欄位2
l 自連線:將一張表看作是兩張表進行連線
l 標準表連線語法:
select …
from
表
inner join 表2
on 連線條件
inner join 表3
on 連線條件
inner
on 連線條件
l 外連線
連線條件以外的資料,也查詢出來
n 左外連線
a left outer join b on …
左側a表,條件外的資料也查詢出來
n 右外連線
a right outer join b on …
右側b表,條件外的資料也查詢出來
select查詢結構
select
distinct
from
join on
left join on
right join on
where
group by
having
order by
limit
事務
l 事務是資料操作的最小單元
l 多個數據增刪改操作,完成的一項業務處理
l 如果事務事務成功,其中每一項操作都生效
如果事務事務失敗,其中每一項操作都失敗
l 資料庫資料操作,以事務為一個最小操作單元,
不應該以一個sql語句為一個操作單元;
要麼整個事務成功,要麼整個事務失敗
l 在當前事務中對資料的修改,只對當前連線可見
l ACID
A - 原型性 Atomic
C - 一致性 Consistency
轉賬前 a+b = 100
轉帳後 a+b = 100
I - 隔離性 Isolation
一個事物進行中時,
另一事物不能操作資料
D - 永續性 Durancy
提交事務之後,
資料持久生效
l 事務操作
n 開始事務
start transaction; / begin;
n 提交事務
commit;
n 回滾事務
rollback;
隔離級別
l set tx_isolation='read-uncommitted';
l set tx_isolation='read-committed';
l set tx_isolation='repeatable-read';
l set tx_isolation='serializable';
l 隔離級別越低,效率越高,資料訪問衝突越多
l 隔離級別越高,效率越低,資料訪問衝突越少
l 資料庫預設隔離級別是repeatable-read
資料訪問衝突問題
n 髒讀
讀取到其他事物未提交的資料
n 幻讀
一個事務新增或刪除資料並提交,
另一個事務查詢不到新資料,或仍查詢到已刪除的資料
n 不可重複讀
再次查詢的資料,與第一次查詢的資料不一致
隔離級別對應資料訪問衝突現象
read-uncommitted |
髒讀,幻讀,不可重複讀 |
read-committed |
幻讀,不可重複讀 |
repeatable-read |
幻讀 |
serializable |
|
檢視
l 將一個查詢儲存在資料庫中
l 可以從這個查詢的查詢結果,再查詢
l 作用:
n 簡化查詢
n 安全
可以讓低許可權使用者,只能從檢視查詢,
而不能去碰真實資料表
建立檢視
create (or replace) view v1
as
select …
檢視檢視
show tables;
desc v1;
show create table v1\G
刪除檢視
drop view v1;
索引
l 提高欄位的過濾查詢速度
l 常見索引資料結構:
n B-Tree
n 雜湊表
建立索引
create index index_name on tb1(name);
n where name='abc'
n where name like 'abc%'
n order by name
n where name like '%abc%' 不使用索引
create index index_name on tb1(name, birthday);
n where name='abc' and birthday='xxxxxx'
n where name='abc'
n where birthday='xxxx' 第二個欄位單獨過濾不使用索引
檢視索引
show create table tb1\G
刪除索引
alter table tb1 drop index index_name;
練習
1. 只有一個下屬的主管資訊
主管id 手下
100 3
120 5
130 1
160 1
員工id first_name salary
130 xxx xxx
160 xxx xxx
select employee_id,first_name,salary
from employees where employee_id in
(select manager_id from employees
where manager_id is not null
group by manager_id having count(*)=1)
2. 平均工資最高的部門編號
過濾條件是用 9000 過濾部門
部門 平均工資
30 6000
50 7000
80 5000
90 9000
100 9000
select department_id,round(avg(salary),2) a
from employees
where department_id is not null
group by department_id
having a=
(select max(a) from
(select department_id, round(avg(salary),2) a
from employees
where department_id is not null
group by department_id) t) -- 必須起別名
3. 平均工資最低的工種,查詢做這些工作的人
工種 平均工資
A 5000
B 9000
C 3000
D 12000
E 3000
Select employee_id,first_name,salary,job_id
From employees
Where job_id in
(select job_id from employees
group by job_id
having round(avg(salary),2)=
(select min(a) from
(select job_id,round(avg(salary),2) a
from employees
group by job_id) t))
4. 查詢員工工資,同時列出最高工資
select
employee_id,
first_name,
salary,
(select max(salary) from employees) max
From
Employees;
5. 部門表
Select * from departments;
6. 查詢員工資訊,並顯示部門名稱
select e.employee_id,
e.first_name,
e.salary,
d.department_id,
d.department_name
from employees e,
departments d
where e.department_id=d.department_id;
7. 地區表
Select * from locations;
8. 查詢部門,同時顯示部門所在城市
select
d.department_id,
d.department_name,
L.location_id,
L.city
from
departments d,locations L
where
d.location_id=L.location_id;
9. 查詢員工,顯示部門名和城市
select
e.employee_id,e.first_name,e.salary,
d.department_name,
L.city
from
employees e,
departments d,
locations L
where
e.department_id=d.department_id
and
d.location_id=L.location_id;
10. 查詢部門,顯示部門經理名
select
d.department_id,
d.department_name,
d.manager_id,
e.first_name
from
departments d,
employees e
where
d.manager_id=e.employee_id;
11. 查詢員工,顯示主管名
select
e1.employee_id,e1.first_name,e1.salary,
e2.first_name manager
from
employees e1,employees e2
where
e1.manager_id=e2.employee_id;
12. 查詢員工,顯示主管名、部門、部門經理名、城市
employees e1
employees e2
departments d
employees e3
locations l
select e1.employee_id,e1.first_name,
e2.first_name mgr, d.department_name,
e3.first_name manager,l.city
from employees e1
join employees e2
on e1.manager_id=e2.employee_id
join departments d
on e1.department_id=d.department_id
join employees e3
on d.manager_id=e3.employee_id
join locations l
on d.location_id=l.location_id;
13. 查詢所有員工,顯示部門名,沒有部門顯示null
select e.employee_id,e.first_name,
d.department_name
from employees e
left join departments d
on e.department_id=d.department_id;
14. 按城市分組,計算每個城市的員工數量
select
l.city, count(*) c
from employees e
join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
group by l.city
order by c desc;
15. Seattle 市所有的員工資訊
select
e.employee_id,e.first_name,e.salary,
l.city
from employees e
join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
where l.city='Seattle';
16. 事務測試
use test;
drop table if exists tb1;
create table tb1(
id int primary key auto_increment,
name varchar(20)
回話1 |
回話2 |
Use test |
User test |
begin; |
begin; |
Insert into tb1(name) values('aa'); |
|
select * from tb1; |
select * from tb1; |
commit; |
|
|
select * from tb1; |
|
commit; |
|
select * from tb1; |
);
回話1 |
回話2 |
Use test |
Use test |
begin; |
begin; |
insert into tb1(name) values('bb'); |
|
update tb1 set name='aaaa' where id=1; |
|
|
Select * from tb1; |
|
update tb1 set name='aaaaaaaa' where id=1; |
rollback; |
|
Select * from tb1; |
Select * from tb1; |
|
commit; |
17. 隔離級別測試
回話1 |
回話2 |
set tx_isolation= 'read-uncommitted'; |
set tx_isolation= 'read-uncommitted'; |
rollback; begin; |
rollback; begin; |
Insert into tb1(name) values('bb'); |
|
|
Select * from tb1; |
Update tb1 set name='a' where id=1; |
|
|
Select * from tb1; |
rollback; |
|
|
Select * from tb1; |
回話1 |
回話2 |
set tx_isolation= 'read-committed' |
set tx_isolation= 'read-committed' |
rollback; begin; |
rollback; begin; |
Insert into tb1(name) values('bb'); |
|
Update tb1 set name='aaaaaaaaaaaa' where id=1; |
|
|
select * from tb1; |
commit; |
|
|
select * from tb1; |
回話1 |
回話2 |
set tx_isolation= 'repeatable-read' |
set tx_isolation= 'repeatable-read' |
rollback; begin; |
rollback; begin; |
insert into tb1(name) values('cc'); |
|
update tb1 set name='bbbbbbbb' where id=4; |
|
|
select * from tb1; |
commit; |
|
|
select * from tb1; |
|
update tb1 set name=concat('*',name); |
|
select * from tb1; |
回話1 |
回話2 |
set tx_isolation= 'repeatable-read' |
set tx_isolation= 'repeatable-read' |
rollback; begin; |
rollback; begin; |
|
select * from tb1; |
delete from tb1 where id=4; |
|
|
select * from tb1; |
commit; |
|
|
select * from tb1; |
|
update tb1 set name=concat('#',name); |
|
select * from tb1; |
18. 檢視測試
use hr;
create or replace view v1 as
select
l.city, count(*) c
from employees e
join departments d
on e.department_id=d.department_id
join locations l
on d.location_id=l.location_id
group by l.city;
show tables;
desc v1;
show create table v1\G
select * from v1;
select c from v1;
select * from v1 where c=1;
練習
子查詢:
1. 工資多於工種 IT_PROG 平均工資的員工
select employee_id,first_name,salary
from employees
where salary>(
select avg(salary) from employees
where job_id='IT_PROG'
);
2. 平均工資最高的工種, 顯示工作全名
Jobs表儲存工作全名
select job_id,job_title from jobs
where job_id in
(
select job_id from employees
group by job_id
having avg(salary)=(
select max(a) from
(select job_id,avg(salary) a from employees
group by job_id) t
)
);
3. 每個部門拿最高工資的人
select employee_id,first_name,salary,department_id
from employees
where (department_id,salary) in
(
select department_id,max(salary)
from employees
where department_id is not null
group by department_id
)
4. 每年第一個入職的人
select employee_id,first_name,salary,hire_date
from employees
where hire_date in
(
select min(hire_date)
from employees
group by extract(year from hire_date)
);
5. 平均工資最高的部門編號
select department_id,round(avg(salary),2) a
from employees
where department_id is not null
group by department_id
having a =
(
select max(a) from
(select department_id,round(avg(salary),2) a
from employees
where department_id is not null
group by department_id) t
);
6. 下屬人數最多的人,查詢其個人資訊
select employee_id,first_name,salary
from employees
where employee_id in
(
Select manager_id
From employees
Where manager_id is not null
Group by manager_id
Having count(*)=
(
select max(c) from
(
Select manager_id, count(*) c
From employees
Where manager_id is not null
Group by manager_id
) t
)
)