oracle數據庫02

馬果老師整理

 

oracle數據庫中,主要包含6種類型的運算符

  • 賦值運算符  =
  • 連接運算符 ||                           
  • 算術運算符 + - * /
  • 邏輯運算符  or  and
  • 關係運算符  > >= < <=  =  !=  <>  in  not in between
  • 聯合運算符  union     union all   intersect

賦值運算符  =

  • update 表 set 字段=值 

連接運算符 ||   

作用:通過||可以把指定內容,拼接成一個字符串

  • select name||'的成績是'||score 信息 from inf;

算術運算符 + - * /

  • update 表 set 字段值=字段值+10
  • select name,score-20 from inf;

邏輯運算符  or  and

OR:或者

  • select * from info2 where class='s1t80' or class='s1t82'

and:並且

  • select * from info2 where class='s1t80' and gender='男';

關係運算符  > >= < <=  =  !=  <>  in  not in between

select * from info2 where score>=90;
select * from info2 where class!='s1t80';
select * from info2 where class<>'s1t80';
select * from info2 where class in('s1t80','s1t82');
select * from info2 where class not in('s1t80','s1t82');
select * from info2 where score between 90 and 100

問題1: -- select * from info2 where score between 100 and 90

  • 這樣,查詢,是沒有結果的,區間查詢時,小的值要在前,大的值要在後

問題2:--日期類型的數據可不可進行區間查詢?

  • select * from info2 where bir between date'1985-01-01' and date'1990-12-31';
  • 日期類型的數據,可以進行區間查詢

聯合運算符  union     union all   intersect

union:聯合兩張表的數據,兩張表相同部份的數據,只顯示1次,不同的部份,則分別顯示

   select * from one
          union
   select * from two;

union all:聯合兩張表的數據,先顯示第一張表的全部數據,然後再顯示第二張表的全部數據,不論數據是否相同,都會顯示


    select * from one
          union all
   select * from two;

intersect:顯示兩張表的交集(只顯示兩張表都有的數據)

    select * from one
         intersect
   select * from two;

模糊查詢  

  •  %: 通配任意長度的任意字符
  •    _: 通配一個任意字符
select * from info2 where name like '%柳%'
select * from info2 where name like '柳%'
select * from info2 where name like '柳_'

範圍查詢

select * from info2 where score between 60 and 100;
select * from info2 where score >=60 and score<=100;

select * from info2 where class in('s1t80','s1t81');
select * from info2 where class not in('s1t80','s1t81');

分組查詢  group by 

select class 班級名稱   from info2 group by class;  --分組查詢

select class 班級名稱, count(*) 人數 from info2 group by class; --先分組再聚合 

要求,查詢班級人數爲5人,或者是5人以上的班級,並且按人數從多至少排序

  • 在分組以後,要設置查詢條件,使用having
  • select class 班級名稱, count(*) 人數 from info2 group by class having count(*)>=5 order by count(*) desc;

聚合查詢 (數據庫中有幾個聚合函數)

  • sum:總和
  • count:個數
  • avg:平均值
  • max:最大值
  • min:最小值

如果查詢語句中,同時包含:  order by ,  group by ,having ,where

它們出現的正常順序應該是:select ......from 表  where .....group by ....having....order by     

oracle中的多表連接 (重點)

在實際工作中,不論任何操作,都是對數據庫執行:增刪改查。其中,最爲繁的就是:查詢

在實際開發過程中,多表聯合查詢很常見:

oracle多表連接查詢的方式有:

自連接:natural join

內連接:inner join

外連接:

  • left outer join 左外連接
  • right outer join 右外連接
  • full outer join  完全外連接

子查詢

自連接: natural join

特點:

  • 兩張表如果要進行自連接,前提條件是,兩張表中,一定要有相同的字段名,纔可以建立關聯
  • 如果進行自連接,兩張表無需設置關聯條件
  • 如果兩張表中,沒有相同的字段名,也在採用自連接,將會產生: 迪卡爾積

學生表

drop table stu;
create table stu
(
       stuId number(11) primary key,--學生編號
       stuName varchar2(20) --學生名稱
)           
insert into stu values(1,'張三');
insert into stu values(2,'李四');
insert into stu values(3,'王五');

成績表

create table score
(
       sid number(11) primary key,--成績編號
       stuId number(11),--哪一個學生的成績
       score number(11) --分數
)
insert into score values(1,1,90);
insert into score values(2,3,78);

自連接

  • select * from stu natural join score;

