java學習day21~23--MySQL(下)
函式
例如 lower 函式把字元變成小寫
upper 函式把字元變成大寫
常用的函式 :
1) 時間加減
date_add(原始時間, 時間間隔)
時間間隔的語法: interval 數字 時間單位
數字可以是正數或負數
select date_add(now(), interval 1 day );
2) 提取時間的某個部分
extract(時間部分 from 原始時間)
select extract(year from now());
select extract(year_month from now());
返回的結果是一個數字型別
例:要獲取1981年入職的員工
select * from emp where extract(year from hiredate)=1981;
3)型別轉換
select cast('11' as signed)+1;
select cast('12.55555' as decimal(5,2));
4)拼接字串
concat(值1, 值2, ... 值n)
select concat('a', 'b', 'c');
select concat('a', 18, 'c'); /*可以把其它型別當做字串拼接*/
5) 求長度的函式
char_length 按字元為單位統計長度
length 按位元組為單位統計長度
utf8mb4編碼下,漢字一個字元佔三個位元組,英文一個字元佔一個位元組
6) 標準sql:
case
when 條件1 then 值1
when 條件2 then 值2
...
else 值n
end
整個case...end 最後返回一個值
select sal,
case
when sal>2000 then '高工資'
when sal between 1000 and 2000 then '中等'
else '低工資'
end from emp;
7) 組函式
最大值 max(列)
最小值 min(列)
和 sum(列)
個數 count(列) 會排除null值
count(*) 針對這次查詢,看看一共有多少行
平均值 avg(列)
8) 去除重複
distinct
select distinct job from emp; /*去除重複後的職位有哪些*/
select count(distinct job) from emp; /*有幾種職位*/
9) 查詢幫助
? contents 總目錄
分組語法
select ... from 表 group by 列1,列2... having 分組條件
select deptno,count(*),max(sal) from emp group by deptno;
把部門編號取值相同的分為一組, 配合組函式一起使用
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | NULL | 20 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-07-13 | 3000.00 | NULL | 20 |
| 7876 | ADAMS | CLERK | 7788 | 1987-07-13 | 1100.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL | 30 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | NULL | 30 |
查詢分組後個數大於3的部門編號和個數
select deptno,count(*),max(sal) from emp
group by deptno having count(*)>3 order by max(sal);
分組後 select,order by 的限制
1) select,order by 中的列必須和group by中的列一樣
2) 其它沒有包含在 group by語句中的列,必須和組函式一起用
執行從先到後
where 進行一遍條件過濾 , 再執行 group by 分組, 再執行 having中的條件, 再執行select, 再執行order by, 執行limit
語法順序
select ... from ... where ... group by ... having ... order by ... limit;
列別名問題
語法: select 列名 別名 ...
語法2: select 列名 as 別名 ...
select deptno 部門編號,count(*) 人數,max(sal) 最高工資 from emp
group by deptno having count(*)>3 order by max(sal);
select deptno 部門編號,count(*) 人數,max(sal) 最高工資 from emp
group by deptno having count(*)>3 order by 人數;
select empno "員工 編號" from emp; /*列別名中如果存在空格等特殊符號,需要用雙引號包圍列別名*/
表別名問題
語法 : select ... from 表 別名
select e.* from emp e;
多列分組
select deptno, job, count(*) from emp group by deptno, job;
/*按deptno和job這兩列取值都相同的分為一組*/
連線查詢
內 連線
select ... from 表1 inner join 表2 on 連線條件 WHERE ... group by ... HAVING ... ORDER BY ... limit ... (重點)
左 外
select ... from 表1 left [outer] join 表2 on 連線條件 (重點)
右 外
select ... from 表1 right [outer] join 表2 on 連線條件
全
select ... from 表1 full join 表2 on 連線條件 (mysql不支援全連線)
例:連線部門表和員工表
select * from emp a inner join dept b on a.deptno=b.deptno;
注意:
1) 內連線是將兩張表中所有符合連線條件的資料列入結果,不符合連線條件的結果中沒有,例如40號部門
2) 如果連線的兩表中有同名的列,列前面要加表名(或表別名)來區分(否則會報歧義錯誤)
3) inner join ... on 的寫法是符合SQL-92標準寫法,其實還有一種內連線的寫法:
select ... from 表1, 表2 where 連線條件;
例: 還是連線部門表和員工表 select * from emp a, dept b where a.deptno=b.deptno;
連線學生表成績表
課程表連線老師表
課程表連線成績表
例子:採用左外連線員工表和部門表
select * from emp a left join dept b on a.deptno = b.deptno;
例子:採用左外連線部門表和員工表
select * from dept b left join emp a on a.deptno = b.deptno;
左外連線,首先將符合連線條件的記錄連在一起,作為結果,其次左邊表中不符合連線條件的記錄也會出現在結果中,只不過它對應的右邊的列都是NULL
例子:右外連線
select * from emp a right join dept b on a.deptno = b.deptno;
注意:左外和右外與表的先後次序有關,而內連線與表的先後次序無關
多表連線
select * from 表1
inner join 表2 on 連線條件
inner join 表3 on 連線條件
...
例子
select * from student a inner join sc b on a.sid = b.sid
inner join course c on b.cid = c.cid
inner join teacher d on c.tid = d.tid
order by a.sid, b.cid;
等價寫法:
select * from student a, sc b, course c, teacher d
where a.sid=b.sid and b.cid=c.cid and c.tid=d.tid;
左外多表連線:
select * from student a left join sc b on a.sid = b.sid
left join course c on b.cid = c.cid
left join teacher d on c.tid = d.tid
order by a.sid, b.cid;
注意:左外多表連線要全部使用left join,不能再出現inner join
效能上:連線的表越多,效能越低, 可以把連線查詢變成分多次查詢
自連線
一個表自己和自己連線
找到員工的姓名和上級的姓名
select a.empno,a.ename,a.mgr,b.empno,b.ename,b.mgr
from emp a left join emp b on a.mgr=b.empno;
以後經常用於樹狀結構的資料表示
陝西省
西安
雁塔區
高新區
咸陽
寶雞
id name parent_id
1 陝西省 null
2 西安 1
3 雁塔區 2
子查詢
把某個select結果當做一個值,或一張表做進一步的查詢
情況1:找具有最高工資的員工資訊(子查詢作為值)
select max(sal) from emp; // 5000
select * from emp where sal = (select max(sal) from emp);
把select max(sal) from emp當成了一個值,代入到主查詢當中,代入時需要在子查詢的兩邊加()
情況2: 獲取每個部門的平均工資和部門的名稱(子查詢作為表)
先查詢平均工資
(select deptno,avg(sal) from emp group by deptno) a
再把子查詢看做臨時表,與其它表做表連線
select * from (子查詢)a inner join dept b on a.deptno=b.deptno;
事務
DDL create alter drop truncate
DML insert update delete select
TCL start transaction, commit, rollback
start transaction 開始事務 (begin)
6.2 commit 提交事務
6.3 rollback 回滾事務
賬戶表account
ID balance(餘額)
1 50000.0
2 0.0
create table account (
id int primary key,
balance decimal(12,2) not null
);
insert into account(id,balance)values(1,50000.0),(2,0.0);
以下兩條sql必須作為一個整體執行, 要麼都成功,其中有一條失敗,前面成功的也得撤銷
update account set balance=balance+10000.0 where id=2; /*2號賬戶轉入10000元*/ 成功
update account set balance=balance-10000.0 where id=1; /*1號賬戶轉出10000元*/
所謂的事務,就是指一個事務內,多條sql語句是作為一個整體執行的。
一個事務內的多條sql是作為一個原子操作,不可以被分割。要麼都成功,要麼都不成功。
start TRANSACTION;
UPDATE
UPDATE
INSERT
DELETE
如果這個事務內多條sql全部成功 COMMIT(讓更改都生效)
如果這個事務內有sql失敗了,Rollback(讓更改都撤銷)
事務內所有更改,在結束之前,對於其它使用者來講都是不可見的。
事務commit提交時,這些更改才會真正生效,其它使用者才能看到你的更改。
事務執行中如果出現意外情況,這時候可以執行rollback,可以撤銷事務內所有更改,恢復到事務開始的時刻
commit 和rollback都意味著事務結束
事務有四大特性
ACID
A 原子性, 指事務內多條sql是作為一個整體執行
C 一致性, 事務開始前後,整個資料的狀態應當一致
I 隔離性, 指事務的隔離級別(未提交讀,提交讀,可重複讀,序列化讀)
1) 髒讀(讀取到了未提交的資料)
客戶1 客戶2
1 號賬戶餘額 10000.0
begin;
update 1 號賬戶餘額50000.0
select 1 號賬戶餘額 50000.0 髒讀
rollback;
select 1 號賬戶餘額 50000.0
2)避免髒讀現象, 將隔離級別升級為提交讀
查詢到的肯定是別人提交後的結果,提交讀下不會有髒讀, 但會有不可重複讀現象:
客戶1 更新 客戶2查詢
1 號賬戶餘額 10000.0
begin;
select ... 10000.0
begin;
update 1 號賬戶餘額50000.0;
commit;
select ... 50000.0
commit;
3) 為了避免不可重複和髒讀的現象,可以將隔離級別升級可重複讀(mysql預設隔離級別)
4) 幻讀 (可以將隔離級別提高為序列化讀,即可避免幻讀現象)
客戶1 新增 客戶2查詢
原始記錄是10條
begin begin;
查詢個數 10
insert 1
commit;
查詢個數 11
commit;
5) mysql的【可重複讀】隔離級別三種現象都可以避免
D 永續性, 事務中做的更改必須在事務結束後永久生效
增刪改查(insert update delete select)
CRUD c insert 插入
r select 查詢
u update 更新
d delete 刪除
DCL 資料控制語言 (瞭解)
grant 授權
revoke 回收許可權
create user 'user1'@'localhost' identified by 'user1';
登入之後執行use test3;
會報告 Access denied for user 'user1' 含義是使用者無權訪問.
使用root 給user1授權
grant all on test3.* to 'user1'@'localhost';
all 是代表所有許可權:select,insert,update,delete...
test3.* 是許可權的範圍:test3庫中所有物件
to 後面跟的是使用者
使用root回收許可權
revoke all on test3.* from 'user1'@'localhost';
更細的許可權分配
grant select on test3.student to 'user1'@'localhost'; /*只讓test1使用者能夠查詢test3.student表*/