1. 程式人生 > >Oracle (03)分組子句.where條件 與 having條件的區別.子查詢.DDL.DML.資料的增刪改.TCL

Oracle (03)分組子句.where條件 與 having條件的區別.子查詢.DDL.DML.資料的增刪改.TCL

昨天作業的回顧 **

  1. 顯示員工的id,last_name,salary,部門名稱 , 要求, 把沒有部門編號的員工也給查詢到:

    前置條件:

    公司業務需要, 把員工編號為23 24 25 的員工 分配到了新的部門, 但是部門還未成立! 
    
    update s_emp set dept_id = null where id in(23,24,25);
    commit; 
    

    語句: select e.id,e.last_name,e.salary,d.name from s_emp e,s_dept d where e.dept_id=d.id(+);

  2. 顯示每個員工的工資 和對應的工資級別 , 超出工資範圍的 也要顯示出來 :

    工資表: salgrade

    前置條件:

    公司老闆覺得自己的工資太高了, 不合適 , 給自己降了-10000的工資 !  還讓自己的祕書 以身作則 , 一起降了工資 !
    
    update s_emp set salary=12500 where id=1;
    update s_emp set salary=500 where id=22;
    commit;
    

    如果在外連線時, 使用between 需要在最小範圍後面加入(+) , 最大範圍後面加入(+)

    salary between losal(+) and hisal(+)
    

    語句:
    select salary,grade,id,last_name from s_emp e,salgrade g where salary between losal(+) and hisal(+);

  3. 顯示每個部門的名稱 和 對應的地區的名稱, 沒有地區編號的也要顯示出來 :

    前置條件:
    因為業務需要, 增加了新的部門, 但是還沒有確定辦公的地點:

    insert into s_dept values(99,'chiji',null);
    commit;
    
    select d.name,r.name from s_dept d,s_region r where d.region_id = r.id(+);
    

group by having 分組子句 **

格式 … group by 分組標準欄位 having 分組過濾條件

分組標準欄位: 指的是查詢的結果, 按照什麼欄位進行分組 ,例如: s_emp表格按照部門編號分組!
分組過濾條件: 對分組後的資料, 進行過濾

分組查詢的限制:

在帶有分組的查詢語句中, select與from中間編寫的查詢欄位, 只能存在兩種:  

    -   分組標準欄位  (在一個組中唯一的)
    -   組函式的結果  (統計一個組中的某資料, 也是隻有一個的)

    上面這兩種可以查詢的資料型別,  都是為了保證分組後的查詢的列資料能一一對應!

分組查詢:

1.  按照部門的編號進行分組 , 統計每個部門的人數 !
select dept_id,count(*) from s_emp group by dept_id;

2.  按照部門的編號進行分組, 統計每個部門的最高薪資,要求,部門人數低於3的不顯示!
select dept_id,max(salary) from s_emp group by dept_id having count(*)>2;   

3.  按照部門編號進行分組, 顯示部門的編號, 平均薪資 , 平均薪資高於1400的才展示出來!
select dept_id,avg(salary) from s_emp group by dept_id having avg(salary)>1400; 

4.  統計每個部門中薪資大於1400的人數 , 低於2人的不顯示 !

select dept_id,count(*) from s_emp where salary>1400 group by dept_id having count(*)>1;

5.  按照 部門編號分組 , 顯示部門的人數, 部門的編號, 部門的名稱

select count(*),dept_id,max(name) from s_emp e,s_dept d where e.dept_id = d.id group by dept_id;        

分組過程中 容易出現的bug **

  1. 按照部門的編號進行分組 , 統計每個部門的人數 !
    select id from s_emp group by dept_id;
    select id,count(*) from s_emp group by dept_id;
    select dept_id,id from s_emp group by dept_id;

上述三行程式碼都出現了錯誤:

ORA-00979: 不是 GROUP BY 表示式
00979. 00000 -  "not a GROUP BY expression"

原因在於, 資料的結果 , 沒有一一對應!

select與from中間編寫的查詢欄位, 只能存在兩種:

    -   分組標準欄位  (在一個組中唯一的)
    -   組函式的結果  (統計一個組中的某資料, 也是隻有一個的)