內連接   inner join

 特點:

  • 內連接的兩張表,不需要有相同的字段名,只要設置關聯條件即可
  • 兩張表進行內連接,至少要設置一個關聯條件。N張表進行內連接,至少要設置N-1個關聯條件
  • 內連接的兩張表是平級關係,必須兩張表都存在的數據,纔可以建立關係      

內連接的標準語法:

採用inner join連接兩張表,採用on設置關聯條件

  • select a.stuid,a.stuName,b.score from stu a inner join score b on(a.stuId=b.stuId);

內連接的另一種寫法:

採用where設置連接條件 ,可以省略inner join關鍵字      

  • select a.stuid,a.stuName,b.score from stu a,score b where a.stuid=b.stuid;

只要會3張的內連接,再多表的內連接,原理一樣

********************三張表的內連接       

create table stu
(
       stuId number(11) primary key,--學生編號
       stuName varchar2(20) --學生名稱
)           
insert into stu values(1,'張三');
insert into stu values(2,'李四');
insert into stu values(3,'王五');

--課程表
create table course
(
   cid number(11) primary key,--課程編號
   cname varchar2(20)--課程名稱
)
insert into course values(1,'語文');
insert into course values(2,'數學');
insert into course values(3,'英語');

--成績表
drop table score;
create table score
(
       sid number(11) primary key,--成績編號
       stuId number(11),--哪一個學生的成績
       cid number(11),--哪一門課程
       score number(11) --分數
)
insert into score values(1,1,3,90);
insert into score values(2,3,1,75);
select a.stuid 學生編號,a.stuName 學生名稱,b.cname 課程名稱,c.score 分數 from stu a,course b,score c where a.stuid=c.stuid and b.cid=c.cid;

外連接 (包含三種類型的外連接)

特點:

  • 外連接的兩張表,分爲主表與副表,主表的數據必須全部顯示,副表的數據只有對應上主表纔可以顯示

左外連接   left outer join

               --連接符左側的表爲主表,右側爲副表
右外連接   right out join
               --連接符右側的表爲主表,左側爲副表
完全外連接 full outer join

內連接與外連接的區別是什麼(面試題)?

  • 內連接的兩張表是平級關係,必須兩張表都存在的數據,纔可以建立關係
  • 外連接的兩張表,分爲主表與副表,主表的數據必須全部顯示,副表的數據只有對應上主表纔可以顯示      

左外連接(右外連接原理一樣)                

顯示所有參加考試的學生,及成績  (左外連接)

  • select a.stuid,a.stuname,b.score from stu a left outer join score b on(a.stuid=b.stuid);

左外連接的簡化寫法

  • select a.stuid,a.stuname,b.score from stu a,score b where a.stuid=b.stuid(+);

注意:有+號的是副表,沒有+的是主表
           
--右外連接           

  • select a.stuid,a.stuname,b.score from stu a right outer join score b on(a.stuid=b.stuid);

--右外連接的簡化寫法            

  • select a.stuid,a.stuname,b.score from stu a,score b where a.stuid(+)=b.stuid;           

完全外連接:full outer join

  • 表示:連接的兩張表,都是主表,所有數據都要顯示
  • select a.stuid,a.stuname,b.score from stu a full outer join score b on(a.stuid=b.stuid);

總結

左外連接

select ...from 表1 left outer join 表2 on(表1.字段=表2.字段);         
           
select ...from 表1,表2 where 表1.字段=表2.字段(+); 

右外連接

select ...from 表1 right outer join 表2 on(表1.字段=表2.字段);         
           
select ...from 表1,表2 where 表1.字段(+)=表2.字段; 

完全外連接

select ...from 表1 full outer join 表2 on(表1.字段=表2.字段);  

子查詢:

問題1:什麼叫子查詢?           

  • 在一條查詢語句中,包含多個select子句,這樣的查詢語句,就稱爲:子查詢語句

問題2:子查詢語句,可以出現在查詢語句中的什麼位置?

子查詢語句,可以出現在查詢語句中任何位置

  • 可以將查詢的結果作爲要顯示的字段
  • 可以將查詢的結果作爲條件
  • 可以將查詢的結果作爲表來繼續查詢
       
       select  (select * from 表) from 表;---------------把子查詢的結果,作爲要顯示的字段
       
       select * from 表 where 字段 in(select * from 表)---------把子查詢的結果,作爲條件過濾
       
       select * from (select * from 表 ) ---------------把子查詢的結果,當作爲表來繼續查詢 

查詢沒有參加考試的學生,把子查詢的結果,作爲條件過濾

  • select * from stu where stuid not in (select stuid from score)

問題:在執行子查詢時,先執行括號內的語句?還是先執行括號外的語句

  • 先執行括號內的語句,再執行括號外的語句

oracle中的分頁

