41,數據庫(03)

/*
 達內學習 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 條件

發佈了72 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章