where條件 與 having條件的區別 *****

  • where 條件 對錶格中所有的資料 進行過濾!
  • having 條件 是對於分組後的組中資料進行過濾!
  • where條件執行在having之前

select語句 *****

完整格式:

select 欄位 from 表名/檢視 [where條件] [group by 分組標準欄位 [having 過濾條件]] [order by 排序欄位 排序規則]

執行順序

from--> where條件 -->group by -->having條件-->select -->order by

子查詢 ***

概念: 把一個select 語句的查詢結果, 當作另一個select 語句的一部分 !

子查詢的子語句, 使用小括號括住!

子查詢的語句, 可以出現的位置有三個:

1.  應用到from 之後
2.  應用到where之後
3.  應用到having之後

應用到where條件之後

把一個select的結果, 當前where後的篩選條件 !

案例: 查詢id最大的員工資訊(id,salary,last_name)

步驟1.    先得到最大的id
select max(id) from s_emp;

步驟2.    根據最大的id 進行資訊的查詢
select id,salary,last_name from s_emp where id=(select max(id) from s_emp);

練習:查詢部門編號最大的部門員工資訊(id,salary,last_name) !

步驟1. 得到最大的部門編號
select max(dept_id) from s_emp;

步驟2. 根據得到的部門編號進行查詢
select id,salary,last_name from s_emp where dept_id=(select max(dept_id) from s_emp);

練習: 查詢公司所有的領導
1. 先查尋到公司所有的領導id(manager_id) , 並去重
select distinct manager_id from s_emp;
select distinct manager_id from s_emp where manager_id is not null;

2.  根據上面查詢到的領導id , 通過in去匹配公司的所有領導
    select id,last_name,salary from s_emp where id in(select distinct manager_id from s_emp where manager_id is not null);

練習: 查詢公司所有的普通員工
1. 先查尋到公司所有的領導id(manager_id) , 並去重
select distinct manager_id from s_emp where manager_id is not null;

2.  根據上面查詢到的領導id,通過not in匹配公司所有的普通員工!
    select id,last_name,salary from s_emp where id not in(select distinct manager_id from s_emp where manager_id is not null);

應用到having之後

把一個select語句的結果, 當作另一個分組查詢語句 分組後的組過濾條件!

尋找部門平均薪資 大於 32號部門平均薪資的 部門資訊 : 顯示部門編號 和 平均薪資!

步驟1.    先找出32號部門的平均薪資
select avg(salary) from s_emp where dept_id=32;

步驟2.  根據部門進行分組查詢, 過濾條件為: 計算後部門的平均薪資大於上面 查詢的結果

select dept_id,avg(salary) from s_emp group by dept_id having avg(salary)>(select avg(salary) from s_emp where dept_id=32);

應用到from之後

每一個select語句的結果, 就類似存在與記憶體中的一個表.

把select語句要查詢的表格 , 更改為另一條查詢語句, 即可!

案例: 查詢員工的id,last_name,salary,條件為薪資大於1400

select id,last_name,salary from s_emp where salary>1400;

根據上次查詢的結果, 使用子查詢更快的獲取員工id為5的員工資訊id,last_name,salary,

select * from (select id,last_name,salary from s_emp where salary>1400) where id=5;

DDL (資料定義語句)
建立表 *****

資料型別:

-   number:     數字型別
-   varchar2:   變長字串 ,編寫為varchar也可以使用, 會自動轉換為varchar2
-   date:       日期型別

建立表格的格式:

create table 表名(
欄位1 資料型別(長度),
欄位2 資料型別(長度),

欄位n 資料型別(長度)
);

注意: 關於number型別長度的編寫,如下所示:

id number(2,3): 2表示整數長度為2,最大能儲存99 , 3 表示小數點後長度為3位

練習:

建立一個表格person15
欄位: 
    1.  id 長度為5 , 小數點後允許0位的number型別資料
    2.  name 長度為10的varchar2型別的資料
    3.  age長度為3,小數點後允許0位的number型別資料

create table person15(
id number(5,0),
name varchar2(10),
age number(3,0)
);

練習:

建立一個表格
表名為: user15
欄位:
    1.  id 長度為5的number型別
    2.  uname 長度為32的varchar2型別
    3.  upass 長度為32的varchar2型別