把子結果,當前數據表,來繼續查詢

例如:oracle中的分頁

注意:在oracle中執行分頁,需要使用rownum(僞列),配合子查詢語句使用

查詢前3條數據

  • select f.*,rownum r from info2 f where rownum<=3;

假設,當前每1頁顯示3條數據,當前是第1頁

  • select f.*,rownum r from info2 f where rownum<=3;

假設,當前每1頁顯示3條數據,當前是第2頁

  • 找到前6條數據:select f.*,rownum r from info2 f where rownum<=6
  • 排除第1頁,已經顯示過的3個僞列:select * from (select f.*,rownum r from info2 f where rownum<=12) k  where k.r>9

分頁語法:

select * from (select f.*,rownum r from info2 f where rownum<=當前頁*每頁顯示條數據) k where k.r>(當前頁-1)*每一頁顯示的條數據

按學生的成績顯示,查詢分數最高的前三名,oracle是先查詢,再生成僞列,再排序                                             

  • select * from (select f.* from info2 f order by score desc) k where rownum<=3;

按學生的成績顯示,查詢分數最高的4-6名

  • select * from (select rownum r,k.* from (select f.* from info2 f order by score desc) k where rownum<=6) t where t.r>3;

oracle中的函數,主要有下面幾種類型:

  • 日期函數
  • 字符函數
  • 數學函數
  • 轉換函數
  • 分析函數
  • 聚合函數(avg,sum,count,max,min)
  • 分組函數(group by)
  • 排序函數(order by)

在講解函數之前,看一下,oracle中一張特殊的表 dual

  • dual:虛表-------------這張表本身並不存在,它的意義是爲了保證語法的完整

日期函數:

sysdate---獲得系統時間

  • select sysdate from dual; --系統函數可以基於虛表查詢,也可以基於任何一張表查詢

add_months

作用:在指定日期上,加上一個指定的月份,產生一個新的日期

  • select  sysdate 生產日期,add_months(sysdate,6) 過期日期 from dual;
  • select add_months(date'2019-01-15',6) from dual;

months_between

作用:計算兩個日期之間,間隔的月份     

注意:在實際開發中,數據表中絕對不會有年齡字段 (年齡一般是根據出生日期自動進行計算)

  • select months_between(date'2020-06-15',date'2019-06-15')/12 年 from dual;
  • select floor(months_between(sysdate,date'2019-06-15')/12) 年 from dual;

floor(浮點數):得到一個小於當前浮點數的最大整數

  • select name,bir,floor(months_between(sysdate,bir)/12) 年齡 from info2;                                                              
  • select * from info2;

last_day

作用:得到指定日期這一個月的最後一天是哪一個日期

  • select last_day(date'2020-02-01') from dual;

next_day

作用,得到從指定日期開始,下一個星期幾是哪一個日期

注意:在日期格式中的星期:

  • 1--------------代表星期天
  • 2--------------代表星期一
  • 7--------------代表星期六                    
  • select next_day(sysdate,2) from dual;

trunc

作用:截斷日期格式,去掉時分秒,只保留年月日

  • select trunc(sysdate) from dual;     

extract   

作用:獲得一個日期格式中,指定部份的值  

  • select extract(year from sysdate) from dual;       --獲得年份   
  • select extract(month from sysdate) from dual;       --獲得月份  
  • select extract(day from sysdate) from dual;       --獲得天

字符函數

length() ----獲得字符串的長度(空格也要計算長度)

  select length('abc ') from dual;
  select length('中國') from dual; --在計算長度時,只要是一個字符,就只算一個長度
  select name,length(name) from info2;

ltrim,rtrim,trim                   

  • ltrim()---去掉字符串左側的空格
  • rtrim()---去掉字符串右側的空格
  • trim()----去掉字符串兩邊的空格(不能去掉中間的空格)
select ltrim('      abc') from dual;

upper(),lower()   

 

  • upper()----------將小寫字母轉換成大寫字母
  • lower()----------將大寫字母轉換成小寫字母
       select upper('abcABC') from dual;
       select lower('abcABC') from dual;

substr()

  • 作用:截斷字符串
substr(字符內容,開始位置,截取長度);    
       
select substr('你好,李小龍!',4,3) from dual;
select substr('18627198028',4,5) from dual;   

replace()

  • 作用:將字符內容中的指定內容,用新的內容進行替換

 

replace(字符內容,指定字符,新字符); 
       
select replace('你好,張三丰','張三丰','李小龍') from dual;    

