/*
達內學習 Oracle day40 2013-10-28
*/
E,多表查詢
執行腳本 :進入sqlplus @路徑/腳本名
不寫多表查詢where 結果是笛卡爾積
把部門的名稱和對應地區名稱列出來
select d.name,r.name from s_dept d,s_region where region_id = r.id; 有別名以後就只能用別名
from 執行早於 where,where 早於 select
from where 多表查詢的另一種寫法
a 表 join b 表 on 連接條件
select d.name,r.name from s_dept d join s_region r on region_id = r.id;
select e.dept_id,d.name from s_emp e join s_dept d on e.dept_id = d.id;
>>> 多表查詢的關鍵就是找到兩張表的關係 用等號連接的叫等值連接
>>> 表達兩張表的連接條件 不是用等值 叫非等值連接
select s_emp.id,salary,salgrade.id from s_emp,salgrade where s_emp.salary >= salgrade.losal and s_emp.salary <= salgrade.hisal;
>>> 特殊的連接 領導是員工 員工不一定是領導
一張表中有多層含義的數據,就需要邏輯上把一張表看成多張表。
使用表的別名
select distinct m.id,m.first_name from s_emp e,s_emp m where e.manager_id = m.id;
----------------------------------------------------------
等值連接、非等值連接、自連接、這些連接 都符合 符合where條件的數據就被選中,不符合where條件的數據被過濾掉。 這個連接稱爲內連接
列出所有的部門名 和部門對應的地區名
s_dept:name,region_id;
s_region: id,name
select d.name,r.name from s_dept d,s_region r where r.id = d.region_id;
新增一個部門
insert into s_dept values(100,'test',NULL);
commit;
列出所有部門名 和對應的地區 名 沒有地區名的部門 也要顯示
外連接: 外連接的結果集,等於內連接的結果集,加上匹配不上的記錄, 一個也不能少
oracle 中使用(+) 把不匹配的記錄找回來;顯示(+)對面沒有匹配的數據。
select d.name,r.name from s_dept d,s_region where s.region_id = r.id(+);
列出員工的first_name和員工所在的部門名
select e.first_name, d.name from s_emp e,s_dept d where e.dept_id = d.id;
列出部門號不出現在部門表中的員工的名字 部門顯示 no dept
select first_name,nvl(name,'no dept') from s_emp e,s_dept d
where dept_id = d.id(+) and d.id is NULL;
------------------------------------------------------
找出所有的領導
select distinct e.first_name ,e.id from s_emp e,s_emp m where e.id = m.manager_id;
找出所有普通員工
select distinct m.id,m.first_name from s_emp e,s_emp m where
e.manager_id(+) = m.id and e.manager_id is null;
----------------------------------------------------
列出 員工的工資 和 工資所在的工資級別
select s_emp.id,salary,salgrade.id from s_emp,salgrade where salary between losal and hisal order by e.id;
update s_emp set salary = 12500 where id = 10 commit;
列出所有員工的工資和工資所在的工資級別
select e.id,salary,s.id from s_emp e,salgrade s where salary between losal(+) and hisal(+) order by e.id;
----------------------------------------------------------
SQL99規定了內外連接的標準
內連接
a 表 join b 表 on 連接條件 where 過濾條件
a 表 inner join b 表 on 連接條件 where 過濾條件
外連接:
a 表 left outer join b on 連接條件 where 過濾條件 ;左外連接
a right outer join b on 連接條件 where 過濾條件 ;右外連接
a full outer join b on 連接條件 where 過濾條件 ;全連接
select e.id,salary ,s.id from s_emp e left outer join salgrade
on salary between
要把哪張表的數據匹配出來,則讓哪張發起連接,左邊用left 右邊用right
全外連接:只是邏輯概念,全外連接的結果等於做外連接的結果集, 加上右外連接的結果集然後減去重複的記錄。
oracle不直接支持全連接, 不是通過兩端加(+)的方法,而是使用 union 合併兩個結果集,並排重,union all 合併兩個結果集。
F,組函數和分組
1,組函數的概念,對一組數據處理之後得到一個結果。
2,常見的組函數 count max min sum avg
3,統計s_emp表中有多少員工,員工的最高工資
select count(id),max(salary),min(salary) from s_emp;
4,統計s_emp 表中工資和工資的平均值
select sum(salary),sum(distinct salary),avg(salary),avg(distinct salary) from s_emp;
5,組函數 對 null 值的處理方式
組函數對 null 的處理方式是 當他不存在
分組:
1, 按照一定的標準把數據分成若干組
where 子句 group by 分組標準 ;位置在where之後
2,舉例
按照部門號 把員工分組 統計每個部門的人數
select dept_id ,count(id) from s_emp where 1= 1 group by dept_id; -- 單獨把空值分一組
按照部門號分組 統計幾每個部門的平均工資 和工資的和
select dept_id,avg(salary),sum(salary) from s_emp group by dept_id;
3, 按照部門號分組 統計每個部門的平均工資 和 工資的和 要求 工資的和大於3000的
select dept_id,avg(salary),sum(salary) from s_emp where 1=1 group by dept_id having sum(salary)>3000 order by sal;
-- 執行順序
from
where
group by
having
select
order by
4,按照部門號分組 統計每個部門的人數 列出大於兩個人的部門
select count(id) ,dept_id from s_emp where 1 =1 group by dept_id having count(id) >2;
5,按照部門號分組 統計每個部門的人數 列出大於2個人的部門,要求顯示部門名
select dept_id,count(e.id),name from s_emp e,s_dept d where e.dept_id = d.id group by dept_id,name having count(e.id) > 2;
在分組語句中select 後的字段要麼是分組標準,要麼是經過合適的組函數(max,min)處理過的。
select deptid,count(d.id),max(name) from s_emp e,s_dept d where e.dept_id = d.id group by dept_id, name having count(e.id) >2;
---------------------------------------------------------------------------------
G,子查詢
把一個查詢的結果 作爲另一個查詢的基礎
1,where 後
select id,first_name from s_emp where id in(select distinct manager_id from s_emp);
select id,first_name from s_emp where id not in(select distinct nvl(manager_id,0) from s_emp); --小心null
2,having 後
求平均工資大於42部門平均工資的部門 列出部門id,平均工資
select dept_id ,avg(salary) from s_emp group by dept_id having avg(salary) > (select avg(salary) from s_emp where dept_id = 42);
3,from 後
任何一條sql,都可以看成一張內存表
select id ,first_name,salary from s_emp;
---------------------------------------------------------------------
DDL
1,添加表 create table tab_name
(
eno number(7),
fname varchar2(10),
sname char(10) -- 最後一個不用逗號
);
2,刪除表
drop table tab_name;
3, 數據類型
number 數字類型
number(7) 最大是七位數
number(7,2)總共七位,小數點佔兩位,整數最大5位
number(5,-2) 有效共5位,小樹2位,整數7位 1234567 --------->1234500
char 定長字符串
varchar2(10)可變長度
4,日期類型
a. date 類型
和系統語言相關
NLS_LANG
系統默認的日期格式 ‘dd-MON-yy’(英語) ‘dd-n月-yy’(漢語)
b. select start
create table order_10019 (
oid varchar2(30),
oname varchar2(30),
omoney number,
odate date
);
c,打破時間的默認表現
to_char(par1,par2)
par1 要處理的日期類型的數據
par2 要表現的日期格式字符串
yyyy四位年 mm兩位月 dd兩位日 hh時(12)hh24(24) mi分 ss秒
mon 三位英文月 month月全拼 day星期幾 pm上午am 下午pm
select to_char (odate,'yyyy-mm-dd pm hh24:mi:ss day' from
系統默認放入的日期 十分秒信息都是0
d,如何放入帶十、分、秒 信息的日期
sysdate 可以直接獲得系統當前時間
to_date(par1,par2) 把日期字符串轉換成日期函數
par1 要轉換的日期字符串,
par2 根據日期字符串 指定日期格式
yyyy-mm-dd hh24:mi:ss
insert into table_name values('2008','test',2800,to_date('2008-9-9 20:09:8','yyyy-mm-dd hh24:mi:ss')) ;
select to_char (odate,'yyyy-mm-dd hh24:mi:ss pm day'from mytable where oid = 'bj2008' ;
inser into table_name values('aa','bbb',200,to_date('2012-12-20 23:56:56','yyyy-mm-dd hh24:mi:ss'));
f,日期的運算
如何按照天來調整
select to_char(sysdatem,'yyyy-mm-dd hh24:mi:ss')from dual;
select to_char (sysdate+1,'yyyy-mm-dd hh24:mi:ss') from dual; --調整到明天
select to_char (sysdate+1/24,'yyyy-mm-dd hh24:mi:ss') from dual;
---向後調整一小時
select to_char (sysdate+1/24/60/60,'yyyy-mm-dd hh24:mi:ss') from dual; --向後調整一秒
g,特殊調整
把時間向後調整一個月
add_months(日期,n) n是正數,向後調 n是負數向前提調
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(add_months(sysdate+3),'yyyy-mm-dd hh24:mi:ss') from dual;
last_day(日期) 得到日期的當月的最後一天的日期時間
next_day(日期,'星期幾') -- 下個星期幾的時間點
select next_day(sysdate,'monday') from dual;
select to_char(next_day(sysdate,'monday'),'yyyy-mm-dd hh24:mi:ss') from dual;
h.對日期的一些數學操作
months_between 兩個日期之間相差多少個月
round 對日期進行四捨五入
1,默認以天位單位進行四捨五入
select to_char(round(sysdate),'yyyy-mm-dd hh24:mi:ss') from dual;
2,指定四捨五入的單位
select to_char(round(sysdate,'dd'),'yyyy-mm-dd hh24:mi:ss') from dual; --以天爲單位,天后面是否進一
trunc 對日期進行截取
select to_char(trunc(sysdate,'mm'),'yyyy-mm-dd hh24:mi:ss') from dual; --以月爲單位,月後面的截斷,回到月初
給定一個日期 計算日期對應月的最後一天的最後一秒的時間點
select to_char(trunc(add_months(sysdate,1),'mm')-1/24/60/60,'yyyy-mm-dd hh24:mi:ss') from dual;
-------------------------------------------------------------------
DML
account
create table accountwang
(
aid number,
aname varchar2(30),
apasswd varchar2(30)
);
1,增加數據
a. insert into tab_name values(val1,val2);
b. 選擇一些字段進行插入,必須包含所有的非空字段
insert into tab_name(字段1,字段3) values(值1,值2);
如果一個字段沒有被選擇,則這個字段的值是null
2,刪除數據
delete from tab_name where
3, 更新數據
update tab_name set 字段名 = 值1,字段名 = 值2 where 條件