create table user15(
    id number(5),
    uname varchar2(32),
    upass varchar2(32)
);
id uname  upass
1   aaa   bbb


create table userPhoneNumber(
    userid number(5),
    phoneNumber number(11)
);
userid   phoneNumber
1        13843838438

刪除一個表格 *****

格式: drop table 表名;

注意: 在刪除一個表格時, 如果此表格與外部其他表格不存在任何資料和格式上的關聯 , 則會立即被刪除

在表格刪除時, 同時表格中的資料也會被清空!

練習:

    刪除你的person表和user15表

語句: drop table person15;
drop table user15;

修改表結構 (瞭解)

很耗費系統的效能:

修改表結構的流程: 
1.  先將表格中的資料備份
2.  將表格清空, 修改結構
3.  將備份的資料 依次插入

如果表格在建立時就有缺陷怎麼辦?

兩種方案:  

    1.  更改 
    2.  擴充套件表格 進行關聯

其實更多的時候 ,我們應儘量避免 表格被重構 !

在設計表格時, 應儘量的讓表格中的欄位完善 !  並設定保留欄位 ,留待以後新增新的業務 !

修改表結構的兩種操作

  1. 刪除表中的欄位

    格式: alter table 表名 drop column 列名;

    練習:

    建立上面案例的person15 和 user15
    
    刪除person15中的age欄位
    

    alter table person15 drop column age;

  2. 新增表中的欄位

    格式: alter table 表名 add 欄位名 資料型別(長度);

    練習:

    向person15表中新增一個age欄位 長度為3  nummber型別
    

    alter table person15 add age number(3);

DML 資料操作語言

對於資料庫中表格資料的 新增 , 刪除 修改

事務: 將一系列的dml語句 看作一個業務流程 , 看作一個整體, 統一進行處理, 要麼一起成功, 要麼一起失敗!

關於DML語句 , 所有的操作, 都需要提交事務 !

在Oracle資料庫中 事務的自動提交 是關閉的 !

提交事務 *****

commit;

事務回退 **

rollback;

INSERT語句 插入資料 *****

  1. 全欄位新增資料

    格式: insert into 表名 values(資料列表);

    注意: 資料列表 , 表示的是要插入的資料列表 ,傳入的順序, 按照欄位建立的順序來插入 , 多個值之間使用逗號隔開

    資料列表中的順序, 是按照建立時欄位的順序插入的
    但是對於表格的修改(增加刪除欄位), 會影響到欄位的順序 !
    

練習:

向user15表格中註冊一組使用者: 

1.  id:10001 , 帳號:dongfei 密碼:ytdhytytwj
insert into user15 values(10001,'dongfei','ytdhytytwj');
2.  id:10002 , 帳號:gaofan  密碼:lzlhlzlh
insert into user15 values(10002,'gaofan','lzlhlzlh');
3.  id:10003 , 帳號:gaosen  密碼:hahahahaha
insert into user15 values(10003,'gaosen','hahahahaha');
4.  id:10004 , 帳號:lukuan  密碼:wdjzdbshjsa
insert into user15 values(10004,'lukuan','wdjzdbshjsa');
5.  id:10005 , 帳號:yuhang  密碼:dgnmadgnl
insert into user15 values(10005,'yuhang','dgnmadgnl');
-- 不要忘記提交事務啊
commit;
  1. 選擇欄位插入資料

    格式: insert into 表名(插入的欄位列表) values(資料列表);

    資料列表: 它資料順序, 與前面的欄位列表一致 !

    注意: 也可以選擇全部欄位, 來進行資料的新增! 例如如下兩段語句 作用相同:

    insert into user15 values(10003,‘gaosen’,‘hahahahaha’);
    insert into user15(id,uname,upass) values(10003,‘gaosen’,‘hahahahaha’);

    練習:
    向資料庫中的user15表格 插入一組資料

    1. id:10006 , 帳號:dongfei
      insert into user15(id,uname) values(10006,‘dongfei’);
    2. id:10007 , 帳號:gaofan
      insert into user15(id,uname) values(10007,‘gaofan’);
    3. id:10008 , 帳號:gaosen
      insert into user15(id,uname) values(10008,‘gaosen’);
    4. id:10009 , 帳號:lukuan
      insert into user15(id,uname) values(10009,‘lukuan’);
    5. id:10010 , 帳號:yuhang
      insert into user15(id,uname) values(10010,‘yuhang’);
      – 不要忘記提交事務啊
      commit;