lpad(),rpad()

  • lpad():從字符內容中,截取指定長度的內容,如果內容的長度不夠,就左至右填充指定的符號                                                                
        select lpad('abc12345def',5,'*') from dual;  --abc12                                                                                      
        select lpad('ab',5,'*') from dual;  -- ***ab

 

  • rpad():從字符內容中,截取指定長度的內容,如果內容的長度不夠,就右至左填充指定的符號                                                 
        select rpad('abc12345def',5,'*') from dual;  --abc12                                                                                      
        select rpad('ab',5,'*') from dual;  -- ab***

 

create table inf3
(
    id number(11) primary key,
    name varchar2(20),
    tel varchar2(20)
)
--1、顯示姓名五個字符或以上,電話號碼以13開始的學生信息
select * from inf3 where tel like '13%' and length(name)>=5;

--2、顯示姓名中任意位置包含c的學生信息,並且電話號碼中間五位用*號替換
select name,tel,replace(tel,substr(tel,4,5),'*****') from inf3 where name like '%c%';


--3、顯示所有學生信息,姓名只顯示第一位,後面幾位用5個*替換,電話號碼中間五位用*替換
    例如:
                      name         tel
    本身數據        jack         13985141027    
                  christina    13982727341 
    -----------------------------
        顯示爲      j*****      139*****027    
                      c*****      139*****341    
                  
select rpad(substr(name,1,1),6,'*'), replace(tel,substr(tel,4,5),'*****') from inf3 

數學函數

abs()-------求絕對值

select abs(-23) from dual;

sqrt()-------計算一個數的平方根

select sqrt(2) from dual;    

power(k,n)---------計算k的n次冪

select power(2,3) from dual;

floor(浮點數);-------得到一個小於當前浮點數的最大整數

select floor(12.34) from dual;   

round(浮點數,2);-----對當前浮點數,四捨五入,小數點後,保留2位有效位數

      select round(123.45678,2) from dual;    

random()------- 生成隨機數

  • dbms: database management system(數據庫管理系統)
select dbms_random.value from dual;    --生成一個隨機浮點數(範圍介於0-1之間)                                                           
select dbms_random.value(0,100) from dual;--產生一個0-100之間的隨機浮點數  
          
select trunc(dbms_random.value(0,100)) from dual;--產生一個0-100之間的隨機整數     
          
select sys_guid() from dual;---產生一個隨機字符串        

sign(num)---判斷num的值是正數,負數,還是零

它的結果只有三種:                 

  • 1---------表示當前數是正數
  • -1--------表示當前數是負數
  • 0---------表示當前數是零                                                                                                             
select sign(0) from dual;   

該函數,單獨使用,意義不在。它主要是結合decode函數一起使用
     
sign函數,結合decode函數,可以在語句中,進行條件判斷,可以形成下列效果
     
decode+sign可以形成:

  • if...else
  • if...else if...else

decode函數的語法:

語法1:  decode(表達式,值,內容1,內容2)   --if..else      

  • 如果表達式的結果與值是相等的,則執行內容1,否則,執行內容2 
  • select name,score,decode(sign(score-60),-1,'考覈不通過','考覈通過') 考覈結果 from info2;

 語法2: decode(表達式,值1,內容1,值2,內容2....)    -------多重if

  • 如果表達式的結果與值1相等,則執行內容1,如果與值2相等,則執行內容2                                                                                                                                                                                                                                                                     
create table user_level
(
       id number(11) primary key,
       name varchar2(20),
       user_level char(1)
)             
insert into user_level values(1,'jack','B');
insert into user_level values(2,'andy','A');
insert into user_level values(3,'chris','B');
insert into user_level values(4,'austin','E');
select id,name,user_level,decode(user_level,'A','一級用戶','B','二級用戶','C','三級用戶') 等級 from user_level;

 在oracle語法中,在語句中,進行邏輯判斷:

  • decode()
  • case..when -----------這個語句,在mysql,oracle中用法一樣

用法1: ---用法類似於java中的switch (主要用於精確值的匹配)
                 
                       

case 表達式
    when  值1  then 代碼1;
    when  值2  then 代碼2;
    .....
    else 
        代碼3     
    end 別名;       
           
          select id,name,
                 case user_level 
                      when 'A' then '一級用戶'
                      when 'B' then '二級用戶'                                                                                
                      when 'C' then '三級用戶'                                                                                                      
                      else '無法確定用戶等級'
                 end 用戶等級 from user_level; 

用法2:---------這種方式,適合用於範圍判斷
               

                         case 
                              when 表達式  then 代碼1;                                                  
                              when 表達式  then 代碼2; 
                              when 表達式  then 代碼3;
                              else 代碼4;
                         end 別名;                                                                  
                  
                  
                  select name,score,
                         case
                             when score>=90 then '優秀'
                             when score>=80 then '良好'                             
                             when score>=60 then '合格'
                             else '不合格'                             
                         end 考覈結果 from info2;   

