Oracle (03)分組子句.where條件 與 having條件的區別.子查詢.DDL.DML.資料的增刪改.TCL
昨天作業的回顧 **
-
顯示員工的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(+);
-
顯示每個員工的工資 和對應的工資級別 , 超出工資範圍的 也要顯示出來 :
工資表: 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(+); -
顯示每個部門的名稱 和 對應的地區的名稱, 沒有地區編號的也要顯示出來 :
前置條件:
因為業務需要, 增加了新的部門, 但是還沒有確定辦公的地點: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 **
- 按照部門的編號進行分組 , 統計每個部門的人數 !
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. 擴充套件表格 進行關聯
其實更多的時候 ,我們應儘量避免 表格被重構 !
在設計表格時, 應儘量的讓表格中的欄位完善 ! 並設定保留欄位 ,留待以後新增新的業務 !
修改表結構的兩種操作
-
刪除表中的欄位
格式: alter table 表名 drop column 列名;
練習:
建立上面案例的person15 和 user15 刪除person15中的age欄位
alter table person15 drop column age;
-
新增表中的欄位
格式: alter table 表名 add 欄位名 資料型別(長度);
練習:
向person15表中新增一個age欄位 長度為3 nummber型別
alter table person15 add age number(3);
DML 資料操作語言
對於資料庫中表格資料的 新增 , 刪除 修改
事務: 將一系列的dml語句 看作一個業務流程 , 看作一個整體, 統一進行處理, 要麼一起成功, 要麼一起失敗!
關於DML語句 , 所有的操作, 都需要提交事務 !
在Oracle資料庫中 事務的自動提交 是關閉的 !
提交事務 *****
commit;
事務回退 **
rollback;
INSERT語句 插入資料 *****
-
全欄位新增資料
格式: 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;
-
選擇欄位插入資料
格式: insert into 表名(插入的欄位列表) values(資料列表);
資料列表: 它資料順序, 與前面的欄位列表一致 !
注意: 也可以選擇全部欄位, 來進行資料的新增! 例如如下兩段語句 作用相同:
insert into user15 values(10003,‘gaosen’,‘hahahahaha’);
insert into user15(id,uname,upass) values(10003,‘gaosen’,‘hahahahaha’);練習:
向資料庫中的user15表格 插入一組資料- id:10006 , 帳號:dongfei
insert into user15(id,uname) values(10006,‘dongfei’); - id:10007 , 帳號:gaofan
insert into user15(id,uname) values(10007,‘gaofan’); - id:10008 , 帳號:gaosen
insert into user15(id,uname) values(10008,‘gaosen’); - id:10009 , 帳號:lukuan
insert into user15(id,uname) values(10009,‘lukuan’); - id:10010 , 帳號:yuhang
insert into user15(id,uname) values(10010,‘yuhang’);
– 不要忘記提交事務啊
commit;
- id:10006 , 帳號:dongfei
資料的刪除*****
格式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中事務是自動提交的
事務特性***
- 原子性: 同一個事務中的多個DML操作, 不可分割 要麼一起成功, 要麼一起失敗!
- 一致性:通一個事務的操作, 結果應保持一致!
- 隔離性:同一個事務的dml操作, 在沒有提交之前,對於其他的事務來說, 資料應是被隔離的 ,不可見的!
- 永續性:儲存的資料要保持一直存在!
如何開始一個事務
從上一次事務的結束之後, 進行的第一次dml操作, 就自動開啟了事務!
如何結束一個事務
結束事務有兩種不同的操作:
-
提交事務commit;
結束事務, 並將事務中所有的dml操作提交, 將資料的更改 新增 刪除 應用到資料庫中!
-
事務回退rollback;
也稱為事務的回滾 , 表示本次事務中 所有的dml操作 撤回 ! 不對資料庫中的資料 產生任何的更改!關於回退事務, 有兩種不同的操作:
-
一次回退所有dml操作 ***
使用格式: rollback; -
回退到某一個儲存點 瞭解
使用格式: 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;
-