資料的刪除*****

格式1: 一次刪除一個表格中的所有資料行

格式: delete from 表名;

練習: 刪除user15表格中的所有資料

delete from user15;

格式2: 根據where條件, 刪除匹配的資料行

格式: delete from 表名 where 條件;

練習: user15表格中id為10001,10002,10003的使用者 ,要求使用1行語句完成!
delete from user15 where id<10004;

注意:

where 條件的使用 與 select語句中基本一致!

資料的修改*****

格式: update 表名 set 欄位名1=欄位值1,欄位名2=欄位值2 … 欄位名n=欄位值n [where條件];

如果在修改時, 不新增where條件, 則表示修改表中的所有資料 !

新增where條件後, 表示修改匹配條件的資料行!

案例: 修改user15表格中 id為10001的使用者的 密碼為 123456

update user15 set upass='123456' where id=10001;
 commit;

練習: 修改user15表格中的 帳號為gaosen的使用者的資訊, 修改密碼(upass)為234567
update user15 set upass=‘123456’ where uname=‘gaosen’;
commit;

練習: 修改user15表格中的 所有使用者的帳號(uname)為******
update user15 set uname=’******’;
commit;

TCL事務控制語句

事務: 將一系列的dml語句 看作一個業務流程 , 看作一個整體, 統一進行處理, 要麼一起成功, 要麼一起失敗!

關於DML語句 , 所有的操作, 都需要提交事務 !

在Oracle資料庫中 事務的自動提交 是關閉的 !

在mysql中 事務是自動提交的 ! 在JDBC中事務是自動提交的

事務特性***

  1. 原子性: 同一個事務中的多個DML操作, 不可分割 要麼一起成功, 要麼一起失敗!
  2. 一致性:通一個事務的操作, 結果應保持一致!
  3. 隔離性:同一個事務的dml操作, 在沒有提交之前,對於其他的事務來說, 資料應是被隔離的 ,不可見的!
  4. 永續性:儲存的資料要保持一直存在!

如何開始一個事務

從上一次事務的結束之後, 進行的第一次dml操作, 就自動開啟了事務!

如何結束一個事務

結束事務有兩種不同的操作:

  1. 提交事務commit;

    結束事務, 並將事務中所有的dml操作提交, 將資料的更改 新增 刪除 應用到資料庫中!

  2. 事務回退rollback;
    也稱為事務的回滾 , 表示本次事務中 所有的dml操作 撤回 ! 不對資料庫中的資料 產生任何的更改!

    關於回退事務, 有兩種不同的操作:

    1. 一次回退所有dml操作 ***
      使用格式: rollback;

    2. 回退到某一個儲存點 瞭解
      使用格式: rollback to 儲存點名稱;

    新增一個儲存在: 在任意的dml語句後, 加入: savepoint 名稱; 即可完成儲存點的新增!

    案例:

    對user15表格進行資料的新增: 
    
     --1.   id:10006 , 帳號:dongfei 
    insert into user15(id,uname) values(10006,'dongfei');
    --2.    id:10007 , 帳號:gaofan  
        insert into user15(id,uname) values(10007,'gaofan');
    commit;
    --3.    id:10008 , 帳號:gaosen 
        insert into user15(id,uname) values(10008,'gaosen');
    --4.    id:10009 , 帳號:lukuan  
        insert into user15(id,uname) values(10009,'lukuan');
    --5.    id:10010 , 帳號:yuhang
        insert into user15(id,uname) values(10010,'yuhang');  
    -- 不要忘記提交事務啊
    rollback;
    

    新增儲存點的案例:

    對於person15表格進行資料的插入
    
    insert into person15 values(1,'董飛',8);
    insert into person15 values(2,'董飛',18);
    savepoint a;
    insert into person15 values(3,'董飛',28);
    savepoint b;
    insert into person15 values(4,'董飛',38);
    savepoint c;
    insert into person15 values(5,'董飛',8);
    savepoint d;
    rollback b;
    commit;