轉換函數:

to_date()

  • 作用:轉換日期格式      
                                 
            /*
              注意,在oracle數據庫中,日期格式的佔位符不區分大小寫
               yyyy:年
               mm:月
               dd:天
               hh:小時
               mi:分鐘
               ss:秒
            */    
  • 語法1:  to_date('2011-12-11','yyyy-mm-dd');
  • 語法2:  to_date('2011-12-11 10:22:33','yyyy-mm-dd hh:mi:ss');    
    默認情況下,oracle數據庫中的小時,採用的是12小時制,如果要採用24小時制,需要寫成如下格式
  • 語法3:  to_date('2011-12-11 10:22:33','yyyy-mm-dd hh24:mi:ss');     

to_char()

  • 將內容轉換成指定字符格式
  • select to_char(123) from dual;  

作用1:將數值類型,轉換成字符類型
           

select name,score,
    case
        when score>=60 then to_char(score)
        else '考覈不合格'
    end 考覈結果
from info2;

用法2:獲得一個日期格式中,指定部份的值

            select to_char(sysdate,'yyyy') from dual;
            select to_char(sysdate,'mm') from dual;
            select to_char(sysdate,'dd') from dual;
            select to_char(sysdate,'hh24') from dual;
            select to_char(sysdate,'mi') from dual;
            select to_char(sysdate,'ss') from dual;

日期類型的數據,添加有如下方式:

方式1:

       insert into test9 values(1,'jack',date'2019-10-02');
       ----這種添加日期的方式,只能添加年月日,不能帶時分秒

方式2:

       insert into test9 values(2,'andy',sysdate);
       ----這種是添加系統時間,包含年月日,以及時分秒

方式3:自己添加指定的日期格式,既包含年月日,也包含時分秒 --(此時必須使用轉換日期函數to_date)           

       insert into test9 values(3,'chris',to_date('2019-01-02','yyyy-mm-dd'));
       insert into test9 values(4,'houston',to_date('2019-01-04 10:12:15','yyyy-mm-dd hh:mi:ss'));
       insert into test9 values(5,'austin',to_date('2019-01-06 13:12:15','yyyy-mm-dd hh24:mi:ss'));
       select * from test9;     

分析函數 (這種函數,主要在數據統計、數據分析時使用)

要求:查詢每一個員工的工資,按工資降序排列,並且生成一個名次

  • select ename,sal,rownum 名次 from emp order by sal desc;

結果不正確,造成錯誤結果的原因是: 語句的執行順序是:

  1. 先執行查詢
  2. 再生成僞列
  3. 最後排序       

解決方案1:子查詢   

  • select k.*,rownum  from (select ename,sal from emp order by sal desc) k                                

解決方案2:使用分析函數

  • 可以先排序,再生成一組連續的序號
  • row_number()  over(order by 字段名)

select ename,deptno,sal,row_number() over(order by sal desc) from emp;
         
既然子查詢可以實現,爲什麼還要使用分析函數?

  • 原因:在進行統計、彙總的查詢時,一些簡單的統計查詢,可以使用可以使用子查詢實現,但稍微複雜一些的統

---例如:要統計每一個部門中,每一個員工在該部門的收入排名(每一個部門都會有1,2,3名) 統計查詢,子查詢也比較難以實現

  • select ename,deptno,sal,row_number() over(partition by deptno order by sal desc) from emp;
  • select ename,deptno,sal,row_number() over(partition by deptno order by sal desc) from emp where deptno=20;    

--- 排序時,如果值一樣,允許產生並列名次

  • select ename,deptno,sal,rank() over(partition by deptno order by sal desc) from emp where deptno=20;                  

---  排序時,如果值一樣,允許產生並列名次,產生並列值以後,後面的序號依然連續

  • select ename,deptno,sal,dense_rank() over(partition by deptno order by sal desc) from emp where deptno=20;    

常用的四個分析函數:

row_number()  over(order by 字段)         

  • 作用:先排序,再根據排列的順序,生成一組連續的序號

row_number()  over(partition by 字段名 order by 字段名)

  • 作用:先按照指定字段分組,然後在組內進行排序         

rank()  over(partition by 字段名 order by 字段名)

  • 作用:排序時,允許出現在並列名次         
  • 注意:如果產生幾個並列值,後序就會跳過幾個序號                       

dense_rank()  over(partition by 字段名 order by 字段名)    

  • 作用:允許產生並列值的排序,產生並列值以後,後面的序號,依然連續                   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章