1. 程式人生 > >java學習day21~23--MySQL(下)

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   總目錄
    
分組語法

(group by 後的列取值相同的會被分為一組)
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表*/