最全的Oracle-SQL筆記

最全的ORACLE-SQL筆記

時間:2013-08-05 17:20 來源:www.chengxuyuans.com
 
-- 首先,以超級管理員的身份登陸oracle  
     sqlplus sys/bjsxt as sysdba  
   
 --而後,解除對scott用戶的鎖  
     alter user scott account unlock;  
 --那麼這個用戶名就能使用了。  
 --(默認全局數據庫名orcl)  
   
 一、select ename, sal * 12 from emp; --計算年薪  
 二、select 2*3 from dual;  --計算一個比較純的數據用dual表 
 三、select sysdate from dual;  --查看當前的系統時間  
 四、select ename, sal*12 anuual_sal from emp; --給搜索字段更更名稱(雙引號 keepFormat 別名有特殊字符,要加雙引號)。  
 五、--任何含有空值的數學表達式,最後的計算結果都是空值。  
 六、select ename||sal from emp;  --(將sal的查詢結果轉化爲字符串,與ename鏈接到一塊兒,至關於Java中的字符串鏈接)  
 七、select ename||'afasjkj' from emp;   --字符串的鏈接  
 八、select distinct deptno from emp;   --消除deptno字段重複的值  
 九、select distinct deptno , job from emp; --將與這兩個字段都重複的值去掉  
 十、select * from emp where deptno=10;   --(條件過濾查詢)               
 十一、select * from emp where empno > 10;  --大於 過濾判斷  
 十二、select * from emp where empno <> 10  --不等於  過濾判斷  
 1三、select * from emp where ename > 'cba';  --字符串比較,實際上比較的是每一個字符的AscII值,與在Java中字符串的比較是同樣的  
 1四、select ename, sal from emp where sal between 800 and 1500;  --(between and過濾,包含800 1500)  
 1五、select ename, sal, comm from emp where comm is null;  --(選擇comm字段爲null的數據)  
 1六、select ename, sal, comm from emp where comm is not null;  --(選擇comm字段不爲null的數據)  
 1七、select ename, sal, comm from emp where sal in (800, 1500,2000);  --(in 表範圍)  
 1八、select ename, sal, hiredate from emp where hiredate > '02-2月-1981'; --(只能按照規定的格式寫)  
 1九、select ename, sal from emp where deptno =10 or sal >1000;  
 20、select ename, sal from emp where deptno =10 and sal >1000;  
 2一、select ename, sal, comm from emp where sal not in (800, 1500,2000);  --(能夠對in指定的條件進行取反)  
 2二、select ename from emp where ename like '%ALL%';   --(模糊查詢)  
 2三、select ename from emp where ename like '_A%';    --(取第二個字母是A的全部字段)  
 2四、select ename from emp where ename like '%/%%';   --(用轉義字符/查詢字段中自己就帶%字段的)  
 2五、select ename from emp where ename like '%$%%' escape '$';   --(用轉義字符/查詢字段中自己就帶%字段的)  
 2六、select * from dept order by deptno desc; (使用order by  desc字段 對數據進行降序排列 默認爲升序asc);  
 2七、select * from dept where deptno <>10 order by deptno asc;   --(咱們能夠將過濾之後的數據再進行排序)    
 2八、select ename, sal, deptno from emp order by deptno asc, ename desc;   --(按照多個字段排序 首先按照deptno升序排列,當detpno相同時,內部再按照ename的降序排列)  
 2九、select lower(ename) from emp;  --(函數lower() 將ename搜索出來後所有轉化爲小寫);  
 30、select ename from emp where lower(ename) like '_a%';  --(首先將所搜索字段轉化爲小寫,而後判斷第二個字母是否是a)  
 3一、select substr(ename, 2, 3) from emp;    --(使用函數substr() 將搜素出來的ename字段從第二個字母開始截,一共截3個字符)  
 3二、select chr(65) from dual;  --(函數chr() 將數字轉化爲AscII中相對應的字符)   
 3三、select ascii('A') from dual;  --(函數ascii()與32中的chr()函數是相反的 將相應的字符轉化爲相應的Ascii編碼)                                                                                                                                                                                                                                                                                                                                             )  
 3四、select round(23.232) from dual;  --(函數round() 進行四捨五入操做)  
 3五、select round(23.232, 2) from dual;  --(四捨五入後保留的小數位數 0 個位 -1 十位)  
 3六、select to_char(sal, '$99,999.9999')from emp;  --(加$符號加入千位分隔符,保留四位小數,沒有的補零)  
 3七、select to_char(sal, 'L99,999.9999')from emp;  --(L 將貨幣轉化爲本地幣種此處將顯示¥人民幣)  
 3八、select to_char(sal, 'L00,000.0000')from emp;  --(補零位數不同,可到數據庫執行查看)  
 3九、select to_char(hiredate, 'yyyy-MM-DD HH:MI:SS') from emp;  --(改變日期默認的顯示格式)  
 40、select to_char(sysdate, 'yyyy-MM-DD HH:MI:SS') from dual;  --(用12小時制顯示當前的系統時間)  
 4一、select to_char(sysdate, 'yyyy-MM-DD HH24:MI:SS') from dual;  --(用24小時制顯示當前的系統時間)  
 4二、select ename, hiredate from emp where hiredate > to_date('1981-2-20 12:24:45','YYYY-MM-DD HH24:MI:SS');   --(函數to-date 查詢公司在所給時間之後入職的人員)  
 4三、select sal from emp where sal > to_number('$1,250.00', '$9,999.99');   --(函數to_number()求出這種薪水裏帶有特殊符號的)  
 4四、select ename, sal*12 +  nvl(comm,0) from emp;   --(函數nvl() 求出員工的"年薪 + 提成(或獎金)問題")  
 4五、select max(sal) from emp;  -- (函數max() 求出emp表中sal字段的最大值)  
 4六、select min(sal) from emp;  -- (函數max() 求出emp表中sal字段的最小值)  
 4七、select avg(sal) from emp;  --(avg()求平均薪水);  
 4八、select to_char(avg(sal), '999999.99') from emp;   --(將求出來的平均薪水只保留2位小數)  
 4九、select round(avg(sal), 2) from emp;  --(將平均薪水四捨五入到小數點後2位)  
 50、select sum(sal) from emp;  --(求出每月要支付的總薪水)  
   
 ------------------------/組函數(共5個):將多個條件組合到一塊兒最後只產生一個數據------min() max() avg() sum() count()----------------------------/  
 5一、select count(*) from emp;  --求出表中一共有多少條記錄  
 5二、select count(*) from emp where deptno=10;  --再要求一共有多少條記錄的時候,還能夠在後面跟上限定條件  
 5三、select count(distinct deptno) from emp;   --統計部門編號前提是去掉重複的值  
 ------------------------聚組函數group by() --------------------------------------  
 5四、select deptno, avg(sal) from emp group by deptno;  --按照deptno分組,查看每一個部門的平均工資  
 5五、select max(sal) from emp group by deptno, job; --分組的時候,還能夠按照多個字段進行分組,兩個字段不相同的爲一組  
 5六、select ename from emp where sal = (select max(sal) from emp); --求出  
 5七、select deptno, max(sal) from emp group by deptno; --搜素這個部門中薪水最高的的值  
 --------------------------------------------------having函數對於group by函數的過濾 不能用where--------------------------------------  
 5八、select deptno, avg(sal) from emp group by deptno having avg(sal) >2000; (order by )--求出每一個部門的平均值,而且要 > 2000  
 5九、select avg(sal) from emp where sal >1200 group by deptno having avg(sal) >1500 order by avg(sal) desc;--求出sal>1200的平均值按照deptno分組,平均值要>1500最後按照sal的倒序排列  
 60、select ename,sal from emp where sal > (select avg(sal) from emp);  --求那些人的薪水是在平均薪水之上的。  
 6一、select ename, sal from emp join (select max(sal) max_sal ,deptno from emp group by deptno) t on (emp.sal = t.max_sal and emp.deptno=t.deptno);  --查詢每一個部門中工資最高的那我的  
 ------------------------------/等值鏈接--------------------------------------  
 6二、select e1.ename, e2.ename from emp e1, emp e2 where e1.mgr = e2.empno;  --自鏈接,把一張表當成兩張表來用  
 6三、select ename, dname from emp, dept;  --92年語法 兩張表的鏈接 笛卡爾積。  
 6四、select ename, dname from emp cross join dept; --99年語法 兩張表的鏈接用cross join  
 6五、select ename, dname from emp, dept where emp.deptno = dept.deptno; -- 92年語法 錶鏈接 + 條件鏈接  
 6六、select ename, dname from emp join dept on(emp.deptno = dept.deptno); -- 新語法  
 6七、select ename,dname from emp join dept using(deptno); --與66題的寫法是同樣的,可是不推薦使用using : 假設條件太多  
 --------------------------------------/非等值鏈接------------------------------------------/  
 6八、select ename,grade from emp e join salgrade s on(e.sal between s.losal and s.hisal); --兩張表的鏈接 此種寫法比用where更清晰  
 6九、select ename, dname, grade from emp e  
     join dept d on(e.deptno = d.deptno)  
     join salgrade s on (e.sal between s.losal and s.hisal)  
     where ename not like '_A%';  --三張表的鏈接  
 70、select e1.ename, e2.ename from emp e1 join emp e2 on(e1.mgr = e2.empno); --自鏈接第二種寫法,同62  
 7一、select e1.ename, e2.ename from emp e1 left join emp e2 on(e1.mgr = e2.empno); --左外鏈接 把左邊沒有知足條件的數據也取出來  
 7二、select ename, dname from emp e right join dept d on(e.deptno = d.deptno); --右外鏈接  
 7三、select deptno, avg_sal, grade from (select deptno, avg(sal) avg_sal from emp group by deptno) t join salgrade s  on    (t.avg_sal between s.losal and s.hisal);--求每一個部門平均薪水的等級  
 7四、select ename from emp where empno in (select mgr from emp); -- 在表中搜索那些人是經理  
 7五、select sal from emp where sal not in(select distinct e1.sal from emp e1 join emp e2 on(e1.sal < e2.sal)); -- 面試題 不用組函數max()求薪水的最大值  
 7六、select deptno, max_sal from  
     (select avg(sal) max_sal,deptno from emp group by deptno)  
         where max_sal =  
         (select max(max_sal) from  
          (select avg(sal) max_sal,deptno from emp group by deptno)  
     );--求平均薪水最高的部門名稱和編號。  
 7七、select t1.deptno, grade, avg_sal from  
       (select deptno, grade, avg_sal from  
     (select deptno, avg(sal) avg_sal from emp group by deptno) t  
         join salgrade s on(t.avg_sal between s.losal and s.hisal)  
       ) t1  
     join dept on (t1.deptno = dept.deptno)  
     where t1.grade =   
       (  
         select min(grade) from  
           (select deptno, grade, avg_sal from  
     (select deptno, avg(sal) avg_sal from emp group by deptno) t  
     join salgrade s on(t.avg_sal between s.losal and s.hisal)  
      )  
    )--求平均薪水等級最低的部門的名稱 哈哈 確實比較麻煩  
 7八、create view v$_dept_avg_sal_info as  
     select deptno, grade, avg_sal from  
        (select deptno, avg(sal) avg_sal from emp group by deptno) t  
     join salgrade s on(t.avg_sal between s.losal and s.hisal);  
     --視圖的建立,通常以v$開頭,但不是固定的  
   
   
 7九、select t1.deptno, grade, avg_sal from v$_dept_avg_sal_info t1  
     join dept on (t1.deptno = dept.deptno)  
     where t1.grade =   
       (  
         select min(grade) from  
          v$_dept_avg_sal_info t1  
      )  
    )--求平均薪水等級最低的部門的名稱 用視圖,能簡單一些,至關於Java中方法的封裝  
   
 80、---建立視圖出現權限不足時候的解決辦法:  
     conn sys/admin as sysdba;  
         --顯示:鏈接成功 Connected  
     grant create table, create view to scott;  
        -- 顯示: 受權成功 Grant succeeded  
 8一、-------求比普通員工最高薪水還要高的經理人的名稱 -------  
     select ename, sal from emp where empno in  
        (select distinct mgr from emp where mgr is not null)  
     and sal >  
     (  
        select max(sal) from emp where empno not in  
          (select distinct mgr from emp where mgr is not null)  
     )  
 8二、---面試題:比較效率  
        select * from emp where deptno = 10 and ename like '%A%';--好,將過濾力度大的放在前面  
        select * from emp where ename like '%A%' and deptno = 10;  
 8三、-----表的備份  
        create table dept2 as select * from dept;  
 8四、-----插入數據  
         insert into dept2 values(50,'game','beijing');  
       ----只對某個字段插入數據  
         insert into dept2(deptno,dname) values(60,'game2');  
 8五、-----將一個表中的數據徹底插入另外一個表中(表結構必須同樣)  
     insert into dept2 select * from dept;  
 8六、-----求前五名員工的編號和名稱(使用虛字段rownum 只能使用 < 或 = 要使用 > 必須使用子查詢)  
     select empno,ename from emp where rownum <= 5;  
 8六、----求10名僱員之後的僱員名稱--------  
     select ename from (select rownum r,ename from emp) where r > 10;  
 8七、----求薪水最高的前5我的的薪水和名字---------  
     select ename, sal from (select ename, sal from emp order by sal desc) where rownum <=5;    
 8八、----求按薪水倒序排列後的第6名到第10名的員工的名字和薪水--------  
     select ename, sal from  
            (select ename, sal, rownum r from  
               (select ename, sal from emp order by sal desc)  
            )  
         where r>=6 and r<=10  
 8九、----------------建立新用戶---------------  
     一、backup scott--備份  
         exp--導出  
     二、create user  
         create user guohailong identified(認證) by guohailong  default tablespace users quota(配額) 10M on users  
         grant create session(給它登陸到服務器的權限),create table, create view to guohailong  
     三、import data  
         imp  
 90、-----------事務回退語句--------  
     rollback;  
       
 9一、-----------事務確認語句--------  
     commit;--此時再執行rollback無效  
   
 9二、--當正常斷開鏈接的時候例如exit,事務自動提交。  當非正常斷開鏈接,例如直接關閉dos窗口或關機,事務自動提交  
 9三、/*有3個表S,C,SC   
     S(SNO,SNAME)表明(學號,姓名)   
     C(CNO,CNAME,CTEACHER)表明(課號,課名,教師)   
     SC(SNO,CNO,SCGRADE)表明(學號,課號成績)   
     問題:   
     1,找出沒選過「黎明」老師的全部學生姓名。   
     2,列出2門以上(含2門)不及格學生姓名及平均成績。   
     3,即學過1號課程有學過2號課全部學生的姓名。  
     */答案:  
     一、  
         select sname from s join sc on(s.sno = sc.sno) join c on (sc.cno = c.cno) where cteacher <> '黎明';  
     二、  
         select sname where sno in (select sno from sc where scgrade < 60 group by sno having count(*) >=2);  
     三、  
         select sname from s where sno in (select sno, from sc where cno=1 and cno in  
                             (select distinct sno from sc where cno = 2);  
                          )  
   
 9四、--------------建立表--------------  
        create table stu  
     (  
     id number(6),  
     name varchar2(20) constraint stu_name_mm not null,  
     sex number(1),  
     age number(3),  
     sdate date,  
     grade number(2) default 1,  
     class number(4),  
     email varchar2(50) unique  
     );  
 9五、--------------給name字段加入 非空 約束,並給約束一個名字,若不取,系統默認取一個-------------  
        create table stu  
     (  
     id number(6),  
     name varchar2(20) constraint stu_name_mm not null,  
     sex number(1),  
     age number(3),  
     sdate date,  
     grade number(2) default 1,  
     class number(4),  
     email varchar2(50)  
     );  
 9六、--------------給nameemail字段加入 惟一 約束 兩個 null值 不爲重複-------------  
        create table stu  
     (  
     id number(6),  
     name varchar2(20) constraint stu_name_mm not null,  
     sex number(1),  
     age number(3),  
     sdate date,  
     grade number(2) default 1,  
     class number(4),  
     email varchar2(50) unique  
     );  
 9七、--------------兩個字段的組合不能重複 約束:表級約束-------------  
        create table stu  
     (  
     id number(6),  
     name varchar2(20) constraint stu_name_mm not null,  
     sex number(1),  
     age number(3),  
     sdate date,  
     grade number(2) default 1,  
     class number(4),  
     email varchar2(50),  
     constraint stu_name_email_uni unique(email, name)  
     );  
 9八、--------------主鍵約束-------------  
        create table stu  
     (  
     id number(6),  
     name varchar2(20) constraint stu_name_mm not null,  
     sex number(1),  
     age number(3),  
     sdate date,  
     grade number(2) default 1,  
     class number(4),  
     email varchar2(50),  
     constraint stu_id_pk primary key (id),  
     constraint stu_name_email_uni unique(email, name)  
     );  
   9九、--------------外鍵約束   被參考字段必須是主鍵 -------------  
        create table stu  
     (  
     id number(6),  
     name varchar2(20) constraint stu_name_mm not null,  
     sex number(1),  
     age number(3),  
     sdate date,  
     grade number(2) default 1,  
     class number(4) references class(id),  
     email varchar2(50),  
     constraint stu_class_fk foreign key (class) references class(id),  
     constraint stu_id_pk primary key (id),  
     constraint stu_name_email_uni unique(email, name)  
     );  
       
     create table class   
     (  
     id number(4) primary key,  
     name varchar2(20) not null  
     );  
 100、---------------修改表結構,添加字段------------------  
     alter table stu add(addr varchar2(29));  
 10一、---------------刪除字段--------------------------  
     alter table stu drop (addr);  
 10二、---------------修改表字段的長度------------------  
     alter table  stu modify (addr varchar2(50));--更改後的長度必需要能容納原先的數據  
 10三、----------------刪除約束條件----------------  
     alter table stu drop constraint  約束名  
 10四、-----------修改表結構添加約束條件---------------  
     alter table  stu add constraint stu_class_fk foreign key (class) references class (id);  
 10五、---------------數據字典表----------------  
      desc dictionary;  
      --數據字典表共有兩個字段 table_name comments  
      --table_name主要存放數據字典表的名字  
      --comments主要是對這張數據字典表的描述  
        
 10五、---------------查看當前用戶下面全部的表、視圖、約束-----數據字典表user_tables---  
     select table_name from user_tables;  
     select view_name from user_views;  
     select constraint_name from user-constraints;  
 10六、-------------索引------------------  
     create index idx_stu_email on stu (email);-- 在stu這張表的email字段上創建一個索引:idx_stu_email  
 10七、---------- 刪除索引 ------------------  
     drop index index_stu_email;  
 10八、---------查看全部的索引----------------  
     select index_name from user_indexes;  
 10九、---------建立視圖-------------------  
     create view v$stu as selesct id,name,age from stu;  
      視圖的做用: 簡化查詢 保護咱們的一些私有數據,經過視圖也能夠用來更新數據,可是咱們通常不這麼用 缺點:要對視圖進行維護  
   
 1十、-----------建立序列------------  
     create sequence seq;--建立序列  
     select seq.nextval from dual;-- 查看seq序列的下一個值  
     drop sequence seq;--刪除序列  
 1十一、------------數據庫的三範式--------------  
     (1)、要有主鍵,列不可分  
     (2)、不能存在部分依賴:當有多個字段聯合起來做爲主鍵的時候,不是主鍵的字段不能部分依賴於主鍵中的某個字段  
     (3)、不能存在傳遞依賴   
 ==============================================PL/SQL==========================  
 1十二、-------------------在客戶端輸出helloworld-------------------------------  
     set serveroutput on;--默認是off,設成on是讓Oracle能夠在客戶端輸出數據  
 11三、begin  
     dbms_output.put_line('helloworld');  
     end;  
     /  
 11四、----------------pl/sql變量的賦值與輸出----  
     declare  
         v_name varchar2(20);--聲明變量v_name變量的聲明以v_開頭  
     begin  
         v_name := 'myname';  
         dbms_output.put_line(v_name);  
     end;  
     /  
 11五、-----------pl/sql對於異常的處理(除數爲0)-------------  
     declare  
         v_num number := 0;  
     begin  
         v_num := 2/v_num;  
         dbms_output.put_line(v_num);  
     exception  
         when others then  
         dbms_output.put_line('error');  
     end;  
     /  
 11六、----------變量的聲明----------  
     binary_integer:整數,主要用來計數而不是用來表示字段類型   比number效率高  
     number:數字類型  
     char:定長字符串  
     varchar2:變長字符串  
     date:日期  
     long:字符串,最長2GB  
     boolean:布爾類型,能夠取值true,false,null--最好給一初值  
 11七、----------變量的聲明,使用 '%type'屬性  
     declare  
         v_empno number(4);  
         v_empno2 emp.empno%type;  
         v_empno3 v_empno2%type;  
     begin  
         dbms_output.put_line('Test');  
     end;  
     /  
     --使用%type屬性,能夠使變量的聲明根據表字段的類型自動變換,省去了維護的麻煩,並且%type屬性,能夠用於變量身上  
 11八、---------------Table變量類型(table表示的是一個數組)-------------------  
     declare  
         type type_table_emp_empno is table of emp.empno%type index by binary_integer;  
             v_empnos type_table type_table_empno;  
     begin  
         v_empnos(0) := 7345;  
         v_empnos(-1) :=9999;  
         dbms_output.put_line(v_empnos(-1));  
     end;  
 11九、-----------------Record變量類型  
     declare  
         type type_record_dept is record  
         (  
             deptno dept.deptno%type,  
             dname dept.dname%type,  
             loc dept.loc%type  
         );  
     begin  
         v_temp.deptno:=50;  
         v_temp.dname:='aaaa';  
         v_temp.loc:='bj';  
         dbms_output.put_line(v temp.deptno || ' ' || v temp.dname);  
     end;  
 120、-----------使用 %rowtype聲明record變量  
     declare  
         v_temp dept%rowtype;  
     begin  
         v_temp.deptno:=50;  
         v_temp.dname:='aaaa';  
         v_temp.loc:='bj';  
     dbms_output.put_line(v temp.deptno || '' || v temp.dname)             
     end;  
       
 12一、--------------sql%count 統計上一條sql語句更新的記錄條數   
 12二、--------------sql語句的運用  
     declare  
         v_ename emp.ename%type;  
         v_sal emp.sal%type;  
     begin  
         select ename,sal into v_ename,v_sal from emp where empno = 7369;  
         dbms_output.put_line(v_ename || '' || v_sal);  
     end;  
   
 12三、  -------- pl/sql語句的應用  
     declare  
         v_emp emp%rowtype;  
     begin  
         select * into v_emp from emp where empno=7369;  
         dbms_output_line(v_emp.ename);  
     end;  
 12四、-------------pl/sql語句的應用   
     declare  
         v_deptno dept.deptno%type := 50;  
         v_dname dept.dname%type :='aaa';  
         v_loc dept.loc%type := 'bj';  
     begin  
         insert into dept2 values(v_deptno,v_dname,v_loc);  
     commit;  
     end;  
 12五、-----------------ddl語言,數據定義語言  
     begin  
         execute immediate 'create table T (nnn varchar(30) default ''a'')';  
     end;  
 12六、------------------if else的運用  
      declare  
         v_sal emp.sal%type;  
      begin  
         select sal into v_sal from emp where empno = 7369;  
     if(v_sal < 2000) then  
         dbms_output.put_line('low');  
     elsif(v_sal > 2000) then  
         dbms_output.put_line('middle');  
     else   
         dbms_output.put_line('height');  
         end if;  
       end;  
 12七、-------------------循環 =====do while  
     declare  
         i binary_integer := 1;  
     begin  
         loop  
                 dbms_output.put_line(i);  
                 i := i + 1;  
             exit when (i>=11);  
         end loop;  
     end;  
 12八、---------------------while   
     declare  
         j binary_integer := 1;  
     begin  
         while j < 11 loop  
             dbms_output.put_line(j);  
         j:=j+1;  
         end loop;  
     end;  
 12九、---------------------for  
     begin  
         for k in 1..10 loop  
             dbms_output.put_line(k);  
         end loop;  
         for k in reverse 1..10 loop  
             dbms_output.put_line(k);  
         end loop;  
     end;  
 130、-----------------------異常(1)  
     declare  
         v_temp number(4);  
     begin  
         select empno into v_temp from emp where empno = 10;  
     exception  
         when too_many_rows then  
             dbms_output.put_line('太多記錄了');  
         when others then  
             dbms_output.put_line('error');    
     end;  
 13一、-----------------------異常(2)  
     declare  
         v_temp number(4);  
     begin  
         select empno into v_temp from emp where empno = 2222;  
     exception  
         when no_data_found then  
             dbms_output.put_line('太多記錄了');  
     end;  
 13二、----------------------建立序列  
     create sequence seq_errorlog_id start with 1 increment by 1;  
 13三、-----------------------錯誤處理(用表記錄:將系統日誌存到數據庫便於之後查看)  
   
   
    -- 建立日誌表:  
     create table errorlog  
     (  
     id number primary key,  
     errcode number,  
     errmsg varchar2(1024),  
     errdate date  
     );  
   
   
       
     declare  
         v_deptno dept.deptno%type := 10;  
         v_errcode  number;  
         v_errmsg varchar2(1024);  
     begin  
         delete from dept where deptno = v_deptno;  
        commit;  
     exception  
         when others then  
             rollback;  
                 v_errcode := SQLCODE;  
                 v_errmsg := SQLERRM;  
         insert into errorlog values (seq_errorlog_id.nextval, v_errcode,v_errmsg, sysdate);  
                 commit;  
     end;  
 133---------------------PL/SQL中的重點cursor(遊標)和指針的概念差很少  
     declare  
         cursor c is  
             select * from emp; --此處的語句不會馬上執行,而是當下面的open c的時候,纔會真正執行  
         v_emp c%rowtype;  
     begin  
         open c;  
             fetch c into v_emp;  
         dbms_output.put_line(v_emp.ename); --這樣會只輸出一條數據 134將使用循環的方法輸出每一條記錄  
       close c;  
     end;  
 134----------------------使用do while  循環遍歷遊標中的每個數據  
     declare  
         cursor c is  
             select * from emp;  
         v_emp c%rowtype;  
     begin  
         open c;   
         loop  
             fetch c into v_emp;  
             (1) exit when (c%notfound);  --notfound是oracle中的關鍵字,做用是判斷是否還有下一條數據  
             (2) dbms_output.put_line(v_emp.ename);  --(1)(2)的順序不能顛倒,最後一條數據,不會出錯,會把最後一條數據,再次的打印一遍  
        end loop;  
        close c;  
     end;  
 135------------------------while循環,遍歷遊標  
     declare  
         cursor c is  
             select * from emp;  
         v_emp emp%rowtype;  
     begin  
         open c;  
         fetch c into v_emp;  
         while(c%found) loop  
            dbms_output.put_line(v_emp.ename);  
            fetch c into v_emp;  
        end loop;  
        close c;  
     end;  
 136--------------------------for 循環,遍歷遊標  
     declare  
         cursor c is  
            select * from emp;  
     begin  
         for v_emp in c loop  
             dbms_output.put_line(v_emp.ename);  
         end loop;  
     end;  
   
 137---------------------------帶參數的遊標  
     declare  
         cursor c(v_deptno emp.deptno%type, v_job emp.job%type)  
         is  
            select ename, sal from emp where deptno=v_deptno and job=v_job;  
         --v_temp c%rowtype;此處不用聲明變量類型  
     begin  
         for v_temp in c(30, 'click') loop  
             dbms_output.put_line(v_temp.ename);  
         end loop;  
     end;  
 138-----------------------------可更新的遊標  
     declare  
         cursor c  --有點小錯誤  
         is  
            select * from emp2 for update;  
         -v_temp c%rowtype;  
     begin  
        for v_temp in c loop  
         if(v_temp.sal < 2000) then  
             update emp2 set sal = sal * 2 where current of c;  
           else if (v_temp.sal =5000) then  
         delete from emp2 where current of c;  
            end if;  
          end loop;  
          commit;  
     end;  
 139-----------------------------------procedure存儲過程(帶有名字的程序塊)  
     create or replace procedure p  
         is--這兩句除了替代declare,下面的語句所有都同樣    
         cursor c is  
             select * from emp2 for update;  
     begin  
          for v_emp in c loop  
         if(v_emp.deptno = 10) then  
             update emp2 set sal = sal +10 where current of c;  
         else if(v_emp.deptno =20) then  
             update emp2 set sal =  sal + 20 where current of c;  
         else  
             update emp2 set sal = sal + 50 where current of c;  
         end if;  
         end loop;  
       commit;  
      end;  
       
     --執行存儲過程的兩種方法:  
     (1)exec p;(p是存儲過程的名稱)  
     (2)  
         begin  
             p;  
         end;  
         /  
 140-------------------------------帶參數的存儲過程  
     create or replace procedure p  
         (v_a in number, v_b number, v_ret out number, v_temp in out number)  
     is  
       
     begin  
         if(v_a > v_b) then  
             v_ret := v_a;  
         else  
             v_ret := v_b;  
         end if;  
         v_temp := v_temp + 1;  
     end;  
 141----------------------調用140  
     declare  
         v_a  number := 3;  
         v_b  number := 4;  
         v_ret number;  
         v_temp number := 5;  
   
     begin  
         p(v_a, v_b, v_ret, v_temp);  
         dbms_output.put_line(v_ret);  
         dbms_output.put_line(v_temp);  
     end;  
   
 142------------------刪除存儲過程  
     drop procedure p;  
 143------------------------建立函數計算我的所得稅    
     create or replace function sal_tax  
         (v_sal  number)   
         return number  
     is  
     begin  
         if(v_sal < 2000) then  
             return 0.10;  
         elsif(v_sal <2750) then  
             return 0.15;  
         else  
             return 0.20;  
         end if;  
     end;  
 ----144-------------------------建立觸發器(trigger)  觸發器不能單獨的存在,必須依附在某一張表上  
   
     --建立觸發器的依附表  
       
     create table emp2_log  
     (  
     ename varchar2(30) ,  
     eaction varchar2(20),  
     etime date  
     );    
   
     create or replace trigger trig  
         after insert or delete or update on emp2 ---for each row 加上此句,每更新一行,觸發一次,不加入則值觸發一次  
     begin  
         if inserting then  
             insert into emp2_log values(USER, 'insert', sysdate);  
         elsif updating then  
             insert into emp2_log values(USER, 'update', sysdate);  
         elsif deleting then  
             insert into emp2_log values(USER, 'delete', sysdate);  
         end if;  
     end;  
 145-------------------------------經過觸發器更新數據  
     create or replace trigger trig  
         after update on dept  
         for each row  
     begin  
         update emp set deptno =:NEW.deptno where deptno =: OLD.deptno;  
     end;  
       
   
     ------只編譯不顯示的解決辦法 set serveroutput on;  
 145-------------------------------經過建立存儲過程完成遞歸  
     create or replace procedure p(v_pid article.pid%type,v_level binary_integer) is  
         cursor c is select * from article where pid = v_pid;  
         v_preStr varchar2(1024) := '';  
     begin  
       for i in 0..v_leave loop  
         v_preStr := v_preStr || '****';  
       end loop;  
   
       for v_article in c loop  
         dbms_output.put_line(v_article.cont);  
         if(v_article.isleaf = 0) then  
             p(v_article.id);  
         end if;  
         end loop;  
       
     end;  
 146-------------------------------查看當前用戶下有哪些表---  
     --首先,用這個用戶登陸而後使用語句:  
     select * from tab;  
       
 147-----------------------------用Oracle進行分頁!--------------  
     --由於Oracle中的隱含字段rownum不支持'>'因此:  
     select * from (  
         select rownum rn, t.* from (  
             select * from t_user where user_id <> 'root'  
         ) t where rownum <6  
     ) where rn >3  
 148------------------------Oracle下面的清屏命令----------------  
     clear screen; 或者 cle scr;  
   
 149-----------將建立好的guohailong的這個用戶的密碼改成abc--------------  
     alter user guohailong identified by abc  
     --當密碼使用的是數字的時候可能會不行  
     
     
     
     
     
     
     --使用在10 Oracle以上的正則表達式在dual表查詢
  with test1 as(
        select 'ao' name from dual union all
        select 'yang' from dual union all
        select 'feng' from dual  )
        select distinct regexp_replace(name,'[0-9]','') from test1
   
 ------------------------------------------
 with tab as (
       select 'hong'  name from dual union all
       select 'qi' name from dual union all 
       select 'gong' name from dual) 
       select translate(name,'\\0123456789','\\') from tab; 
 
     
     
     
     
     
     
 CREATE OR REPLACE PROCEDURE 
     calc(i_birth VARCHAR2) IS 
     s VARCHAR2(8);  
     o VARCHAR2(8);  
     PROCEDURE cc(num VARCHAR2, s OUT VARCHAR2) IS 
     BEGIN 
     FOR i 
        IN REVERSE 2 .. length(num) LOOP
      s := s || substr(substr(num, i, 1) + substr(num, i - 1, 1), -1);
       END LOOP; 
        SELECT REVERSE(s) INTO s FROM dual; 
         END; 
          BEGIN o := i_birth; 
          LOOP 
           cc(o, s); 
           o := s; 
          dbms_output.put_line(s); 
         EXIT WHEN length(o) < 2; 
         END LOOP; 
      END; 
    set serveroutput on; 
      
  exec calc('19880323');  
  
  
  
  
  ----算命pl/sql
  with t as
  (select '19880323' x from dual)
	  select 
	    case 
		     when mod (i, 2) = 0 then '命好'
		     when  i = 9 		 then '命運悲慘' 
		        else '通常'
		     end result
	    from (select mod(sum((to_number(substr(x, level, 1)) +to_number(substr(x, -level, 1))) *                      
	         greatest(((level - 1) * 2 - 1) * 7, 1)),10) i from t connect by level <= 4);
       
       
 
--構造一個表,和emp表的部分字段相同,可是順序不一樣
SQL> create table t_emp as
  2  select ename,empno,deptno,sal
  3  from emp
  4  where 1=0
  5  /
 
Table created
 --添加數據
SQL> insert into t_emp(ename,empno,deptno,sal)
  2  select ename,empno,deptno,sal
  3  from emp
  4  where sal >= 2500 
  5  /
  
  
  select * from tb_product where createdate>=to_date('2011-6-13','yyyy-MM-dd') and createdate<=to_date('2011-6-16','yyyy-MM-dd');  

sysdate --獲取當前系統的時間


to_date('','yyyy-mm-dd')


select * from tb_product where to_char(createdate,'yyyy-MM-dd')>='2011-6-13' and to_char(createdate,'yyyy-MM-dd')<='2011-6-16';  


select * from tb_product where trunc(createdate)>=? and trunc(createdate)<=?
用trunc函數就能夠了 


 </pre>
<p> </p>
<pre name="code" >第一次
一、Oracle安裝及基本命令
1.一、Orace簡介
Oracleso一個生產中間件和數據庫的較大生產商。其發展依靠了IBM公司。創始人是Larry Ellison。
1.二、Oracle的安裝
1) Oracle的主要版本
Oracle 8;
Oracle 8i;i,指的是Internet
Oracle 9i;相比Oracle8i比較相似
Oracle 10g;g,表示網格技術
所謂網格技術,拿百度搜索爲例,如今咱們須要搜索一款叫作「EditPlus」的文本編輯器軟件,當咱們在百度搜索框中輸入「EditPlus」進行搜索時, 會獲得百度爲咱們搜索到的大量關於它的連接,此時,咱們考慮一個問題,若是在我所處的網絡環境周邊的某個地方的服務器就提供這款軟件的下載(也就是說提供一個下載連接供咱們下載),那麼,咱們就不必去訪問一個遠在地球對面的某個角落的服務器去下載這款軟件。如此一來就能夠節省大量的網絡資源。使用網格技術就能解決這種問題。咱們將整個網絡劃分爲若干個網格,也就是說每個使用網絡的用戶,均存在於某一個網格,當咱們須要搜索指定資源時,首先在咱們所處的網格中查找是否存在指定資源,沒有的話就擴大搜索範圍,到更大的網格中進行查找,直到查找到爲止。
2) 安裝Oracle的準備工做
關閉防火牆,以避免影響數據庫的正常安裝。
3) 安裝Oralce的注意事項
爲了後期的開發和學習,咱們將全部數據庫默認帳戶的口令設置爲統一口令的,方便管理和使用。
在點擊「安裝」後,數據庫相關參數設置完成,其安裝工做正式開始,在完成安裝時,不要急着去點擊「肯定」按鈕,這時候,咱們須要進行一個很是重要的操做——帳戶解鎖。由於在Oracle中默認有一個叫作scott的帳戶,該帳戶中默認有4張表,而且存有相應的數據,因此,爲了方便咱們學習Oracle數據庫,咱們能夠充分利用scott這個內置帳戶。可是奇怪的是,在安裝Oracle數據庫的時候,scott默認是鎖住的,因此在使用該帳戶以前,咱們就須要對其進行解鎖操做。在安裝完成界面中,點擊「口令管理」進入到相應的口令管理界面,找到scott帳戶,將是否解鎖一欄的去掉,便可完成解鎖操做,後期就能夠正常使用scott帳戶。咱們運行SQLPlus(Oracle提供的命令行操做),會提示咱們輸入用戶名,如今咱們能夠輸入用戶名scott,回車後,會提示輸入口令,奇怪的是,當咱們輸入在安裝時設置的統一口令時,提示登陸拒絕,顯然是密碼錯誤,那麼,在Oracle數據庫中,scott的默認密碼是tiger,因此使用tiger能夠正常登陸,可是提示咱們scott的當前密碼已經失效,讓咱們從新設置密碼,建議仍是設置爲tiger。
在Oracle中內置了不少帳戶,那麼,咱們來了解下一下幾個比較重要的內置帳戶:
   |-普通用戶:scott/tiger
   |-普通管理員:system/manager
   |-超級管理員:sys/change_on_install
4) 關於Oracle的服務
    在Oracle安裝完成以後,會在咱們的系統中進行相關服務的註冊,在全部註冊的服務中,咱們須要關注一下兩個服務,在實際使用Oracle的過程當中,這兩個服務必須啓動才能使Oracle正常使用。
     |-第一個是OracleOraDb11g_home1TNSListener,監聽服務,若是客戶端想要鏈接數據庫,此服務必須開啓。
     |-第二個是OracleServiceORCL,數據庫的主服務。命名規則:OracleService + 數據庫名稱,此 服務必須啓動。
此後,咱們能夠經過命令行方式進入到SQLPlus的控制中心,進行命令的輸入。
1.三、SQLPlus
SQLPlus是Oracle提供的一種命令行執行的工具軟件,安裝以後會自動在系統中進行註冊。鏈接到數據庫以後,就能夠開始對數據庫中的表進行操做了。
1) 對SQLPlus的環境設置
set linesize 長度;--設置每行顯示的長度
set pagesize 行數;--修改每頁顯示記錄的長度。
須要注意的是,上述連個參數的設置只在當前的命令行有效,命令行窗口重啓或者開啓了第二個窗口須要從新設置。
2) SQLPlus經常使用操做
在SQLPlus中輸入ed a.sql,會彈出找不到文件的提示框,此時點擊「是」,將建立一個a.sql文件,並彈出文本編輯頁面,在這裏能夠輸入相關的sql語句,編輯完成後保存,在命令行中經過 @ a.sql的方式執行命令,若是建立的文件後綴爲「sql」,那麼在執行的時候能夠省略掉,便可以這麼寫, @ a。除了建立不存在的文件外,sqlplus中也能夠經過指定本地存在的文件進行命令的執行,方式爲 @ 文件路徑。
在SQLPlus中能夠經過命令使用其餘帳戶進行數據庫的鏈接,如,當前鏈接的用戶是scott,咱們須要使用sys進行鏈接,則能夠這麼操做:conn sys/430583 as sysdba,這裏須要說明的是,sys是超級管理員,當咱們須要使用sys進行登陸的時候,那麼須要額外的加上as sysdba表示sys將以管理員的身份登陸。這裏有幾點能夠測試下
|-當咱們使用sys以sysdba的角色登陸時,其密碼能夠隨意輸入,不必定是咱們設置的統一口令(430583)。因此,咱們得出結論,在管理員登陸時,只對用戶進行驗證,而普通用戶登陸時,執行用戶和密碼驗證。
在sys帳戶下訪問scott下的emp表時,會提示錯誤,由於在sys中是不存在emp表的,那麼若是須要在sys下訪問scott的表(也就是說須要在a用戶下訪問b用戶下的表),該如何操做呢?首先,咱們應該知道每一個對象是屬於一種模式(模式是對用戶所建立的數據庫對象的總稱,包括表,視圖,索引,同義詞,序列,過程和程序包等)的,而每一個帳戶對應一個模式,因此咱們須要在sys下訪問scott的表時,須要指明所訪問的表是屬於哪個模式的,即,咱們能夠這樣操做來實現上面的操做:select * from scott.emp;
若是咱們須要知道當前鏈接數據庫的帳戶是誰,能夠這樣操做:show user;
咱們知道,一個數據庫能夠存儲多張表,那麼,如何查看指定數據庫的全部表名稱呢?select * from tab;
在開發過程當中,咱們須要常常的查看某張表的表結構,這個操做能夠這樣實現:desc emp;
在SQLPlus中,咱們能夠輸入「/」來快速執行上一條語句。例如,在命令行中咱們執行了一條這樣的語句:select * from emp;可是咱們須要再次執行該查詢,就能夠輸入一個「/」就可快速執行。
3) 經常使用數據類型
    number(4)--&gt;表示數字,長度爲4
    varchar2(10)--&gt;表示的是字符串,只能容納10個長度
date--&gt;表示日期
number(7,2)--&gt;表示數字,小數佔2位,整數佔5位,總共7位
第二次
一、SQL語句
1.1 準備工做--熟悉scott帳戶下的四張表及表結構
第一張表emp--&gt;僱員表,用於存儲僱員信息
empno number(4) 表示僱員的編號,惟一編號
ename varchar2(10) 表示僱員的姓名
job varchar2(9) 表示工做職位
mgr number(4) 表示一個僱員的上司編號
hiredate date 表示僱傭日期
sal number(7,2) 表示月薪,工資
comm number(7,2) 表示獎金
deptno number(2) 表示部門編號
第二張表dept--&gt;部門表,用於存儲部門信息
deptno number(2) 部門編號
dname varchar2(14) 部門名稱
loc varchar2(13) 部門位置
第三張表salgrade--&gt;工資等級表,用於存儲工資等級
grade number 等級名稱
losal number 此等級的最低工資
hisal number 此等級的最高工資
第四張表bonus--&gt;獎金錶,用於存儲一個僱員的工資及獎金
ename varchar2(10) 僱員姓名
job varchar2(9) 僱員工做
sal number 僱員工資
comm number 僱員獎金
1.二、SQL簡介
什麼是SQL?
SQL(Structured Query Language,結構查詢語言)是一個功能強大的數據語言。SQL一般用於與數據庫的通信。SQL是關係數據庫管理系統的標準語言。SQL功能強大,歸納起來,分爲如下幾組:
|-DML--&gt;Data Manipulation Language,數據操縱語言,用於檢索或者修改數據,即主要是對數據庫表中的數據的操做。
|-DDL--&gt;Data Definition Language,數據定義語言,用於定義數據的結構,如建立、修改或者刪除數據庫對象,即主要是對錶的操做。
|-DCL--&gt;Data Control Language,數據控制語言,用於定義數據庫用戶的權限,即主要對用戶權限的操做。
1.三、簡單查詢語句
簡單查詢語句的語法格式是怎樣的?
select * |具體的列名 [as] [別名] from 表名稱;
須要說明的是,在實際開發中,最好不要使用*代替須要查詢的全部列,最好養成顯式書寫須要查詢的列名,方便後期的維護;在給查詢的列名設置別名的時候,能夠使用關鍵字as,固然不用也是能夠的。
拿emp表爲例,咱們如今須要查詢出僱員的編號、姓名、工做三個列的信息的話,就須要在查詢的時候明確指定查詢的列名稱,即
select empno,ename,job from emp;
若是須要指定查詢的返回列的名稱,即給查詢列起別名,咱們能夠這樣操做
select empno 編號,ename 姓名,job 工做 from emp;--省略as關鍵字的寫法
或者
select empno as 編號,ename as 姓名,job as 作工 from emp; --保留as關鍵字的寫法
若是如今須要咱們查詢出emp中全部的job,咱們可能這麼操做
select job from emp;
可能加上一個別名會比較好
select job 工做 from emp;
可是如今出現了一個問題,從查詢的結果中能夠看出,job的值是有重複的,這是爲何呢?由於咱們知道一個job職位可能會對應多個僱員,好比,在一個公司的市場部會有多名市場人員,在這裏咱們使用select job from emp;查詢的其實是當前每一個僱員對應的工做職位,有多少
個僱員,就會對應的查詢出多少個職位出來,因此就出現了重複值,爲了消除這樣的重複值,咱們在這裏能夠使用關鍵字distinct,接下來咱們繼續完成上面的操做,即
select distinct job from emp;
因此,咱們能夠看到,使用distinct的語法是這樣的:
select distinct *|具體的列名 別名 from 表名稱;
可是在消除重複列的時候,須要強調的是,若是咱們使用distinct同時查詢多列時,則必須保證查詢的全部列都存在重複數據才能消除掉。也就是說,當咱們須要查詢a,b,c三列時,若是a表存在重複值,可是b和c中沒有重複值,當使用distinct時是看不到消除重複列的效果的。拿scott中的emp表爲例,咱們須要查詢出僱員編號及僱員工做兩個列的值,咱們知道一個工做會對應多個僱員,因此,在這種操做中,僱員編號是沒有重複值的,可是工做有重複值,因此,執行這次查詢的結果將是獲得每個僱員對應的工做名稱,顯然,distinct沒起到做用。
如今咱們獲得了一個新的需求,要求咱們按以下的方式進行查詢:
編號是:7369的僱員,姓名是:SMITH,工做是:CLERK
那麼,咱們該如何解決呢?在這裏,咱們須要使用到Oracle 中的字符串鏈接(「||」)操做來實現。若是須要顯示一些額外信息的話,咱們須要使用單引號將要顯示的信息包含起來。那麼,上面的操做能夠按照下面的方式進行,
select '編號是' || empno || '的僱員,姓名是:' || ename || ',工做是:' || job from emp;
下面咱們再看一個新的應用。公司業績很好,因此老闆想加薪,全部員工的工資上調20%,該如何實現呢?難道在表中一個一個的修改工資列的值嗎?很顯然不是的,咱們能夠經過使用四則運算來完成加薪的操做。
select ename,sal*1.2 newsal from emp;--newsal是爲上調後的工資設置的列名
四則運算,+、-、*、/,一樣有優先順序,先乘除後加減。
1.四、限定查詢(where子句)
在前面咱們都是將一張表的所有列或者指定列的全部數據查詢出來,如今咱們有新的需求了,須要在指定條件下查詢出數據,好比,須要咱們查詢出部門號爲20的全部僱員、查詢出工資在3000以上的僱員信息......,這些所謂的查詢限定條件就是經過where來指定的。咱們先看看如何經過限定查詢的方式進行相關操做。咱們在前面知道了簡單的查詢語法是:
select *|具體的列名 from 表名稱;
那麼,限定查詢的語法格式以下:
select *|具體的列名 from 表名稱 where 條件表達式;
首先,咱們如今要查詢出工資在1500(不包括1500)之上的僱員信息
select * from emp where sal&gt;1500;
下面的操做是查詢出能夠獲得獎金的僱員信息(也就是獎金列不爲空的記錄)
select * from emp where comm is not null;
很顯然,查詢沒有獎金的操做就是
select * from emp where comm is null;
咱們來點複雜的查詢,查詢出工資在1500之上,而且能夠拿到獎金的僱員信息。這裏的限定條件再也不是一個了,當全部的限定條件須要同時知足時,咱們採用and關鍵字將多個限定條件進行鏈接,表示全部的限定條件都須要知足,因此,該查詢能夠這麼進行:
select * from emp where sal&gt;1500 and comm is not null;
如今的需求發生了變化,要求查詢出工資在1500之上,或者能夠領取到獎金的僱員信息。這裏的限定條件也是兩個,可是有所不一樣的是,咱們不須要同時知足着兩個條件,由於需求中寫的是
「或者」,因此在查詢時,只須要知足兩個條件中的一個就行。那麼,咱們使用關鍵字or來實現「或者」的功能。
select * from emp where sal&gt;1500 or comm is not null;
需求再次發生變化,查詢出工資不大於1500(小於或等於1500),同時不能夠領取獎金的僱員信息,可想這些僱員的工資必定不怎麼高。以前咱們使用not關鍵字對限定條件進行了取反,那麼,這裏就至關於對限定條件總體取反。咱們分析下,工資不大於1500同時不能夠領取獎金的反面含義就是工資大於1500同時能夠領取獎金,因此,咱們這樣操做:
select * from emp where sal&gt;1500 and comm is not null;
這是原始需求取反後的查詢語句,那麼爲了達到最終的查詢效果,咱們將限定條件總體取反,即
select * from emp where not(sal&gt;1500 and comm is not null);
在這裏,咱們經過括號將一系列限定條件包含起來表示一個總體的限定條件。
咱們在數學中學過這樣的表達式:100&lt;a&lt;200,那麼在數據庫中如何實現呢?同樣的,咱們如今要查詢出工資在1500之上,可是在3000之下的所有僱員信息,很顯然,兩個限定條件,同時要知足才行。
select * from emp where sal&gt;1500 and sal&lt;3000;
這裏不要異想天開的寫成select * from emp where 1500&lt;sal&lt;3000;()試試吧,絕對會報錯。 很簡單,數據庫軟件不支持這樣的寫法,至少如今的數據庫沒有誰去支持這樣的寫法。
在SQL語法中,提供了一種專門指定範圍查詢的過濾語句:between x and y,至關於a&gt;=x and a&lt;=y,也就是包含了等於的功能,其語法格式以下:
select * from emp where sal between 1500 and 3000;
如今咱們使用這種範圍查詢的方式修改上面的語句以下:
select * from emp where sal between 1500 and 3000;
好了,咱們如今開始使用數據庫中很是重要的一種數據類型,日期型。
查詢出在1981年僱傭的所有僱員信息,看似很簡單的一個查詢操做,這樣寫嗎?
select * from emp where hiredate=1981;()
很顯然,有錯。hiredate是date類型的,1981看似是一個年份(日期),可是像這樣使用,它僅僅是一個數字而已,類型都匹配,怎麼進行相等判斷呢?繼續考慮。咱們先這樣操做,查詢emp表的全部信息,
select * from emp;
從查詢結果中,咱們重點關注hiredate這一列的數據格式是怎麼定義的,
20-2月 -81,很顯然,咱們抽象的表示出來是這樣的,
一個月的第幾天-幾月 -年份的後兩位
因此,接下來咱們就有思路了,咱們就按照這樣的日期格式進行限定條件的設置,該如何設置呢?考慮下,查詢1981年僱傭的僱員,是否是這個意思,從1981年1月1日到1981年12月31日僱傭的就是咱們須要的數據呢?因此,這樣操做吧
select * from emp where hiredate between '1-1月 -81' and '31-12月 -81';
能夠看到,上面的限定條件使用了單引號包含,咱們暫且能夠將一個日期看作是一個字符串。由上面的範例中咱們獲得結論:between...and ...除了能夠進行數字範圍的查詢,還能夠進行日期範圍的查詢。
咱們再來看下面的例子,查詢出姓名是smith的僱員信息,嗯,很簡單,這樣操做
select * from emp where ename='smith';
看似沒有問題,限定條件也給了,單引號也沒有少,但是爲何查詢不到記錄呢?明明記得emp表中有一個叫作smith的僱員呀?難道被刪掉了,好吧,咱們不須要在這裏耗費時間猜想語句自身的問題了,上面的語句在語法上沒有任何問題,咱們先看看emp表中有哪些僱員,
select * from emp;
能夠看到,確實有一個叫作smith的僱員,可是不是smith,而是SMITH,因此,咱們忽略了一個很重要的問題,Oracle是對大小寫敏感的。因此,更改以下:
select * from emp where ename='SMITH';
如今看一個這樣的例子,要求查詢出僱員編號是7369,7499,7521的僱員信息。若是按照之前的作法,是這樣操做的,
select * from emp where empno=7369 or empno=7499 or empno=7521;
執行一下吧,確實沒任何問題,查詢出指定僱員編號的全部信息。可是SQL語法提供一種更好的解決方法,使用in關鍵字完成上面的查詢,以下:
select * from emp where empno in(7369,7499,7521);
總結下in的語法以下:
select * from tablename where 列名 in (值1,值2,值3);
select * from tablename where 列名 not in (值1,值2,值3);
須要說明的是,in關鍵字不光能夠用在數字上,也能夠用在字符串的信息上。看下面的例子
查詢出姓名是SMITH、ALLEN、KING的僱員信息
select * from emp where ename in('SMITH','ALLEN','KING');
若是在指定的查詢範圍中附加了額外的內容,不會影響查詢結果。
模糊查詢對於提升用戶體驗是很是好的,對於數據庫的模糊查詢,咱們經過like關鍵字來實現。首先咱們瞭解下like主要使用的兩種通配符:
|-「%」--&gt;能夠匹配任意長度的內容,包括0個字符;
|-「_」--&gt;能夠匹配一個長度的內容。
下面咱們看這樣一個需求,查詢全部僱員姓名中第二個字母包含「M」的僱員信息
select * from emp where ename like '_M%';
說明下,前面的「_」匹配姓名中第一個字母(任意一個字母),「%」匹配M後面出現的0個或者多個字母。
查詢出僱員姓名中包含字母M的僱員信息。分析可知,字母M能夠出如今姓名的任意位置,如何進行正確的匹配呢?
select * from emp where ename like '%M%';
這裏仍是使用%,匹配0個或者多個字母,便可以表示M出如今姓名的任意位置上。
若是咱們在使用like查詢的時候沒有指定查詢的關鍵字,則表示查詢內容,即
select * from emp where ename like '%%';
至關於咱們前面看到的
select * from emp;
前面咱們遇到了一個這樣的需求,查詢出在1981年僱傭的全部僱員信息,當時咱們採起的是使用範圍查詢between ... and ...實現的,如今咱們使用like一樣能夠實現
select * from emp where hiredate like '%81%';
查詢工資中包含6的僱員信息
select * from emp where sal like '%5%';
在操做條件中還能夠使用:&gt;、&gt;=、=、&lt;、&lt;=等計算符號
對於不等於符號,有兩種方式:&lt;&gt;、!=
如今須要咱們查詢僱員編號不是7369的僱員信息
select * from emp where empno&lt;&gt;7369;
select * from emp where empno!=7369;
1.五、對查詢結果進行排序(order by子句)
在查詢的時候,咱們經常須要對查詢結果進行一種排序,以方便咱們查看數據,好比以僱員編號排序,以僱員工資排序等。排序的語法是:
select *|具體的列名稱 from 表名稱 where 條件表達式 order by 排序列1,排序列2 asc|desc;
asc表示升序,默認排序方式,desc表示降序。
如今要求全部的僱員信息按照工資由低到高的順序排列
select * from emp order by sal;
在升級開發中,會遇到多列排序的問題,那麼,此時,會給order by指定多個排序列。要求查詢出10部門的全部僱員信息,查詢的信息按照工資由高到低排序,若是工資相等,則按照僱傭日期由早到晚排序。
select * from emp where deptno=10 order by sal desc,hiredate asc;
須要注意的是,排序操做是放在整個SQL語句的最後執行。
1.六、單行函數
在衆多的數據庫系統中,每一個數據庫之間惟一不一樣的最大區別就在於函數的支持上,使用函數能夠完成一系列的操做功能。單行函數語法以下:
function_name(column|expression,[arg1,arg2...])
參數說明:
function_name:函數名稱
columne:數據庫表的列名稱
expression:字符串或計算表達式
arg1,arg2:在函數中使用參數
單行函數的分類:
字符函數:接收字符輸入而且返回字符或數值
數值函數:接收數值輸入並返回數值
日期函數:對日期型數據進行操做
轉換函數:從一種數據類型轉換到另外一種數據類型
通用函數:nvl函數,decode函數
字符函數:
專門處理字符的,例如能夠將大寫字符變爲小寫,求出字符的長度。
如今咱們看一個例子,將小寫字母轉爲大寫字母
select upper('smith') from dual;
在實際中,咱們會遇到這樣的狀況,用戶須要查詢smith僱員的信息,可是咱們數據庫表中存放的是SMITH,這時爲了方便用戶的使用咱們將用戶輸入的僱員姓名字符串轉爲大寫,
select * from emp where ename=upper('smith');
一樣,咱們也能夠使用lower()函數將一個字符串變爲小寫字母表示,
select lower('HELLO WORLD') from dual;
那麼,將字符串的首字母變爲大寫該如何實現呢?咱們使用initcap()函數來完成上面的操做。
select initcap('HELLO WOLRD') from dual;
在前面的學習中咱們知道,在scot帳戶下的emp表中的僱員姓名採用全大寫顯示,如今咱們須要激昂姓名的首字母變爲大寫,該如何操做呢?
select initcap(ename) from emp;
咱們在前面使用了字符串鏈接操做符「||」對字符串鏈接顯示,好比:
select '編號爲' || empno || '的姓名是:' || ename from emp;
那麼,在字符函數中提供concat()函數實現鏈接操做。
select concat('hello','world') from dual;
上面的範例使用函數實現以下:
select concat('編號爲',empno,'的姓名是:',ename);?????????
此種方式不如鏈接符「||」好使。
在字符函數中能夠進行字符串的截取、求出字符串的長度、進行指定內容的替換
select substr('hello',1,3) 截取字符串,length('hello') 字符串長度,replace('hello','l','x') 字符串替換 from dual;
經過上面範例的操做,咱們須要注意幾如下:
Oralce中substr()函數的截取點是從0開始仍是從1開始;針對這個問題,咱們來操做看下,將上面的截取語句改成:
select substr('hello',0,3) 截取字符串 from dual;
由查詢結果能夠發現,結果同樣,也就是說從0和從1的效果是徹底同樣,這歸咎於Oracle的智能化。
若是如今要求顯示全部僱員的姓名及姓名的後三個字符,咱們知道,每一個僱員姓名的字符串長度可能不一樣,因此咱們採起的措施是求出整個字符串的長度在減去2,咱們這樣操做,
select ename,substr(ename,length(ename)-2) from emp;
雖然功能實現了,可是有沒有羽化的方案呢?固然是有的,咱們分析下,當咱們在截取字符串的時候,給定一個負數值是什麼效果,對,就是倒着截取,咱們採起這種方式優化以下:
select ename,substr(ename,-3) from emp;
數值函數:
四捨五入:round()
截斷小數位:trunc()
取餘(取模):mod()
執行四捨五入操做,能夠指定保留的小數位
select round(789.536) from dual;
select round(789.436) from dual;
select round(789.436,2) from dual;
能夠直接對整數進行四捨五入的進位
select round(789.536,-3) from dual;--1000
select round(789.536,-2) from dual;--800
trunc()函數與round()函數的不一樣在於,trunc不會保留任何的小數位,並且小數點也不會執行四捨五入的操做,也就是說在使用trunc()函數時,它會將數值從小數點截斷,只保留整數部分。
select trunc(789.536) from dual;--789
固然使用trunc()函數也能夠設置小數位的保留位數
select trunc(789.536,2) from dual;--789.53
select trunc(789.536,-2) from dual;--700
使用mod()函數能夠進行取餘的操做
select mod(10,3) from dual;--1
日期函數:
在Oracle中提供了不少餘日期相關的函數,包括加減日期等。可是在日期進行加或者減結果的時候有一些規律:
日期-數字=日期
日期+數字=日期
日期-日期=數字(天數的差值)
顯示部門10的孤雁進入公司的星期數,要想完成此查詢,必須知道當前的日期,在Oralce中能夠經過如下的操做求出當前日期,使用sysdate表示
select sysdate from dual;
如何求出星期數呢?使用公式:當前日期-僱傭日期=天數 / 7 = 星期數,因此
select empno,ename,round((sysdate-hiredate)/7) from emp;
在Oracle中提供瞭如下的日期函數支持:
months_between()--&gt;求出給定日期範圍的月數
add_months()--&gt;在指定日期上加上指定的月數,求出以後的日期
next_day()--&gt;下一個的今天是哪個日期
last_day()--&gt;求出給定日期的最後一天日期
查詢出全部僱員的編號,姓名,和入職的月數
select empno,ename,round(months_between(sysdate,hiredate)) from emp;
查詢出當前日期加上4個月後的日期
select add_months(sysdate,4) from dual;
查詢出下一個給定日期數
select next_day(sysdate,'星期一') from dual;
查詢給定日期的最後一天,也就是給定日期的月份的最後一天
select last_day(sysdate) from dual;
轉換函數:
to_char()--&gt;轉換成字符串
to_number()--&gt;轉換成數字
to_date()--&gt;轉換成日期
咱們先看看前面作的一個範例,查詢全部僱員的僱員編號,姓名和僱傭時間
select empno,ename,hiredate from emp;
可是如今的要求是講年、月、日進行拆分,此時咱們就須要使用to_char()函數進行拆分,拆分的時候必須指定拆分的通配符:
年--&gt;y,年是四位數字,因此使用yyyy表示
月--&gt;m,月是兩位數字,因此使用mm表示
日--&gt;d,日是兩位數字,因此使用dd表示
select empno,ename,to_char(hiredate,'yyyy') year,to_char(hiredate,'mm') month,to_char(hiredate,'dd') day from emp;
咱們還能夠使用to_char()進行日期顯示的轉換功能,Oracle中默認的日期格式是:19-4月 -87,而中國喜歡的格式是:1987-04-19
select empno,ename,to_char(hiredate,'yyyy-mm-dd') from emp;
從顯示結果中咱們能夠看到,對於月份和日的顯示中,若是不足10,就會自動補零,哪一個0咱們成爲前導0,若是不但願顯示前導0的話,則能夠使用fm去掉
select empno,ename,to_char(hiredate,'fmyyyy-mm-dd') from emp;
固然,to_char()也能夠用在數字上
查詢所有的僱員編號、姓名和工資
select empno,ename,sal from emp;
咱們能夠看到,當工資數比較大時,是不利於讀的,那麼,咱們能夠在數字中使用「,」每3位進行一個分隔,此時,就能夠使用to_char()進行格式化。格式化時,9並不表明實際的數字9,而是一個佔位符
select empno,ename,to_char(sal,'99,999') from emp;
還有一個問題,工資數表示的是美圓仍是人民幣呢?如何解決顯示區域的問題呢?咱們能夠使用下面的兩種符號:
L--&gt;表示Local的縮寫,以本地的語言進行金額的顯示
$--&gt;表示美圓
select empno,ename,to_char(sal,'$99,999') from emp;
to_number()是能夠講字符串變爲數字的函數
select to_number('123') + to_number('123') from dual;
to_date()能夠講一個字符串變爲date的數據
select to_date('2012-09-12','yyyy-mm-dd') from dual;
通用函數:
如今又這樣一個需求,求出每一個僱員的年薪。咱們知道求年薪的話應該加上獎金的,格式爲(sal+comm)*12
select empno,ename,(sal+comm)*12 from emp;
查看結果,能夠發現一個很奇怪的顯現,居然有的僱員年薪爲空,這是如何引發的呢?咱們分析下,首先能夠查看下全部僱員的獎金列數據,發現只有部分僱員才能夠領取獎金,沒有領取獎金
的僱員其comm列是空的,沒有任何值(null),由此,上面的四則運算顯然沒結果。爲了解決這個問題,咱們須要用到一個通用函數nvl,將一個指定的null值變爲指定的內容
select empno,ename,(sal+nvl(comm,0))*12 from emp;
decode()函數,此函數相似於if...elseif...else語句
其語法格式爲:
decode(col/expression,search1,result1[search2,result2,......][,default])
說明:col/expression--&gt;列名或表達式
search1.search2......--&gt;爲用於比較的條件
result一、result2......--&gt;爲返回值
若是col/expression和search i 相比較,相同的話返回result i ,若是沒有與col/expression相匹配的結果,則返回默認值default。
select decode(1,1,'內容是1',2,'內容是2',3,'內容是3') from dual;
那麼,如何在對錶查詢時使用decode()函數呢?咱們來定義一個需求,
如今僱員的工做職位有:
CLERK--&gt;業務員
SALESMAN--&gt;銷售人員
MANAGER--&gt;經理
ANALYST--&gt;分析員
PRESIDENT--&gt;總裁
要求咱們查詢出僱員的編號,姓名,僱傭日期及工做,將工做替換爲上面的中文
select empno 僱員編號,ename 僱員姓名,hiredate 僱傭日期,decode(job,'CLERK','業務員','SALESMAN','銷售人員','MANAGER','經理','ANALYST','分析員','PRESIDENT','總裁') 職位 from emp;
從查詢結果能夠看出,全部的職位都被相應的中文替換了。
1.七、SQL語法練習
如今咱們再次經過相應的練習對scott帳戶下的四張表作進一步的熟悉。
選擇部門30中的全部員工。
select * from emp where deptno=30;
此查詢包含一個限定條件
列出全部業務員的姓名,編號和部門編號。
select empno 編號,ename 姓名,deptno 部門編號 from emp where job='CLERK';
此查詢應用了別名,單個限定條件,須要注意的是Oracle是區分大小寫的,因此咱們要將業務員大寫爲「CLERK」才能查詢出數據,或者使用upper()函數。
select empno 編號,ename 姓名,deptno 部門編號 from emp where job=upper('clerk');
找出佣金高於工資的僱員信息
select * from emp where comm&gt;sal;
此查詢爲單個限定條件的查詢
找出佣金高於工資的60%的僱員信息
select * from emp where comm&gt;sal*0.6;
此查詢使用了比較運算符和四則運算符
找出部門10中全部經理和部門20中全部業務員的詳細信息。
select * from emp where (deptno=10 and job='MANAGER') or (deptno=20 and job='CLERK');
此查詢使用了多限定查詢,邏輯運算符and 和 or ,而且使用()將多個限定條件包含做爲一個總體看待。
看一個比較複雜的需求。找出部門10中全部經理,部門20中全部業務員,既不是經理又不是業務員可是工資大於或等於2000的全部僱員信息。
select * from emp where (deptno=10 and job='MANAGER') or (deptno=20 and job='CLERK') or (sal&gt;=2000 and job not in('MANAGER','CLERK'));
找出領取佣金的僱員的不用工做。這個需求包含的信息有,工做會重複復,因此咱們須要使用關鍵字distinct消除重複的記錄,可以領取佣金說明comm is not null
select distinct job from emp where comm is not null;
找出不能領取佣金或者領取的佣金低於100的僱員信息
select * from emp where comm is null or comm&lt;100;
找出每月中倒數第三天僱傭的僱員信息,咱們分析下,Oracle爲咱們提供了一個叫作last_day()的函數,它的功能是查詢出指定日期的最後一天對應的日期,可是咱們這裏是要查詢倒數第三天,如何處理?咱們按照倒序的思想,將最後一天減去2不就獲得了倒數第三天嗎?
select * from emp where last_day(hiredate)-2=hiredate;
來一個頗有趣的需求,找出早於12年前僱傭的僱員信息,咱們將這個需求轉變下,咱們知道Oracle中有一個函數叫作months_between(),它的做用是查詢出給定的日期的差值,這個差值是月份數,因此,咱們這麼考慮
select * from emp where months_between(sysdate,hiredate)/12&gt;12;
看一個字符函數的應用。以首字母大寫的方式顯示全部僱員的姓名
select initcap(ename) from emp;
顯示僱員姓名長度正好是5的僱員姓名
select ename from emp where length(ename)=5;
顯示僱員姓名中不含「R」的僱員姓名
select ename from emp where ename not like '%R%';
此查詢使用了like語句作模糊查詢,當like後指定的關鍵字爲「%%」時,表示查詢出全部數據
顯示全部僱員姓名的前三個字符
select substr(ename,0,3) from emp;
select substr(ename,1,3) from emp;
此處應該強調的是,截取點的指定中,0和1的效果是同樣的。
顯示全部僱員的姓名,而且用「a」替換全部的「A」
select ename,replace(ename,'A','a') from emp;
此處要強調的是replace()函數的參數中,第一個表示須要作替換操做的列名稱,第二個參數是新的字符串,第三個參數表示的是原始的字符串,也就是須要替換的字符串。
顯示工齡爲10或以上的僱員姓名和僱傭日期
select ename,hiredate from emp where months_between(sysdate,hiredate)/12&gt;10;
顯示僱員的詳細信息,並按照姓名排序
select * from emp order by ename;
顯示僱員的姓名和僱傭時間,根據其工齡,將最老的僱員排在最前面
select ename,hiredate from emp order by hiredate;
顯示全部僱員的姓名、工做和工資,按照工做降序排列,若工做相同則按照工資排序
select ename,job,sal from emp order by job desc,sal;
顯示全部僱員的姓名、僱傭的年份,月份,按照僱傭日期所在月排序,若是月份相同則將最先的年份的僱員排在最前面。此需求首先要求出全部僱員的僱傭月份,使用to_char()函數求出月份
select ename,to_char(hiredate,'mm') month,to_char(hiredate,'yyyy') year from emp order by month,year;
顯示在一個月爲30天的狀況下全部僱員的日薪,忽略餘數。忽略餘數使用round()函數完成
select ename,round(sal/30) from emp;
找出在每一年2月份僱員的全部僱員信息
select * from emp where to_char(hiredate,'mm')=2;
此處仍是使用了to_char()函數求出月份
對於每一個僱員,顯示其到今天爲止的總天數
select ename,round(sysdate-hiredate) from emp;
顯示僱員姓名中包含「A」的全部僱員姓名
select ename from emp where ename like '%A%';
以年月日的方式顯示全部僱員的工齡。年,求出總月數/12,此時會產生小數,可是咱們不能再這裏進行四捨五入,而是採用trunc()函數獲得整數部分
select ename,trunc(months_between(sysdate,hiredate)/12) year from emp;
如今工齡的年獲得了,下面求出月份,咱們知道年除完以後的餘數就是月,使用取餘函數進行處理
select ename ,trunc(months_between(sysdate,hiredate)/12) year,trunc(mod(months_between(sysdate,hiredate),12)) month from emp;
獲得月份後,如何求出天數呢?咱們知道日期-日期獲得的是天數(須要作取整處理),將總天數/30(假設每個月爲30天)獲得的就是剩餘的天數值
select ename ,trunc(months_between(sysdate,hiredate)/12) year,trunc(mod(months_between(sysdate,hiredate),12)) month,trunc(mod(sysdate-hiredate,30)) day from emp;
這樣就完成了上面的查詢操做。
第三次
一、Oracle
1.一、多表查詢
1) 多表查詢的基本語法
前面的查詢都是針對一張表的操做,若是在查詢的時候涉及到多張表,那麼就稱爲多表查詢,奪標查詢的語法以下:
select *|具體的列名 from 表名稱1,表名稱2 where 條件表達式 order by 排序字段 asc|desc;
下面看一個例子,對emp表和dept表進行查詢
select * from emp,dept;
如此多的數據,咱們要向知道當前的記錄總數,如何操做呢?
select count(*) from emp,dept;--56
select count(*) from emp;--14
select count(*) from emp;--4
此處查詢使用count(*|具體的列名)查詢總記錄數
上面的三條查詢語句分別獲得了多表查詢,單表查詢的總記錄數,很明顯的看到,多表查詢的記錄數56並不等於單表查詢的總記錄數之和18,怎麼回事呢?由於,在進行多表查詢時,會產生笛卡爾積,若是表的數據越多,那麼笛卡爾積就會越大。若是如今有5張表,每張表有10000條數據,查詢5張表會產生10000的5次方條數據,因此在實際開發中多表查詢不建議過多的使用。
要向去掉笛卡爾積,能夠使用關聯來實現。如今咱們知道emp表中有字段deptno,dept表中有字段deptno,emp.deptno=dept.deptno就是灌籃字段。在多表查詢中加入where語句就能夠消除笛卡爾積
select * from emp,dept where emp.deptno=dept.deptno;
此時查詢的記錄數爲14條,可是若是表名過長的話,不方便咱們使用,因此通常咱們會爲表名設置別名,
select * from emp e,dept d where e.deptno=d.deptno;
若是在進行多表查詢時,最好爲表名設置別名
要求查詢出僱員的編號、僱員姓名、部門編號、部門名稱及部門位置
select e.empno,e.ename,e.deptno,d.dname,d.loc from emp e,dept d where e.deptno=d.deptno;
要求查詢出每一個僱員的姓名,工做,僱員的直接上級領導的姓名
select e.ename,e.job,m.ename from emp e,emp m where e.mgr=m.empno;
此處查詢將emp表作自身的關聯
繼續擴展以前的程序,要求將僱員素在部門名稱同時列出
select e.ename,e.job,m.ename,d.dname from emp e,emp m,dept d where e.mgr=m.empno and e.deptno=d.deptno;
查詢出每一個僱員的姓名,工資,部門名稱,工資等級,以及領導的姓名及工資所在公司的等級
先肯定工資等級表
select * from salgrade;
在查詢出每一個僱員的姓名,工資,部門名稱和工資等級
select e.ename,e.sal,d.dname,s.grade from emp e,dept d,salgrade s where e.deptno=d.deptno and e.sal between s.losal and s.hisal;
查詢其領導的姓名及工資等級
select e.ename,e.sal,m.ename,decode(ms.grade,1,'第五等工資',2,'第四等工資',3,'第三等工資',4,'第二等工資',5,'第一等工資'),decode(s.grade,1,'第五等工資',2,'第四等工資',3,'第三等工資',4,'第二等工資',5,'第一等工資'),d.dname from emp e,emp m,dept d,salgrade s,salgrade ms where e.mgr=m.empno and m.sal between ms.losal and ms.hisal and e.deptno=d.deptno and e.sal between s.losal and s.hisal;
2) 左、右鏈接
如今咱們先查詢下dept表中的數據
select * from dept;
能夠看到,dept表中包含了4條記錄,如今咱們將emp表和dept表關聯查詢,查詢一下指定的字段
select e.empno,e.ename,d.deptno,d.dname,d.loc from emp e,dept d where e.deptno=d.deptno;
有查詢結果能夠看到,部門表中的部門號只出現了3個,由於在僱員表中沒有指定40部門的僱員,可是咱們如今須要查看兩張表關聯後的完整信息,該如何進行呢?
select e.empno,e.ename,d.deptno,d.dname,d.loc from emp e,dept d where e.deptno(+)=d.deptno;
如今的結果中沒有指定僱員的部門信息也顯示出來了。這裏咱們使用到了右鏈接。有以下規律:
(+)在=左邊表示右鏈接,查詢時以=右邊的表做爲標準
(+)在=右邊表示左鏈接,查詢時以=左邊的表做爲標準
在前面咱們有過以下操做:查詢僱員的編號,姓名及其領導的編號、姓名
select e.empno,e.ename,m.ename from emp e,emp m where e.mgr=m.empno;
可是咱們仔細觀察會發現,僱員名稱爲KING的僱員信息沒有顯示出來,咱們知道KING爲president,沒有領導,因此按照上面的方式是不能查詢出來的,修改以下:
select e.empno,e.ename,m.ename from emp e,emp m where e.mgr=m.empno(+);
發如今加入作連接後KING出現了。
3) SQL:1999語法對SQL的支持
SQL:1999語法格式以下:
select table1.column,table2.column from table1
[cross join table2]|
[natural join table2]|
[join table2 using(column_name)]|
[join table2 on(table1.column_name=table2.column_name)]|
[left|right|full outer join table2 on(table1.column_name=table2.column_name)];
交叉鏈接(cross join):產生笛卡爾積
select * from emp cross join dept;--56
天然鏈接(natural join):自動進行關聯字段的匹配
select * from emp natural join dept;
至關於
select * from emp,dept where emp.deptno=dept.deptno;
using子句:直接關聯的操做列
select * from emp e join dept d using(deptno) where deptno=30;
on子句,用戶本身編寫鏈接的條件
select * from emp e join dept d on(e.deptno=d.deptno) where d.deptno=30;
左鏈接(左外鏈接)、右鏈接(右外鏈接):left join,right join
select e.ename,d.deptno,d.dname,d.loc from emp e right outer join dept d on(e.deptno=d.deptno);
1.二、組函數及分組統計
什麼是分組?
舉例吧,把全部男生分爲一組,把全部女生分爲一組。
若是想要求出每一組的平均身高,評價呢年齡等,就須要使用分組函數。
1) 組函數
在SQL中經常使用的組函數有如下幾個:
count()--&gt;求出所有的記錄數
max()--&gt;求出一組數據中的最大值
min()--&gt;求出一組數據中的最小值
avg()--&gt;求出平均值
sum()--&gt;求和
count()函數:
如今咱們須要查詢出emp中有多少個僱員
select count(*) from emp;--14
max()、min(),求最大最小值,通常是針對數字的應用
求出全部僱員的最低工資
select min(sal) from emp;
求出全部僱員的最高工資
select max(sal) from emp;
sum()、avg(),求和,求平均值
求出部門20中的總工資
select sum(sal) from emp where deptno=20;
求出全部僱員的平均工資
select avg(sal) from emp;
2) 分組統計
要想使用分組統計,則首先應該固定其語法,使用group by進行分組,此時SQL語法格式以下:
select *|具體的列
from 表名稱1
where 條件表達式
group by 分組條件
order by 排序字段 asc|desc
求出每一個部門的僱員數量,這裏須要按照部門編號劃分,及按照deptno分組
select deptno,count(empno) from emp group by deptno;
求出每一個部門的平均工資
select deptno,avg(sal)
from emp
group by deptno;
如今,咱們觀察下面的一行代碼:
select deptno,count(empno) from emp;
以上代碼不能正確執行,報錯爲:不是單組分組函數,爲何呢?
若是程序中使用了分組函數,則有兩種能夠使用的狀況:
1-程序中存在了group by,並指定了分組條件,這樣能夠將分組條件一塊兒查詢出來。
2-若是不使用分組的話,則只能單獨的使用分組函數
在使用分組函數的時候,不能出現分組函數和分組條件以外的字段。
看下面的代碼:
select deptno,empno,count(empno) from emp group by deptno;
程序會報錯,提示empno不是group by表達式,由於在這裏,咱們使用了組函數count(empno),group by deptno,根據先前的規則,empno的出現是不合法的。
按照部門分組,並顯示部門的名稱,及每一個部門的員工數
select d.dname,count(e.ename) from dept d,emp e where d.deptno=e.deptno group by d.dname;
要求顯示出平均工資大於2000的部門編號和平均工資
select deptno,avg(sal) from emp where avg(sal)&gt;2000 group by deptno;
程序報錯,提示avg(sal)&gt;2000處不容許使用分組函數。由於分組函數只能在分組中使用,不容許出如今where語句之中,那麼若是如今假設要指定分組的條件,則只能經過第二種條件的指令,having,此時SQL語法格式爲:
select * | 具體的列名
from 表名稱
where 條件表達式
group by 分組條件
having 分組條件
order by 排序字段 asc|desc
因此,咱們使用having完成上面的操做
select deptno,avg(sal) from emp group by deptno having avg(sal)&gt;2000;
下面咱們看一個這樣的需求:顯示非銷售人員工做名稱以及從事同一工做的僱員的月工資的總和,而且要知足從事同一工做的僱員的月工資合計大於5000,輸出結果按照月工資的合計升序排列
·-首先咱們查詢出所有的非銷售人員,限定條件job&lt;&gt;'SALESMAN'
select * from emp where job&lt;&gt;'SALESMAN';
·-按照工做名稱分組,而且求出每組的工資總和
select job,sum(sal) from emp
where job&lt;&gt;'SALESMAN'
group by job;
·-對分組的調價進行限制,工資總和大於5000
select job,sum(sal) from emp
where job&lt;&gt;'SALESMAN'
group by job
having sum(sal)&gt;5000;
·-對查詢結果按照月工資的合計升序排列
select job,sum(sal) from emp
where job&lt;&gt;'SALESMAN'
group by job
having sum(sal)&gt;5000
order by sum(sal) asc;
下面咱們總結下分組的簡單原則:
--只要一列上存在重複的內容纔有可能考慮到分組
使用分組時的注意點:
--分組函數能夠嵌套使用,可是在組函數嵌套使用的時候不能再出現分組條件的查詢語句
例如,咱們要求求出平均工資最高的部門工資
select deptno,max(avg(sal)) from emp
group by deptno;
程序會報錯,提示deptno不是單組分組函數
修改代碼以下:
select max(avg(sal)) from emp
group by deptno;
1.三、子查詢
子查詢:在一個查詢的內部還包括另一個查詢,則此查詢稱爲子查詢,子查詢的格式以下:
select * | 具體的列名稱
from 表名稱
where 條件表達式(
select * | 具體的列名稱
from 表名稱
where 條件表達式(
...
)
group by 分組條件
having 分組條件
order by 排序字段 asc|desc
)
group by 分組條件
having 分組條件
order by 排序字段 asc|desc
要求查詢出比7654工資要高的所有僱員信息
·-首先要知道7654僱員的工資是多少
select sal from emp where empno=7654;
·-上面查詢的結果做爲最後查詢的子查詢結果,只要是其餘的工資大於上面的查詢結果,則表示符合條件。
select * from emp where sal&gt;(select sal from emp where empno=7654);
應該要強調的是,全部的子查詢語句必須在「()」中編寫。
子查詢在操做上分爲三類:
單列子查詢:返回的結果是某列的一個內容,出現的概率最高
單行子查詢:返回多個列,有多是一條完整的記錄
多行子查詢:返回多條記錄
要求查詢出工資比7654高,同時與7788從事相同工做的所有僱員信息
·-查詢出7654的工資
select sal from emp where empno=7654;
·-查詢出7788的工做名稱
select job from emp where empno=7788;
·-總和查找
select * from emp where sal&gt;(select sal from emp where empno=7654) and job=(select job from emp where empno=7788);
要求查詢出工資最低的僱員姓名,工做,工資
·-求出最低工資
select min(sal) from emp;
·-以最低工資爲條件進一步查詢
select ename,job,sal from emp
where sal=(select min(sal) from emp);
要求查詢出:部門名稱,部門的員工數,部門的平均工資,部門的最低收入的僱員姓名,此時,程序須要兩張表關聯:dept、emp
·-若是要想求出每一個部門的員工數,平均工資,要使用分組統計,這裏咱們按照deptno進行分組
select deptno,count(empno),avg(sal) from emp
group by deptno;
·-可是咱們要查詢的是部門的名稱,因此這裏須要與dept表進行關聯
select d.dname,ed.c,ed.a
from dept d,
(select deptno,count(empno) c,avg(sal) a from emp
group by deptno) ed
where d.deptno=ed.deptno;
·-求出最低收入的僱員姓名
select d.dname,ed.c,ed.a,e.ename
from dept d,(select deptno,count(empno) c,avg(sal) a,min(sal) min from emp
group by deptno) ed,emp e
where d.deptno=ed.deptno and e.sal=ed.min;
可是此程序中有一個問題,若是一個部門中同時存在兩個給你工資最低的僱員,則程序會出現錯誤。
在子查詢中,存在如下三種查詢的操做符號:
in、any、all
in操做符的做用是指定一個查詢的範圍
求出每一個部門的最低工資的僱員信息。
分析:每一個部門的最低工資,返回值確定是多個,因此此時能夠使用in指定一個操做範圍。
select * from emp
where sal in(select min(sal) from emp group by deptno);
any操做符的通常用法:=any(與in操做符的功能徹底同樣)、&gt;any(比裏面最小的值要大)、&lt;any(比裏面最大的值要小)
select * from emp
where sal=any(select min(sal) from emp group by deptno);
all操做符的通常用法:&gt;all(比最大值要大)、&lt;all(比最小值要小)
select * from emp
where sal&gt;all(select min(sal) from emp group by deptno);
對於子查詢來說,還能夠進行多列子查詢,一個子查詢中同時返回多個查詢的列。
select * from emp
where (sal,nvl(comm,-1)) in(select sal,nvl(comm,-1) from emp where deptno=20);
1.四、數據庫更新操做
數據庫的主要操做分爲兩種:
--數據庫的查詢操做:select
--數據庫的更新操做:insert、update、delete
此時,爲了保存原始的emp表的信息,在進行增長、修改、刪除操做以前,先將此表複製一份
create table myemp as select * from emp;
1) 添加數據
添加數據的語法是:
insert into 表名稱[(字段名1,字段名2,......)] values(值1,值2,......);
爲myemp表添加一條新的記錄,按照標準的作法完成
insert into myemp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7899,'張三','清潔工',7369,'14-2月 -1995',9000,300,40);
在添加數據時,須要強調的是:對於數字,不用加單引號,可是字符串必須加上單引號。能夠使用簡略寫法,當咱們想所有的阻斷插入數據時,能夠不用指定須要插入數據的字段名,可是,咱們並不推薦這種寫法,由於這樣寫的壞處在於,當咱們向部分字段插入數據時,須要和表的字段順序一一對一個才能插入成功,而使用標準寫法時,只須要指定的字段名和value中的值一一對應就能夠完成插入操做。
插入部分數據,如今要求插入一個新的僱員,可是此僱員暫時沒有領導,也沒有獎金,也就是說,在插入數據的時候,mgr和comm字段的值要置空。
第一種作法:不明確寫出要插入的字段名 ,沒有數據的字段寫成null
insert into myemp values(8889,'王五','清潔工',null,'14-2月 -1982',9000,null,40);
第二種作法:明確寫出要插入的字段名
insert into myemp(empno,ename,job,hiredate,sal,deptno) values(8889,'王五','清潔工','14-2月 -1982',9000,40);
在上面的插入操做中,咱們應該發現了這麼一個問題,插入的日期都是按照Oracle默認的日期格式進行書寫的,可是,如今有一個「2009-01-19」這樣格式的日期,該如何插入到數據庫表中呢?咱們英愛還記得在前面學習單行函數的時候,介紹了一個叫作to_date()的函數,該函數的功能是將一個字符串類型的數據變爲date類型的數據。
insert into myemp(empno,ename,job,hiredate,sal,deptno) values(8888,'趙六','保潔工',to_date('2009-01-19','yyyy-mm-dd'),9000,40);
2) 修改數據
在SQL語法中使用update語句就能夠完成數據的修改功能,此語句的語法格式以下:
修改所有:update 表名稱 set 要修改的字段=新值,要修改的字段=新值,......;
修改局部:update 表名稱 set 要修改的字段=新值,要修改的字段=新值,...... where 修改條件;
可是,從通常的開發角度上講,咱們都在修改數據時加上修改條件
如今將myemp表中的全部僱員的獎金修改成1000--&gt;修改所有
update myemp set comm=1000;
將編號爲7899的僱員的工資修改成5000--&gt;指定了更新條件
update myemp set sal=5000 where empno=7899;
將編號爲7899的僱員的領導取消
update myemp set mgr=null where empno=7899;
注意點:在進行數據庫更新的操做時,必定要寫上更新的條件,拒絕批量更新。
將736九、889九、7788的領導及獎金取消
update myemp set mgr=null,comm=null where empno in(7369,7788,8899);
3) 刪除數據
在SQL語法中能夠使用delete命令刪除記錄,語法格式以下:
刪除所有:delete from 表名稱;
刪除局部:delete from 表名稱 where 刪除條件;
刪除編號是7899的僱員信息
delete from myemp where empno=7899;
刪除編號是8889,7889,8888的僱員信息
delete from myemp where empno in(8889,7889,8888);
刪除掉所有領取獎金的僱員
delete from myemp where comm is not null;
刪除表的所有內容,此時不須要指定刪除條件
delete from myemp;
在實際開發中不建議使用所有刪除,在執行刪除命令的時候都要指定刪除條件。
1.五、事務處理
建立一個只包含10部門僱員信息的臨時表
create table emp10 as select * from emp where deptno=10;
刪除emp10中7782的僱員信息
delete from emp10 where empno=7782;
當咱們再次查詢emp10表的數據時,該數據確實刪除了,接下來,咱們作以下操做,再次開啓一個sqlplus窗口,再次查詢emp10的數據,咱們發現僱員編號爲7782的僱員信息仍然存在,這是爲何?
這就是Oracle中事務處理的概念了。
事務處理:所謂事務處理就是保證數據的完整性,全部的操做要麼同時成功,要麼同時失敗。
在Oracle中對於每個鏈接到數據庫的窗口(sqlplus、sqlplusw)鏈接以後實際上都會與數據庫創建一個session,即:每個鏈接到數據庫上的用戶表示建立了一個session。
一個session對數據庫所作的修改,不會馬上反映到數據庫的真實數據之上,是容許回滾的,當一個session提交全部的操做以後,數據庫才真正的作出了修改。
在數據庫的操做中提供瞭如下兩個主要命令完成事物的處理:
--提交事物:commit
--回滾事物:rollback
若是數據已經被提交了則確定沒法回滾,因此,回滾只有在事物未被提交時纔有效。
在Oracle中關於事物的處理上夜壺存在一種死鎖的概念。
一個session若是更新了數據庫中的記錄,其餘session是沒法馬上更新的,要等待對方提交以後才容許更新。
下面咱們來測試下Oracle的事務處理是如何進行的。
首先,咱們在窗口1中查詢出emp10的數據
select * from emp10;
如今作一個更新的操做,將編號爲7934的僱員的工資更改成3000
update emp10 set sal=3000 where empno=7934;
如今咱們再次查詢emp10的數據,發現,編號爲7934的僱員工資確實更改成3000來 ,可是咱們應該知道,對於這個更新操做,咱們是沒有提交的,咱們如今再打開一個窗口,查詢emp10的數據,發現編號爲7934的僱員工資仍是1300,這就驗證了咱們所說的「事物未提交」,接下來,咱們在窗口2中進行一個更新操做,將7839的獎金設置爲10000
update emp10 set comm=10000 where empno=7839;
下面咱們在窗口1中提交事物
在窗口2中再次查詢emp10的數據,更新成功。
在窗口2中提交事物
一樣在窗口1中查詢emp10的數據,更新成功。
1.六、查詢練習
列出至少有一個員工的全部部門
select deptno ,count(empno) from emp
group by deptno;
此查詢使用了組函數,分組,注意,若是不加分組,該程序會報錯
列出部門人數大於1的全部部門編號
select deptno,count(empno) from emp
group by deptno having count(empno)&gt;1;
這裏沒使用where設置查詢限定條件,由於where子句中時不能出現函數的。
經過部門表,查詢出部門的信息
select d.*,ed.cou from dept d,(select deptno,count(empno) cou from emp
group by deptno) ed
where d.deptno=ed.deptno;
列出工資比「SMITH」多的全部僱員。
--求出SMITH的工資
select sal from emp where ename='SMITH';
--將上面的結果做爲查詢條件,只要工資比上面的結果大的就是符合條件的
select * from emp where sal&gt;(select sal from emp where ename='SMITH');
列出全部員工的姓名和其直接上司的姓名
--此程序屬於自身關聯查詢,爲了獲得KING,咱們使用左鏈接查詢,以等號左邊的表爲標準
select e.ename,m.ename from emp e,emp m
where e.mgr=m.empno(+);
列出僱傭日期早於其直接上級的全部僱員的編號、姓名和部門名稱
--自身關聯,查找mgr=empno的同時還要比較hiredate,咱們先查詢編號和姓名
select e.empno,e.ename
from emp e,emp m
where e.mgr=m.empno and e.hiredate&lt;m.hiredate;
--若是要加入部門名稱,咱們須要加入dept表,作表關聯查詢
select e.empno,e.ename,d.dname
from emp e,emp m,dept d
where e.mgr=m.empno and e.hiredate&lt;m.hiredate and e.deptno=d.deptno;
列出部門名稱和這些部門的僱員信息,同時列出那些沒有僱員的部門
--左右關聯問題,以=右邊的表爲標準
select d.deptno,d.dname,e.empno,e.ename
from dept d,emp e
where d.deptno=e.deptno(+);
列出全部「CLERK」的姓名和其部門名稱,部門的人數
--找出全部CLERK的姓名和部門編號
select ename,deptno from emp
where job='CLERK';
--要想查詢部門名稱,則必須使用dept表
select e.ename,d.dname from emp e,dept d
where job='CLERK' and e.deptno=d.deptno;
--部門人數要用到分組完成,一旦使用分組,確定是group by
select e.ename,d.dname,ed.cou
from emp e,dept d,(select deptno, count(empno) cou from emp group by deptno) ed
where job='CLERK' and e.deptno=d.deptno and ed.deptno=e.deptno;
列出最低工資大於1500的各類工做以及從事此工做的所有僱員人數
--按工做分組,分組條件是最低工資大於1500
select job,min(sal) from emp
group by job having min(sal)&gt;1500;
--工做就出來了,以後再求所有的僱傭人數
select e.job,count(e.empno)
from emp e
where e.job in(
select job from emp
group by job having min(sal)&gt;1500
)
group by e.job;
列出在部門「SALES」工做的員工姓名,假定不知道銷售部的部門編號
--經過dept表查詢出銷售部的部門編號
select deptno from dept where dname='SALES';
--將上面的查詢結果做爲下一步查詢的條件
select ename from emp
where deptno=(
select deptno from dept where dname='SALES'
);
列出工資高於公司平均工資的所願僱員,所在部門,上級領導,公司的工資等級
--求出公司的平均工資
select avg(sal) from emp;
--列出工資高於平均工資的僱員信息
select * from emp where sal&gt;(select avg(sal) from emp);
--與部門表關聯,查出所在部門的信息
select e.*,d.dname,d.loc from emp e,dept d
where sal&gt;(select avg(sal) from emp) and e.deptno=d.deptno;
--要想查出上級領導,須要和自身進行關聯查詢
select e.empno,e.ename,m.ename,m.empno,d.deptno,d.dname,d.loc
from emp e,dept d,emp m
where e.sal&gt;(select avg(sal) from emp)
and e.deptno=d.deptno
and e.mgr=m.empno(+);
--與工資等級表關聯,查出工資等級
select e.empno,e.ename,s.grade,m.ename,m.empno,d.deptno,d.dname,d.loc
from emp e,dept d,emp m,salgrade s
where e.sal&gt;(select avg(sal) from emp)
and e.deptno=d.deptno
and e.mgr=m.empno(+)
and e.sal between s.losal and s.hisal;
列出與scott從事相同工做的全部僱員及部門名稱
--找到scott的工做
select job from emp where ename='SCOTT';
--找到和上面查詢工做相同的僱員
select * from emp where job=(select job from emp where ename='SCOTT');
--使用dept表查詢出所在部門名稱
select e.*,d.dname from emp e,dept d
where job=(select job from emp where ename='SCOTT')
and ename!='SCOTT'
and d.deptno=e.deptno;
列出工資等於部門30中僱員的工資的全部僱員姓名和工資
--查出部門30中僱員的工資
select sal from emp where deptno=30;
--找出工資等於上面結果的僱員姓名
select ename,sal from emp
where sal in(select sal from emp where deptno=30)
and deptno!=30;
列出工資高於在30部門工做的全部僱員的工資的僱員姓名和工資,部門名稱
--在以前的程序上進行修改,使用&gt;all,比最大的還要大
select ename,sal
from emp where sal&gt;all(
select sal from emp where deptno=30
)
and deptno!=30;
--使用dept表,查詢出部門名稱
select e.ename,e.sal,d.dname from emp e,dept d
where sal&gt;all(
select sal from emp where deptno=30
)
and e.deptno!=30
and e.deptno=d.deptno;
列出在每一個部門工做的僱員數量,平均工資和平均工齡
--求出每一個部門的僱員數量,按照部門名稱分組
select d.dname,count(e.empno)
from emp e,dept d
where e.deptno=d.deptno
group by d.dname;
--求出每一個部門的平均工資和工齡
select d.dname,count(e.empno),avg(e.sal),avg(months_between(sysdate,hiredate)/12) 年
from emp e,dept d
where e.deptno=d.deptno
group by d.dname;
列出全部僱員的姓名、部門名稱和工資
--直接兩張表關聯
select e.ename,e.sal,d.dname
from emp e,dept d
where e.deptno=d.deptno;
列出全部部門的詳細信息和部門的人數
--列出每一個部門的僱員人數
select deptno,count(empno) cou
from emp
group by deptno;
--把以上的查詢做爲一張臨時表
select d.*,ed.cou from dept d,
(select deptno dto,count(empno) cou from emp group by deptno ) ed
where d.deptno=ed.dto;
查詢結果中沒包含40部門,修改以下
select d.*,nvl(ed.cou,0) from dept d,
(select deptno dto,count(empno) cou from emp group by deptno ) ed
where d.deptno=ed.dto(+);
列出各類工做的最低工資及從事此工做的僱員姓名
--按照工做分組,使用min()求出最低工資
select job,min(sal) from emp group by job;
--按照工資查詢出僱員的信息
select * from emp
where sal in(select min(sal) from emp group by job);
列出各個部門的MANAGER的最低工資
select deptno,min(sal)
from emp
where job='MANAGER'
group by deptno;
列出全部僱員的年薪,按照年薪從低到高排序
select ename,(sal+nvl(comm,0))*12 yearsal from emp order by yearsal asc;
查詢某個僱員的上級主管,並求出這些主管中的薪水超過3000的
select distinct m.* from emp e,emp m
where e.mgr=m.empno and m.sal&gt;3000;
求出部門名稱中帶「S」的部門僱員的工資合計和部門人數
--查詢部門表的部門名稱,使用模糊查詢,來肯定部門的編號
select deptno from dept where dname like '%S%';
--查詢出符合上述條件的僱員工資合計和部門人數
select deptno,sum(sal),count(empno) from emp
where deptno in(select deptno from dept where dname like '%S%')
group by deptno;
第四次
一、Oracle
1.一、 建立和管理表
1) 經常使用的數據類型
varchar\varchar2--&gt;表示的是一個字符串,有長度限制,255,
number--&gt;number(n):表示一個整數,數字的長度是n,能夠使用int
number(m,n):表示一個小數,數字小數長度爲n,整數長度爲m-n,能夠使用float
date--&gt;表示日期的類型,日期要按照標準的日期格式進行存放
clob--&gt;大對象,表示大文本數據,通常能夠存放4G的文本
blob--&gt;大對象,表示二進制數據,最大能夠存放4G,如:電影,歌曲,圖片
2) 表的創建
表的創建仍是按照標準的語法進行,可是在表的創建時有時候會指定約束,那麼此處先給出一個創建表的簡單語法。
create table 表名稱(
字段名稱1 字段類型 [default 默認值],
字段名稱2 字段類型 [default 默認值],
....
字段名稱n 字段類型 [default 默認值]
)
在前面咱們使用了一種這樣的語法來建立表:
create table 表名稱 as (子查詢)--將子查詢的結果做爲一張表
若是如今子查詢寫的是:select * from emp;表示將表結構和表的內容一塊兒複製
若是如今子查詢寫的是:select * from emp where 1=2;加入了一個永遠都不會成立的條件,則此時表示咱們複製的只是表的結構,不復製表的內容
複製表結構:
create table temp as(select * from emp where 1=2);
3) 表的刪除
表的刪除語法以下:
drop table 表名稱;
4) 表的修改
在SQL語法操做中,提供了alter指令,經過alter指令就能夠增長新的列
爲emp表添加一個address列
alter table emp add(address varchar2(200) default'暫無地址');
修改emp表中的ename,將長度改成50
alter table emp modify(ename varchar2(50));
5) 爲表重命名
在Oracle中提供了rename命令,能夠爲表從新進行命名,可是此語句只能在Oracle中使用。語法格式以下:
rename 舊的表名稱 to 新的表名稱;
6) 截斷表
若是如今咱們須要清空一張表的數據,可是同時不須要回滾,能夠馬上釋放資源就須要使用截斷表的語法:
truncate table 表名稱;
思考下面的問題:如今有一張國家表,裏面只有一個國家名稱的字段,內容以下:「中國、美國、巴西、荷蘭「,如今要求經過查詢實現對戰功能:
中國-&gt;美國
中國-&gt;巴西
中國-&gt;荷蘭
美國-&gt;中國
美國-&gt;巴西
美國-&gt;荷蘭
......
分析:本程序只能使用笛卡爾積完成
首先,創建一張表
create table national(
name varchar2(30)
)
向表中增長測試數據
insert into national(name) values('中國');
insert into national(name) values('美國');
insert into national(name) values('巴西');
insert into national(name) values('荷蘭');
查詢的時候表本身和本身關聯
select n1.name,n2.name from national n1,national n2 where n1.name&lt;&gt;n2.name;
1.二、約束
在數據庫表的開發中,餘數是必不可少的支持。使用約束能夠更好的保證數據庫中的數據完整性。
數據庫中的約束分類:
--在實際中,約束主要分爲如下五種:
···主鍵約束primary key:主鍵表示是一個惟一的標識,自己是不能爲空的
|-例如:身份證號是惟一的,不可重複,不可爲空
···惟一約束unique:在一個表中只容許創建一個主鍵約束,而其餘列若是不但願出現重複值的話,則能夠使用惟一約束。
···檢查約束:檢查一個列的內容是否合法
|-例如:年齡。只能在0~150之間
|-例如:性別,只能是男、女、中性
···非空約束:姓名這樣的字段裏面的內容就不能爲空
···外鍵約束:在兩張表中進行約束操做。
1) 主鍵約束(primary key)
主鍵約束通常都是使用在id上,並且自己已經默認了內容不能爲空,主鍵約束能夠再建表的時候指定
如今咱們創建一張person表,在pid上增長主鍵約束
drop table person;
create table person(
pid varchar2(18) primary key,
name varchar2(200),
age number(3),
birthday date,
sex varchar2(3) default '男'
)
如今咱們向表中插入數據
insert into person(pid,name,age,birthday,sex) values('1111111111111111','張三',30,to_date('1976-08-09','yyyy-mm-dd'),'女');
insert into person(pid,name,age,birthday,sex) values('1111111111111111','李四',30,to_date('1976-08-04','yyyy-mm-dd'),'男');
當插入第二條語句時,會提示:違反惟一約束,那麼咱們將pid的值設置爲null
insert into person(pid,name,age,birthday,sex) values(null,'李四',30,to_date('1976-08-04','yyyy-mm-dd'),'男');
一樣會提示錯誤:沒法將 NULL 插入 ("SCOTT"."PERSON"."PID"),以上的約束是系統自動分配好的約束名稱,也能夠經過constraint指定一個約束的名字,
將person表的pid指定名稱
drop table person;
create table person(
pid varchar2(18),
name varchar2(200),
age number(3),
birthday date,
sex varchar2(3) default '男',
constraint person_pid_pk primary key(pid)
)
2) 非空約束(not null)
使用非空約束,表示一個字段的內容不容許爲空,即:插入數據的時候必須插入內容
drop table person;
create table person(
pid varchar2(18),
name varchar2(200) not null,
age number(3) not null,
birthday date,
sex varchar2(3) default '男',
constraint person_pid_pk primary key(pid)
)
3) 惟一約束(unique)
表示一個字段中的內容是惟一的,其餘列不容許重複。
假設:如今姓名不容許出現重名的狀況
drop table person;
create table person(
pid varchar2(18),
name varchar2(200) unique not null,
age number(3) not null,
birthday date,
sex varchar2(3) default '男',
constraint person_pid_pk primary key(pid)
)
4) 檢查約束(check)
使用檢查約束來判斷一個列中插入的內容是否合法,例如,年齡的取值範圍,性別的取值範圍
drop table person;
create table person(
pid varchar2(18),
name varchar2(200) unique not null,
age number(3) not null check(age between 0 and 150),
birthday date,
sex varchar2(3) default '男' check(sex in('男','女','中')),
constraint person_pid_pk primary key(pid)
)
5) 主-外鍵約束(foreign key)
以前的約束都是針對一張表的,那麼主-外鍵約束是針對兩張表的約束。爲何須要主-外鍵約束呢?
要求完成一個程序,一本書只屬於一我的
書自己應該是一張表,一本書中必然有一個字段表示屬於某我的的
drop table person;
drop table book;
create table person(
pid varchar2(18),
name varchar2(200) not null,
age number(3) not null,
birthday date,
sex varchar2(3) default '男',
constraint person_pid_pk primary key(pid),
constraint person_name_uk unique(name),
constraint person_age_ck check(age between 0 and 150),
constraint person_sex_ck check(sex in('男','女','中'))
);
create table book(
bid number primary key not null,
bname varchar2(20),
bprice number(5,2),
pid varchar2(18)
);
insert into person(pid,name,age,birthday,sex) values('1111111111111111','張三',30,to_date('1976-08-09','yyyy-mm-dd'),'女');
insert into book(bid,bname,bprice,pid) values(1,'JAVA SE',89.9,'0000000000000');
在插入第二條數據前,咱們看看pid字段的值,很明顯,在咱們的person表中不存在這樣的person,那麼, 這樣的數據時不該該插入到數據庫中的,爲了解決這樣的問題,咱們使用主-外鍵關聯,關聯以後字表的數據要跟隨父表的數據內內容。
drop table person;
drop table book;
create table person(
pid varchar2(18),
name varchar2(200) not null,
age number(3) not null,
birthday date,
sex varchar2(3) default '男',
constraint person_pid_pk primary key(pid),
constraint person_name_uk unique(name),
constraint person_age_ck check(age between 0 and 150),
constraint person_sex_ck check(sex in('男','女','中'))
);
create table book(
bid number primary key not null,
bname varchar2(20),
bprice number(5,2),
pid varchar2(18),
constraint person_book_pid_fk foreign key(pid) references person(pid)
);
如今咱們再次執行數據的插入操做,此時系統提示:違反完整約束條件 (SCOTT.PERSON_BOOK_PID_FK) - 未找到父項關鍵字,根據上面的分析沒咱們修改以下:
insert into book(bid,bname,bprice,pid) values(1,'JAVA SE',89.9,'1111111111111111');
此時插入數據成功。
在使用主-外鍵關聯的時候有幾點須要注意:
|-在子表中設置的外鍵在父表中必須是主鍵
|-刪除時應該先刪除子表,再刪除父表
在主-外鍵關聯中也能夠使用級聯刪除
以現有數據庫中的數據爲例
delete from person where pid='1111111111111111';
要刪除person表中編號爲1111111111111111的人員,可是這我的在book表中存在一本書的記錄。提示錯誤:違反完整約束條件 (SCOTT.PERSON_BOOK_PID_FK) - 已找到子記錄,那麼,若是想刪除成功必須先刪除book表中pid對應的記錄,再刪除此人的信息
若是咱們但願一個表中的數據在刪除時,能夠自動刪除掉其對應的子表記錄,則能夠使用級聯刪除來實現。
drop table person;
drop table book;
create table person(
pid varchar2(18),
name varchar2(200) not null,
age number(3) not null,
birthday date,
sex varchar2(3) default '男',
constraint person_pid_pk primary key(pid),
constraint person_name_uk unique(name),
constraint person_age_ck check(age between 0 and 150),
constraint person_sex_ck check(sex in('男','女','中'))
);
create table book(
bid number primary key not null,
bname varchar2(20),
bprice number(5,2),
pid varchar2(18),
constraint person_book_pid_fk foreign key(pid) references person(pid) on delete cascade
);
6) 修改約束
若是一張表已經創建完成,則能夠爲其添加約束
關於約束類型的命名,必定要統一:
--primary key--&gt;主鍵字段_pk
--unique--&gt;字段_uk
--check--&gt;字段_ck
--foreign key--&gt;父字段_子字段_fk
爲person添加一個約束
alter table person add constraint person_pid_pk primary key(pid);
將person的主鍵約束刪除掉該怎麼操做呢?
alter table person drop constraint person_pid_pk;
1.三、rownum
rownum:表示行號,實際上這是一個列的列名,可是這個列咱們稱爲僞列,此列尅在每張表中出現。
例如,在咱們查詢僱員表的時候,加上rownum這個列名稱
select rownum,empno,ename,job,sal,hiredate from emp;
從執行的效果來看,rownum自己採用自動編號的形式出現。
咱們擴展下rownum的應用,如今咱們只想顯示前5條僱員信息,該如何實現呢?
select rownum,empno,ename,job,sal,hiredate from emp where rownum&lt;=5;
既然能夠查詢前5條數據,那麼,咱們如今要求提升了,查詢中間的5條數據
select rownum,empno,ename,job,sal,hiredate from emp where rownum between 5 and 10;
看似沒有問題的語句卻查不出數據來,到底哪裏出錯了呢?
若是如今要想進行中間的截取操做,則只能採用子查詢,例如如今假設每頁顯示5條,第二頁應該顯示6~10條,那麼對於數據庫操做來說,它在查詢的時候應該首先查詢出1~10條,以後再在查詢的結果中截取出後5條。
select * from (select rownum m,empno,ename,job,sal,hiredate from emp where rownum&lt;=10) temp where temp.m&gt;5;
若是如今要求輸出最後的4條呢?
select * from (select rownum m,empno,ename,job,sal,hiredate from emp where rownum&lt;=15) temp where temp.m&gt;10;
1.四、集合操做
在Oracle中提供了三種類型集合的操做,並(union)、交(intersect)、差(minus)
|-union:將多個查詢的結果組合到一個查詢結果中,沒有重複的內容
|-union all:將多個查詢結果組合到一個查詢之中,可是包含了重複值
|-intersect:返回多個查詢結果中相同的部分
|-minus:返回兩個查詢結果的差集
爲了更好的觀察查詢結果,咱們將複製emp表,將20部門的僱員信息取出來
create table emp20 as select * from emp where deptno=20;
1) 驗證union
返回兩個集合的全部內容,不包含重負的內容
select * from emp
union
select * from emp20;
2) 驗證union all
返回兩個集合的全部內容,包含重複內容
select * from emp
union all
select * from emp20;
3) 驗證intersect
返回多個查詢結果中相同的部分
select * from emp
intersect
select * from emp20;
由於兩張表中只有20部門的僱員信息是重複的,全部實際上返回的相同內容就是表emp20的內容
4) 驗證minus
返回兩個查詢結果的差集
select * from emp
minus
select * from emp20;
1.五、交表、約束、查詢綜合練習
題目背景:
有某個學生運動會比賽信息的數據庫,保存了以下的表:
|-運動員sporter(運動員編號sporterid,運動員姓名name,運動員性別sex,所屬系號department)
|-項目item(項目編號itemid,項目名稱itemname,項目比賽地點location)
|-成績grade(運動員編號sporterid,項目編號itemid,積分mark)
功能要求
1) 建表
--定義各個表的主碼外碼約束
--運動員的姓名和所屬系別不能爲空值
--積分要麼爲空值,要麼爲六、四、二、0,分別表明第1、第2、第三和其餘名次的積分
create table sporter(
sporterid number(4) primary key not null,
name varchar2(50) not null,
sex varchar2(3) not null,
department varchar2(30) not null,
constraint sporter_sex_ck check(sex in('男','女'))
);
create table item(
itemid varchar2(4) primary key not null,
itemname varchar2(50) not null,
location varchar2(50) not null
);
create table grade(
sporterid number(4),
itemid varchar2(4),
mark number(2),
constraint sporter_grade_sporterid_fk foreign key(sporterid) references sporter(sporterid) on delete cascade,
constraint sporter_item_itemid_fk foreign key(itemid) references item(itemid) on delete cascade,
constraint grade_mark_ck check(mark in(6,4,2,0))
);
2) 數據
運動員sporter
insert into sporter(sporterid,name,sex,department) values(1001,'李明','男','計算機系');
insert into sporter(sporterid,name,sex,department) values(1002,'張三','男','數學系');
insert into sporter(sporterid,name,sex,department) values(1003,'李四','男','計算機系');
insert into sporter(sporterid,name,sex,department) values(1004,'王二','男','物理系');
insert into sporter(sporterid,name,sex,department) values(1005,'李娜','女','心理系');
insert into sporter(sporterid,name,sex,department) values(1006,'孫儷','女','數學系');
項目item
insert into item(itemid,itemname,location) values('x001','男子五公里','一操場');
insert into item(itemid,itemname,location) values('x002','男子標槍','一操場');
insert into item(itemid,itemname,location) values('x003','男子跳遠','二操場');
insert into item(itemid,itemname,location) values('x004','女子跳高','二操場');
insert into item(itemid,itemname,location) values('x005','女子三公里','三操場');
積分grade
insert into grade(sporterid,itemid,mark) values(1001,'x001',6);
insert into grade(sporterid,itemid,mark) values(1002,'x001',4);
insert into grade(sporterid,itemid,mark) values(1003,'x001',2);
insert into grade(sporterid,itemid,mark) values(1004,'x001',0);
insert into grade(sporterid,itemid,mark) values(1001,'x003',4);
insert into grade(sporterid,itemid,mark) values(1002,'x003',6);
insert into grade(sporterid,itemid,mark) values(1004,'x003',2);
insert into grade(sporterid,itemid,mark) values(1005,'x004',6);
insert into grade(sporterid,itemid,mark) values(1006,'x004',4);
3) 要求
求出目前總積分最高的系名,及其積分
--全部的系名都在sporter表中,而積分在grade表中,因此sporter和grade進行關聯查詢
select s.department,sum(g.mark) sum
from sporter s,grade g
where s.sporterid=g.sporterid
group by s.department
order by sum desc;
--使用rownum最方便
select * from(
select s.department,sum(g.mark) sum
from sporter s,grade g
where s.sporterid=g.sporterid
group by s.department
order by sum desc)
where rownum=1;
第五次
一、Oracle數據庫
1.一、視圖
視圖的功能:一個視圖實際上就是封裝了一條複雜的查詢語句
建立視圖的語法以下:
create view 視圖名稱 as 子查詢
|-實際上此時的子查詢就表示一條很是複雜的查詢語句
創建一個視圖:此視圖包含了所有的20部門的僱員信息(僱員編號,姓名,工做,僱傭日期)
create view empv20 as select empno,ename,job,hiredate from emp where deptno=20;
視圖建立完成以後,就能夠像查找表那樣直接對視圖進行查詢的操做了。
select * from empv20;
此時,咱們經過視圖查詢出20部門的僱員信息,也就是,能夠使用視圖包裝的查詢語句完成咱們的操做。可是,咱們思考下,如今這個視圖中一樣只包含了4個字段的信息,若是,如今但願多包含一個字段呢?
create view empv20 as select empno,ename,job,sal,hiredate from emp where deptno=20;
此時,系統會報錯,名稱已有現有對象使用。也就是說,該名稱的視圖已經存在了,因此,在建立視圖的時候是不容許重名的,那麼,咱們只能先刪除掉這個視圖而後進行新視圖的建立。該如何刪除視圖呢?
drop view 視圖名稱;
因此,相似於刪除表的操做,咱們將上面建立的視圖empv20刪除
drop view empv20;
刪除成功後,從新執行建立視圖的語句
create view empv20 as select empno,ename,job,sal,hiredate from emp where deptno=20;
可是,咱們應該發現,若是全部的代碼都這樣去寫確定很麻煩,由於若是要想對視圖進行修改操做,則確定先要刪除掉視圖,再進行新視圖的建立才能達到目的,因此在Oracle中爲了方便用戶修改視圖,提供了一種替換的命令,此時完整的視圖建立語法以下:
create or replace 視圖名稱 as 子查詢;
按照上面的語法格式,咱們在更改視圖的時候就不須要先執行刪除操做了,系統會爲用戶自動進行刪除及重建的功能。
create or replace view empv20 as select empno,ename,job,sal,hiredate from emp where deptno=20;
此時,系統不會提示任何錯誤,表示該視圖刪除及建立成功。
咱們說視圖其實是封裝了一個很是複雜的查詢語句。下面咱們使用視圖來封裝一個很是複雜的查詢。此查詢返回部門名稱、部門人數、平均工資以及最低工資的僱員姓名。首先看看之前的寫法
select d.dname,ed.c,ed.a,e.ename
from dept d,
(
select count(empno) c,deptno,avg(sal) a,min(sal) min from emp e
group by deptno
) ed,emp e
where d.deptno=ed.deptno and e.sal=ed.min;
若是在開發中每次都寫如此之長的SQL語句,則確定很不方便,因此此時就能夠經過創建師視圖簡化操做,方便用戶作查詢。
create or replace view myempv as
select d.dname,ed.c,ed.a,e.ename
from dept d,
(
select count(empno) c,deptno,avg(sal) a,min(sal) min from emp e
group by deptno
) ed,emp e
where d.deptno=ed.deptno and e.sal=ed.min;
在之後的操做中只須要查詢該視圖就能夠獲得結果,而不須要再次執行那麼長的SQL語句。
建立一個只包含20部門的僱員視圖
create or replace view mepv20
as
select * from emp where deptno=20;
視圖建立成功。下面進行視圖的更新操做,咱們應該記住,在視圖中是不該該包含真實數據的,並且在此程序中,建立的視圖其實是存在建立條件的,此條件是deptno=20.若是如今將視圖中的7369的部門編號修改成30呢?
update empv20 set deptno=30 where empno=7369;
更新成功,如今咱們查詢該視圖,
select * from mepv20;
發如今視圖中已經沒有7369這個僱員了。那麼,在咱們的原始表emp中呢?
select * from emp;
發如今emp表中的編號爲7369的僱員的部門編號已經修改成30,咱們思考下,這樣的更新操做合適嗎?很明顯,是不合適的,咱們在建立視圖的時候是有條件的,一旦修改以後,該條件被破壞。因此在建立視圖的時候SQL中提供了兩個很重要的參數:
|-with check option:不能更新視圖的建立條件
下面咱們在視圖建立中使用此參數
create or replace view empv20
as
select * from emp where deptno=20
with check option;
咱們再對建立的視圖進行更新操做
update mepv20 set deptno=30 where empno=7566;
此時,系統報錯,提示:視圖 with check option where 子句違規
很明顯,建立條件不能更新,那麼其餘字段呢,例如:如今將7566的僱員姓名修改成「約翰」
update empv20 set ename='約翰' where empno=7566;
更新成功,也就是說在使用了上述的with約束後,在更新視圖時,除了建立條件不能更新其餘字段都可以更新。
可是,咱們說視圖自己的做用仍是用來查詢的,因此不該該容許修改,因此此時能夠使用第二個參數:
|-with read only:建立的視圖只讀,即只能讀取操做
建立只讀視圖
create or replace view empv20
as
select * from emp where deptno=20
with read only;
再次執行更新操做,更新僱員的姓名
update empv20 set ename='約翰' where empno=7566;
提示錯誤:沒法對只讀視圖進行DML操做。
1.二、序列
在不少數據庫系統中都存在一個自動增加的列,若是如今要想在Oracle中完成自動增加的功能,則只能依靠序列完成,全部的自動增加操做,須要用戶手工完成處理。
序列的建立格式:
create sequence sequence
[increment by n][start with n]
[{maxvalue n | nomaxvalue}]
[{minvalue n | nominvalue}]
[cycle | nocycle]
[{cache n | nocache}];
建立一個myseq的序列,驗證自動增加的操做
create sequence myseq;
序列建立完成以後,全部的自動增加應該由用戶本身處理,在序列中提供瞭如下兩種操做:
|-nextVal:取得序列的下一個內容
|-currVal:取得序列的當前內容
如今咱們先創建一張用於驗證序列的表
create table testseq(
next number,
curr number
);
下面向表中添加數據,添加數據的時候須要手工使用序列
使用序列插入數據
insert into testseq(next,curr) values(myseq.nextval,myseq.currval);
將以上的插入語句執行5次
咱們查詢下testseq表,看看序列的變化
select * from testseq;
從查詢結果中咱們發現,nextval的內容始終在進行自動增加的操做,而curr使用取出當前操做的序列結果,也就是說,如今的這種序列,每次增加的幅度是1,那麼也能夠修改序列的增加幅度。
能夠使用如下的一個參數:
|-每次增加長度:increment by 長度
從新創建序列
drop sequence myseq;
create sequence myseq increment by 2;
此時,序列已經正常的建立,建立以後來測試下,序列的操做,從新建立testseq表
drop table testseq;
create table testseq(
next number,
curr number
);
從新進行數據的插入操做,插入5次
insert into testseq(next,curr) values(myseq.nextval,myseq.currval);
再次查詢testseq表,觀察序列的變化
select * from testseq;
從序列的結果來看,每次取得都是奇數。
默認狀況下,序列從1開始的,那麼能夠使用start with來指定其開始的位置
drop sequence myseq;
create sequence myseq increment by 2 start with 10;
這裏指定序列開始點爲10,之後直接從10開始進行序列的計算。
下面咱們從新建立下該序列,讓其取值固定在一、三、五、七、9,並循環序列
drop sequence myseq;
create sequence myseq
maxvalue 10
increment by 2 start with 1
cache 2 cycle;
從新創建testseq表,插入數據,測試最終的結果,能夠發現序列的內容是循環出現的,可是咱們說在實踐中,序列使用最多的語法是:create sequence 序列名稱。其餘選項使用默認值。
1.三、同義詞
在前面咱們使用過這樣的查詢語句:
select sysdate from dual;
咱們知道dual是一張虛擬表,那麼雖然是虛擬表,但是此表究竟是在哪裏定義的呢?
經過測試,咱們發如今sys帳戶下存在dual表。如今問題出現了,既然dual表是sys帳戶下的,那麼根據咱們前面的知識,若是想要在scott用戶中使用dual表時,正確的作法是:
select sysdate from sys.dual;
可是咱們在scott帳戶下是這樣寫的
select sysdate from dual;
這是爲何呢?此時,實際上就是同義詞的做用。什麼是同義詞?同義詞可讓其餘用戶經過一個名稱方便的訪問」用戶名.表名稱「。
建立同義詞的語法:
create synonym 同義詞名稱 for 用戶名.表名稱;
下面咱們將scott表的emp定義emp的同義詞:
create sysnonym emp for scott.emp;
若是要刪除一個同義詞,能夠使用以下的語法格式:
drop sysnonym 同義詞名稱;
因此,刪除上面建立的同義詞:
drop sysnonym emp;
可是,此種特性只適用於Oracle數據庫。
1.四、用戶管理
在Oracle中能夠對用戶進行創建和受權的操做。
建立用戶的語法是:
create user 用戶名 identified by 密碼;
假設如今要建立一個test用戶,密碼爲123
create user test identified by 123;
建立用戶成功事後,是否能夠登陸呢?顯然是不行的,在登陸請安必須爲新建立的用戶授予相關的權限才能執行相應的操做。
爲用戶受權的格式以下:
grant 權限1,權限2,...... to 用戶名;
因此,爲了新建立的用戶test可以鏈接數據庫,咱們須要爲它受權
grant create session to test;
以後咱們就能使用test正常登錄了。
那麼,咱們開始常見一張表吧。
但是,咱們發現,系統又提示權限不足。很明顯的知道,當前用戶test沒有建立表的權限,既然如此,咱們就爲它授予建立表的權限。在此以前,咱們給出一個這樣的結論:對於一個新建立的用戶,全部的權限均要分別賦予,該用戶才能進行相應的操做。若是如今假設要想把多個權限一次性賦予一個用戶,則能夠講這些權限先定義成一組角色的集合。
在Oracle中提供了兩個主要角色:connect、resource,能夠直接把這啷個角色賦予test用戶。
grant connect,resource to test;
忽然,test用戶密碼忘記了,那麼如何修改一個用戶的密碼呢?固然該操做只有超級管理員纔有權限
alter user 用戶名 identified by 密碼;
將test的用戶密碼修改成hello
alter user test identified by hello;
在通常的系統中存在這樣的狀況,在用戶第一次登錄的時候能夠修改密碼,因此要想完成此功能,能夠手工讓一個密碼失效,格式以下:
alter user 用戶名 password expire;
如今咱們能夠設置test的當前密碼失效
alter user test password expire;
若是系統中某個用戶須要被鎖住,該如何操做呢?
alter user 用戶名 account lock;
如今因爲某些緣由,咱們須要將test用戶鎖住
alter user test account lock;
那麼,test用戶就不能鏈接數據庫了。
若是要解鎖test呢?
alter user 用戶名 account unlock;
好了,如今咱們解鎖test
alter user test account unlock;
那麼,test用戶就能正常鏈接數據庫了。
如今咱們須要使用test用戶來訪問scott用戶下的emp表
select * from scott.emp;
按照前面的知識,該查詢時沒有問題的,可是系統提示錯誤說:scott.emp表不存在。怎麼回事?
再想一想前面的一句話,」咱們須要爲新建立的用戶分別授予相應的權限來執行相應的操做「,很明顯,test沒有訪問其餘用戶下表的權限,因此這麼操做
grant select,delete on scott.emp to test;
咱們將查詢和刪除emp表的權限授予給test用戶
既然能夠授予權限,那麼也能夠回收權限,回收權限使用revoke語法。,語法格式以下:
revoke 權限名 on 用戶表名稱 from 用戶;
若是咱們不但願test用戶查詢和刪除scott的emp表,
revoke select,delete on scott.emp from test;
1.五、數據庫的備份和恢復
數據庫在運行的期間都是須要不斷的進行備份的,萬一假設系統崩潰了,能夠從備份中恢復數據。
Oracle在安裝完成以後能夠使用兩個命名進行數據庫的備份和恢復:
|-數據庫備份:exp
|-數據庫恢復:imp
1.六、嵌套表
嵌套表:在一個表中還包含另一個子表
例如:如今有一種狀況,一個部門可能承接多個項目,若是此時,按照最原始的方法設計,那麼定義兩張表,department表,project表
create table department(
deptno number(2) primary key not null,
dname varchar2(50) not null
);
create table project(
proid number(4) primary key not null,
proname varchar2(50) not null,
deptno number(2),
constraint department_project_deptno foreign key(deptno) references department(deptno) on delete cascade
);
這是咱們最多見的思路,並且自己也屬於一個正確的作法,可是在Oracle中引入了嵌套表的概念,能夠直接將項目表的類型做爲一個department表的字段類型,達到嵌套的目的。
可是,要想完成一個嵌套表的製做,則首先要保證一點:由於數據庫在建立數據表的時候都要指定字段的類型,因此嵌套表自己也須要一樣指定類型,那麼這種類型就須要單獨的定義:
create type project_ty as object(
proid number(4),
proname varchar2(50),
prodate date
);
/
類型建立成功以後,並不意味着此類型能夠直接使用,由於此類型是一個完整的類型,因此要爲此類型指定一個名稱
create type project_nt as table of project_ty;
/
以上的操做表示之後直接使用project_nt表示project_ty類型,就相似於varchar2表示字符串是同樣的,此時能夠使用此類型建立department表
create table department(
deptno number(2) primary key not null,
dname varchar2(50) not null,
projects project_nt
)nested table projects store as project_nt_tab_temp;
對於插入語句來說,須要指定每一個project_ty的類型
insert into department(deptno,dname,projects)
values(
1,'技術部',
project_nt(
project_ty(1001,'ERP',sysdate),
project_ty(1002,'CRM',sysdate),
project_ty(1003,'OA',sysdate)
)
);
此時,查詢嵌套表,能夠返回多個項目
select * from department;
若是這個時候,咱們須要查看一個部門的所有項目的話,則須要查詢嵌套表
select * from table
(select projects from department where deptno=1);
若是如今咱們須要更新項目編號爲1001的項目名稱,將此項目名稱更新爲「測試項目」
update table (select projects from department where deptno=1) pro
set value(pro)=project_ty(1001,'測試項目',to_date('1998-09-21','yyyy-mm-dd')) where pro.proid=1001;
1.七、可變數組
可變數組屬於嵌套表的升級版,在可變數組中,實際上就是將內部的嵌套表的內容的長度進行了限制。
例如,一個部門有多個工人,若是按照可變數組的作法,確定首先要作出一個工人的類型。
create type worker_info as object(
id number(4),
name varchar2(50),
sex varchar2(6)
);
/
下面再定義數組類型
create type worker_info_list as varray(10) of worker_info;
/
定義部門表,一個部門中可能存在多個工人
drop table department;
create table department(
deptno number(2) primary key not null,
dname varchar2(50) not null,
workers worker_info_list
);
插入測試數據
insert into department(deptno,dname,workers)
values(20,'後勤部',
worker_info_list(
worker_info(1,'張三','男'),
worker_info(2,'李四','男'),
worker_info(3,'王五','男')
)
);
查詢所有
select * from department;
除了以上的全部內容以外,對於數據庫的開發中,像過程之類的基本不用了,由於如今的不少地方都使用程序完成功能。
並且,對於高級開發部分:遊標、觸發器、包、函數。基本上不多去直接調用。
1.八、數據庫設計範式
數據庫設計範式實際上很是的重要,可是從實際的開發來看,若是真的所有按照範式去作,則這個程序無法寫,包括查詢語句也會變得複雜。
在Oracle中的scott用戶的所有表,實際上就已經很好的體現了一張設計思路,僱員-部門的關係。
1) 第一範式
例如,如今假設有以下的數據庫建立腳本
create table person(
pid number(4) primary key not null,
name varchar2(50),
info varchar(200)
);
插入如下測試數據
insert into person(pid,name,info) values(1111,'張三','1983年11月23日出生,如今的住址是:北京市西城區。。。。。');
實際上對於人員來看,由如下幾部分組成:
|-生日:1983年1月23日
|-省市:北京
|-地區:西城區
|-詳細的信息:。。。。。
每一個字段不可再分,因此,以上的數據庫建立腳本修改以下:
create table person(
pid number(4) primary key not null,
name varchar2(50),
birthday date,
area varchar2(200),
subarea varchar2(200),
address varchar2(200)
);
這種設計看上去每一個字段是不可再分的,可是咱們應該會注意到,在一些網站的註冊中,會要求用戶分別輸入「姓」和「名」,因此,可將上面的設計修改以下:
create table person(
pid number(4) primary key not null,
姓 varchar2(50),
名 varchar2(50),
birthday date,
area varchar2(200),
subarea varchar2(200),
address varchar2(200)
);
因此,在設計表字段的時候,最好保證每一個字段均不能再分。
2) 第二範式
第一範式的要求很是簡單,保證每一個字段有意義。可是若是全部的操做都使用第一範式,那麼會存在問題:
如今創建一張學生選課表:學號、姓名、年齡、課程名稱、成績、學分
create table selectcourse(
stuno varchar2(50),
stuname varchar2(50),
stuage number,
cname varchar2(50),
grade number,
credit number
);
以上的腳本符合第一範式的要求,可是若是按照第一範式設計的話,會存在問題:
insert into selectcourse values('s001','張三',21,'JAVA',89,0.3);
insert into selectcourse values('s001','李四',20,'JAVA',78,0.3);
insert into selectcourse values('s001','王五',23,'JAVA',80,0.3);
insert into selectcourse values('s001',趙六',22,'JAVA',90,0.3);
從以上的數據庫腳本上能夠發現,全部的課程信息冗餘了,並且還存在如下問題:
|-若是一門課程沒有一個學生選擇,則此而成就從學校完全消失了
|-課程中自己也應該包含一個課程的編號,可是若是按照以上的設計,則課程編號確定重複
|-若是要更改課程信息,則要更改許多條記錄
咱們使用第二範式修改數據庫腳本:
|-學生是一個實體--學生表
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number
);
|-課程也應該是一個實體--課程表
create table course(
cid number(5) primary key not null,
cname varchar2(50),
credit number
);
|-學生選課信息也是一個實體--學生選課表
create table selectcourse(
stuno varchar2(50),
cid number(5),
grade number,
加入外鍵關聯,由於學生沒了,成績就沒了,由於課程沒了,成績就沒了
);
以上設計解決了如下問題:
|-學生不選課的時候,課程信息不會消失
|-更新課程的時候直接更新課程表便可
|-全部的關聯關係在關係表中體現。
3) 第三範式
在實際開發中,第三範式的使用是最多的。
例如,如今要求設計一張學生表,包含學號、姓名、年齡、所在院校、學院地址、學院電話,此時確定不能使用第一範式,可是如今若是使用的是第二範式呢?
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number
);
create table collage(
cid number(4) primary key not null,
cname varchar2(50) not not null,
caddress varchar2(200) not nul,
ctel varchar2(200) not null
);
create table studentcollage(
stuno varchar2(50),
cid number(4),
設置主-外鍵關係
);
按照上面的設計,一個學生能夠同時在多個學院同時上課,多個學院會同時有同一個學生,此時,最好的作法是:一個學院包含多個學生,一個學生屬於一個學院,實際上,此設計就徹底相似於部門和僱員表的設計結構。
create table collage(
cid number(4) primary key not null,
cname varchar2(50) not not null,
caddress varchar2(200) not nul,
ctel varchar2(200) not null
);
create table student(
stuno varchar2(50) primary key not null,
stuname varchar2(50),
stuage number,
cid number(4),
創建主-外鍵關係
);
該設計是一個很明確的一對多的關係設計。
數據庫的惟一原則:
|-數據庫表的關聯查詢越少越好,SQL語句的複雜度越低越好。
1.九、數據庫設計工具
在實際中數據庫也有本身的設計工具,比較經常使用的就是Sybase的PowerDesigner開發工具,此工具能夠方便的作各類設計,啓動以後,能夠使用此工具,進行數據庫的建模設計。
啓動PowerDesigner後,選擇新建,Physical Data Model,選擇Oracle數據庫
下面使用PowerDesigner工具將Oracle中的dept和emp表進行還原
建立表--在工具中進行主-外鍵的操做--獲得關係以後,就能夠經過Powerdesigner工具進行數據庫腳本的建立了。
1.十、數據庫設計分析
1) 要求
設計要求,要求設計一個網上購物程序(使用Powerdesigner創建模型並編寫測試數據),有如下的需求
|-管理員能夠再後臺添加商品,每一個商品屬於一個商品組
|-能夠對管理員進行分組,對每一組進行分別受權,即一個管理員組能夠有多個管理員,一個管理員組有多個權限,一個管理員能夠再多個組
|-用戶能夠本身購買商品,購買商品時要在訂單表中添加信息,一個用戶能夠同時購買多個商品,用戶能夠選擇本身所在的地區進行商品的派送
|-用戶能夠根據本身的購買積分,對商品進行折扣
2) 實現
根據第一個要求,一個商品屬於一個商品組,則此時應該創建一個「一對多」的關係
根據第二個要求,能夠對管理員進行分組,須要管理員表、管理員組表、權限表、管理員-管理員組表、管理員組-權限表
管理員和商品表也要存在關係
須要一個用戶表,與其產生關係的有地區表、子地區表、訂單表、訂單詳情表、積分表
正常狀況下,一份訂單確定會按照以上的格式顯示,那麼請問,這樣一來要查詢多少張表?
|-用戶表(用戶姓名、用戶電話、用戶地址)
|-地區表-子地區表(用戶地區)
|-訂單表、訂單詳情表(商品總價、訂單日期、郵政編碼)
本查詢須要同時查詢6張表。本程序中的全部代碼都是按照標準範式完成的,因此此時出現了以上的問題。
在開發中減小多表查詢的方法能夠經過冗餘數據完成。</pre>
<p> </p>
<pre name="code" >Oracle 筆記
1
韓順平老師 oracle教程筆記
1.Oracle認證,與其它數據庫比較,安裝 Oracle安裝會自動的生成sys用戶和system用戶: (1)sys用戶是超級用戶,具備最高權限,具備sysdba角色,有create database的權限,該用戶默認的密碼是change_on_install (2)system用戶是管理操做員,權限也很大。具備sysoper角色,沒有create database的權限,默認的密碼是manager (3)通常講,對數據庫維護,使用system用戶登陸就能夠拉 也就是說sys和system這兩個用戶最大的區別是在於有沒有create database的權限。
2.Oracle的基本使用--基本命令
sql*plus的經常使用命令
鏈接命令 1.conn[ect] 用法:conn 用戶名/密碼@網絡服務名[as sysdba/sysoper]當用特權用戶身份鏈接時,必須帶上as sysdba或是as sysoper 2.disc[onnect] 說明: 該命令用來斷開與當前數據庫的鏈接 3.psssw[ord] 說明: 該命令用於修改用戶的密碼,若是要想修改其它用戶的密碼,須要用sys/system登陸。 4.show user 說明: 顯示當前用戶名 5.exit 說明: 該命令會斷開與數據庫的鏈接,同時會退出sql*plus 文件操做命令 1.start和@ 說明: 運行sql腳本 案例: sql&gt;@ d:\a.sql或是sql&gt;start d:\a.sql 2.edit 說明: 該命令能夠編輯指定的sql腳本 案例: sql&gt;edit d:\a.sql,這樣會把d:\a.sql這個文件打開 3.spool 說明: 該命令能夠將sql*plus屏幕上的內容輸出到指定文件中去。 案例: sql&gt;spool d:\b.sql 並輸入 sql&gt;spool off 交互式命令 1.&amp; 說明:能夠替代變量,而該變量在執行時,須要用戶輸入。 select * from emp where job='&amp;job'; 2.edit 說明:該命令能夠編輯指定的sql腳本 案例:SQL&gt;edit d:\a.sql 3.spool 說明:該命令能夠將sql*plus屏幕上的內容輸出到指定文件中去。 spool d:\b.sql 並輸入 spool off 顯示和設置環境變量 概述:能夠用來控制輸出的各類格式,set show若是但願永久的保存相關的設置,能夠去修改glogin.sql腳本
Oracle 筆記
2
1.linesize 說明:設置顯示行的寬度,默認是80個字符 show linesize set linesize 90 2.pagesize說明:設置每頁顯示的行數目,默認是14 用法和linesize同樣 至於其它環境參數的使用也是大同小異
3.oracle用戶管理
oracle用戶的管理 建立用戶 概述:在oracle中要建立一個新的用戶使用create user語句,通常是具備dba(數據庫管理員)的權限才能使用。 create user 用戶名 identified by 密碼; (oracle有個毛病,密碼必須以字母開頭,若是以字母開頭,它不會建立用戶) 給用戶修改密碼 概述:若是給本身修改密碼能夠直接使用 password 用戶名 若是給別人修改密碼則須要具備dba的權限,或是擁有alter user的系統權限 SQL&gt; alter user 用戶名 identified by 新密碼 刪除用戶 概述:通常以dba的身份去刪除某個用戶,若是用其它用戶去刪除用戶則須要具備drop user的權限。 好比 drop user 用戶名 【cascade】 在刪除用戶時,注意: 若是要刪除的用戶,已經建立了表,那麼就須要在刪除的時候帶一個參數cascade; 用戶管理綜合案例 概述:建立的新用戶是沒有任何權限的,甚至連登錄的數據庫的權限都沒有,須要爲其指定相應的權限。給一個用戶賦權限使用命令grant,回收權限使用命令revoke。 爲了給講清楚用戶的管理,這裏我給你們舉一個案例。 SQL&gt; conn xiaoming/m12; ERROR: ORA-01045: user XIAOMING lacks CREATE SESSION privilege; logon denied 警告: 您再也不鏈接到 ORACLE。 SQL&gt; show user; USER 爲 "" SQL&gt; conn system/p; 已鏈接。 SQL&gt; grant connect to xiaoming; 受權成功。 SQL&gt; conn xiaoming/m12; 已鏈接。 SQL&gt; 注意:grant connect to xiaoming;在這裏,準確的講,connect不是權限,而是角色。
如今說下對象權限,如今要作這麼件事情: * 但願xiaoming用戶能夠去查詢emp表 * 但願xiaoming用戶能夠去查詢scott的emp表
Oracle 筆記
3
grant select on emp to xiaoming * 但願xiaoming用戶能夠去修改scott的emp表 grant update on emp to xiaoming * 但願xiaoming用戶能夠去修改/刪除,查詢,添加scott的emp表 grant all on emp to xiaoming * scott但願收回xiaoming對emp表的查詢權限 revoke select on emp from xiaoming //對權限的維護。 * 但願xiaoming用戶能夠去查詢scott的emp表/還但願xiaoming能夠把這個權限繼續給別人。 --若是是對象權限,就加入 with grant option grant select on emp to xiaoming with grant option 個人操做過程: SQL&gt; conn scott/tiger; 已鏈接。 SQL&gt; grant select on scott.emp to xiaoming with grant option; 受權成功。 SQL&gt; conn system/p; 已鏈接。 SQL&gt; create user xiaohong identified by m123; 用戶已建立。 SQL&gt; grant connect to xiaohong; 受權成功。 SQL&gt; conn xiaoming/m12; 已鏈接。 SQL&gt; grant select on scott.emp to xiaohong; 受權成功。 --若是是系統權限。 system給xiaoming權限時: grant connect to xiaoming with admin option 問題:若是scott把xiaoming對emp表的查詢權限回收,那麼xiaohong會怎樣? 答案:被回收。 下面是個人操做過程: SQL&gt; conn scott/tiger; 已鏈接。 SQL&gt; revoke select on emp from xiaoming; 撤銷成功。 SQL&gt; conn xiaohong/m123; 已鏈接。 SQL&gt; select * from scott.emp; select * from scott.emp 第 1 行出現錯誤: ORA-00942: 表或視圖不存在 結果顯示:小紅受到誅連了。。 使用profile管理用戶口令 概述:profile是口令限制,資源限制的命令集合,當創建數據庫的,oracle會自動創建名稱爲default的profile。當創建用戶沒
Oracle 筆記
4
有指定profile選項,那麼oracle就會將default分配給用戶。 1.帳戶鎖定 概述:指定該帳戶(用戶)登錄時最多能夠輸入密碼的次數,也能夠指定用戶鎖定的時間(天)通常用dba的身份去執行該命令。 例子:指定scott這個用戶最多隻能嘗試3次登錄,鎖定時間爲2天,讓咱們看看怎麼實現。 建立profile文件 SQL&gt; create profile lock_account limit failed_login_attempts 3 password_lock_time 2; SQL&gt; alter user scott profile lock_account; 2.給帳戶(用戶)解鎖 SQL&gt; alter user tea account unlock; 3.終止口令 爲了讓用戶按期修改密碼能夠使用終止口令的指令來完成,一樣這個命令也須要dba的身份來操做。 例子:給前面建立的用戶tea建立一個profile文件,要求該用戶每隔10天要修改本身的登錄密碼,寬限期爲2天。看看怎麼作。 SQL&gt; create profile myprofile limit password_life_time 10 password_grace_time 2; SQL&gt; alter user tea profile myprofile; 口令歷史 概述:若是但願用戶在修改密碼時,不能使用之前使用過的密碼,可以使用口令歷史,這樣oracle就會將口令修改的信息存放到數據字典中,這樣當用戶修改密碼時,oracle就會對新舊密碼進行比較,當發現新舊密碼同樣時,就提示用戶從新輸入密碼。 例子: 1)創建profile SQL&gt;create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10 password_reuse_time //指定口令可重用時間即10天后就能夠重用 2)分配給某個用戶
刪除profile 概述:當不須要某個profile文件時,能夠刪除該文件。 SQL&gt; drop profile password_history 【casade】 注意:文件刪除後,用這個文件去約束的那些用戶統統也都被釋放了。。 加了casade,就會把級聯的相關東西也給刪除掉
4.oracle表的管理(數據類型,表建立刪除,數據CRUD操做)
指望目標
? 1.掌握oracle表的管理(建立/維護)
? 2.掌握對oracle表的各類查詢技巧
? 3.學會建立新的oracle數據庫 oracle的表的管理 表名和列的命名規則
? 必須以字母開頭
? 長度不能超過30個字符
? 不能使用oracle的保留字
? 只能使用以下字符 A-Z,a-z,0-9,$,#等
oracle支持的數據類型? 字符類 char 定長 最大2000個字符。
Oracle 筆記
5
例子:char(10) ‘小韓’前四個字符放‘小韓’,後添6個空格補全 如‘小韓 ’ varchar2(20) 變長 最大4000個字符。 例子:varchar2(10) ‘小韓’ oracle分配四個字符。這樣能夠節省空間。 clob(character large object) 字符型大對象 最大4G char 查詢的速度極快浪費空間,查詢比較多的數據用。 varchar 節省空間 數字型 number範圍 -10的38次方 到 10的38次方 能夠表示整數,也能夠表示小數 number(5,2) 表示一位小數有5位有效數,2位小數 範圍:-999.99到999.99 number(5) 表示一個5位整數 範圍99999到-99999 日期類型 date 包含年月日和時分秒 oracle默認格式 1-1月-1999 timestamp 這是oracle9i對date數據類型的擴展。能夠精確到毫秒。 ? 圖片 blob 二進制數據 能夠存放圖片/聲音 4G 通常來說,在真實項目中是不會把圖片和聲音真的往數據庫裏存放,通常存放圖片、視頻的路徑,若是安全須要比較高的話,則放入數據庫。 怎樣建立表 建表 --學生表 create table student ( ---表名 xh number(4), --學號 xm varchar2(20), --姓名 sex char(2), --性別 birthday date, --出生日期 sal number(7,2) --獎學金 ); --班級表 CREATE TABLE class( classId NUMBER(2), cName VARCHAR2(40) ); 修改表 ? 添加一個字段 SQL&gt;ALTER TABLE student add (classId NUMBER(2)); ? 修改一個字段的長度 SQL&gt;ALTER TABLE student MODIFY (xm VARCHAR2(30)); ? 修改字段的類型/或是名字(不能有數據) 不建議作 SQL&gt;ALTER TABLE student modify (xm CHAR(30)); ? 刪除一個字段 不建議作(刪了以後,順序就變了。加就沒問題,應爲是加在後面) SQL&gt;ALTER TABLE student DROP COLUMN sal;
Oracle 筆記
6
? 修改表的名字 不多有這種需求 SQL&gt;RENAME student TO stu; ? 刪除表 SQL&gt;DROP TABLE student; 添加數據 全部字段都插入數據 INSERT INTO student VALUES ('A001', '張三', '男', '01-5月-05', 10); oracle中默認的日期格式‘dd-mon-yy’ dd日子(天) mon 月份 yy 2位的年 ‘09-6月-99’ 1999年6月9日 修改日期的默認格式(臨時修改,數據庫重啓後仍爲默認;如要修改須要修改註冊表) ALTER SESSION SET NLS_DATE_FORMAT ='yyyy-mm-dd'; 修改後,能夠用咱們熟悉的格式添加日期類型: INSERT INTO student VALUES ('A002', 'MIKE', '男', '1905-05-06', 10); 插入部分字段 INSERT INTO student(xh, xm, sex) VALUES ('A003', 'JOHN', '女'); 插入空值 INSERT INTO student(xh, xm, sex, birthday) VALUES ('A004', 'MARTIN', '男', null); 問題來了,若是你要查詢student表裏birthday爲null的記錄,怎麼寫sql呢? 錯誤寫法:select * from student where birthday = null; 正確寫法:select * from student where birthday is null; 若是要查詢birthday不爲null,則應該這樣寫: select * from student where birthday is not null; 修改數據 ? 修改一個字段 UPDATE student SET sex = '女' WHERE xh = 'A001'; ? 修改多個字段 UPDATE student SET sex = '男', birthday = '1984-04-01' WHERE xh = 'A001'; 修改含有null值的數據 不要用 = null 而是用 is null; SELECT * FROM student WHERE birthday IS null; ? 刪除數據 DELETE FROM student; 刪除全部記錄,表結構還在,寫日誌,能夠恢復的,速度慢。 Delete 的數據能夠恢復。 savepoint a; --建立保存點 DELETE FROM student; rollback to a; --恢復到保存點 一個有經驗的DBA,在確保完成無誤的狀況下要按期建立還原點。 DROP TABLE student; --刪除表的結構和數據; delete from student WHERE xh = 'A001'; --刪除一條記錄; truncate TABLE student; --刪除表中的全部記錄,表結構還在,不寫日誌,沒法找回刪除的記錄,速度快。
5.oracle表查詢(1)
在咱們講解的過程當中咱們利用scott用戶存在的幾張表(emp,dept)爲你們演示如何使用select語句,select語句在軟件編程中很是有用,但願你們好好的掌握。
Oracle 筆記
7
emp 僱員表 clerk 普員工 salesman 銷售 manager 經理 analyst 分析師 president 總裁 mgr 上級的編號 hiredate 入職時間 sal 月工資 comm 獎金 deptno 部門 dept部門表 deptno 部門編號 accounting 財務部 research 研發部 operations 業務部 loc 部門所在地點 salgrade 工資級別 grade 級別 losal 最低工資 hisal 最高工資 簡單的查詢語句 ? 查看錶結構 DESC emp; ? 查詢全部列 SELECT * FROM dept; 切忌動不動就用select * SET TIMING ON; 打開顯示操做時間的開關,在下面顯示查詢時間。 CREATE TABLE users(userId VARCHAR2(10), uName VARCHAR2 (20), uPassw VARCHAR2(30)); INSERT INTO users VALUES('a0001', '啊啊啊啊', 'aaaaaaaaaaaaaaaaaaaaaaa'); --從本身複製,加大數據量 大概幾萬行就能夠了 能夠用來測試sql語句執行效率 INSERT INTO users (userId,UNAME,UPASSW) SELECT * FROM users; SELECT COUNT (*) FROM users;統計行數 ? 查詢指定列 SELECT ename, sal, job, deptno FROM emp; ? 如何取消重複行DISTINCT SELECT DISTINCT deptno, job FROM emp; ?查詢SMITH所在部門,工做,薪水 SELECT deptno,job,sal FROM emp WHERE ename = 'SMITH'; 注意:oracle對內容的大小寫是區分的,因此ename='SMITH'和ename='smith'是不一樣的
Oracle 筆記
8
? 使用算術表達式 nvl null 問題:如何顯示每一個僱員的年工資? SELECT sal*13+nvl(comm, 0)*13 "年薪" , ename, comm FROM emp; ? 使用列的別名 SELECT ename "姓名", sal*12 AS "年收入" FROM emp; ? 如何處理null值 使用nvl函數來處理 ? 如何鏈接字符串(||) SELECT ename || ' is a ' || job FROM emp; ? 使用where子句 問題:如何顯示工資高於3000的 員工? SELECT * FROM emp WHERE sal &gt; 3000; 問題:如何查找1982.1.1後入職的員工? SELECT ename,hiredate FROM emp WHERE hiredate &gt;'1-1月-1982'; 問題:如何顯示工資在2000到3000的員工? SELECT ename,sal FROM emp WHERE sal &gt;=2000 AND sal &lt;= 3000; ? 如何使用like操做符 %:表示0到多個字符 _:表示任意單個字符 問題:如何顯示首字符爲S的員工姓名和工資? SELECT ename,sal FROM emp WHERE ename like 'S%'; 如何顯示第三個字符爲大寫O的全部員工的姓名和工資? SELECT ename,sal FROM emp WHERE ename like '__O%'; ? 在where條件中使用in 問題:如何顯示empno爲7844, 7839,123,456 的僱員狀況? SELECT * FROM emp WHERE empno in (7844, 7839,123,456); ? 使用is null的操做符 問題:如何顯示沒有上級的僱員的狀況? 錯誤寫法:select * from emp where mgr = ''; 正確寫法:SELECT * FROM emp WHERE mgr is null;
6.oracle表查詢(2)
? 使用邏輯操做符號 問題:查詢工資高於500或者是崗位爲MANAGER的僱員,同時還要知足他們的姓名首字母爲大寫的J? SELECT * FROM emp WHERE (sal &gt;500 or job = 'MANAGER') and ename LIKE 'J%'; ? 使用order by 字句 默認asc 問題:如何按照工資的從低到高的順序顯示僱員的信息? SELECT * FROM emp ORDER by sal; 問題:按照部門號升序而僱員的工資降序排列 SELECT * FROM emp ORDER by deptno, sal DESC; ? 使用列的別名排序 問題:按年薪排序 select ename, (sal+nvl(comm,0))*12 "年薪" from emp order by "年薪" asc; 別名須要使用「」號圈中,英文不須要「」號
Oracle 筆記
9
? 分頁查詢 等學了子查詢再說吧。。。。。。。。 Clear 清屏命令 oracle表複雜查詢 ? 說明 在實際應用中常常須要執行復雜的數據統計,常常須要顯示多張表的數據,如今咱們給你們介紹較爲複雜的select語句 數據分組 ——max,min, avg, sum, count 問題:如何顯示全部員工中最高工資和最低工資? SELECT MAX(sal),min(sal) FROM emp e; 最高工資那我的是誰? 錯誤寫法:select ename, sal from emp where sal=max(sal); 正確寫法:select ename, sal from emp where sal=(select max(sal) from emp); 注意:select ename, max(sal) from emp;這語句執行的時候會報錯,說ORA-00937:非單組分組函數。由於max是分組函數,而ename不是分組函數....... 可是select min(sal), max(sal) from emp;這句是能夠執行的。由於min和max都是分組函數,就是說:若是列裏面有一個分組函數,其它的都必須是分組函數,不然就出錯。這是語法規定的 問題:如何顯示全部員工的平均工資和工資總和? 問題:如何計算總共有多少員工問題:如何 擴展要求: 查詢最高工資員工的名字,工做崗位 SELECT ename, job, sal FROM emp e where sal = (SELECT MAX(sal) FROM emp); 顯示工資高於平均工資的員工信息 SELECT * FROM emp e where sal &gt; (SELECT AVG(sal) FROM emp); ? group by 和 having子句 group by用於對查詢的結果分組統計, having子句用於限制分組顯示結果。 問題:如何顯示每一個部門的平均工資和最高工資? SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno; (注意:這裏暗藏了一點,若是你要分組查詢的話,分組的字段deptno必定要出如今查詢的列表裏面,不然會報錯。由於分組的字段都不出現的話,就沒辦法分組了) 問題:顯示每一個部門的每種崗位的平均工資和最低工資? SELECT min(sal), AVG(sal), deptno, job FROM emp GROUP by deptno, job; 問題:顯示平均工資低於2000的部門號和它的平均工資? SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno having AVG(sal) &lt; 2000; ? 對數據分組的總結 1 分組函數只能出如今選擇列表、having、order by子句中(不能出如今where中) 2 若是在select語句中同時包含有group by, having, order by 那麼它們的順序是group by, having, order by 3 在選擇列中若是有列、表達式和分組函數,那麼這些列和表達式必須有一個出如今group by 子句中,不然就會出錯。 如SELECT deptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) &lt; 2000; 這裏deptno就必定要出如今group by 中 多表查詢 ? 說明 多表查詢是指基於兩個和兩個以上的表或是視圖的查詢。在實際應用中,查詢單個表可能不能知足你的需求,(如顯示sales部門位置和其員工的姓名),這種狀況下須要使用到(dept表和emp表)
Oracle 筆記
10
問題:顯示僱員名,僱員工資及所在部門的名字【笛卡爾集】? 規定:多表查詢的條件是 至少不能少於 表的個數-1 才能排除笛卡爾集 (若是有N張表聯合查詢,必須得有N-1個條件,才能避免笛卡爾集合) SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno; 問題:顯示部門號爲10的部門名、員工名和工資? SELECT d.dname, e.ename, e.sal FROM emp e, dept d WHERE e.deptno = d.deptno and e.deptno = 10; 問題:顯示各個員工的姓名,工資及工資的級別? 先看salgrade的表結構和記錄 SQL&gt;select * from salgrade; GRADE LOSAL HISAL ------------- ------------- ------------ 1 700 1200 2 1201 1400 3 1401 2000 4 2001 3000 5 3001 9999 SELECT e.ename, e.sal, s.grade FROM emp e, salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal; 擴展要求: 問題:顯示僱員名,僱員工資及所在部門的名字,並按部門排序? SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno ORDER by e.deptno; (注意:若是用group by,必定要把e.deptno放到查詢列裏面) ? 自鏈接 自鏈接是指在同一張表的鏈接查詢 問題:顯示某個員工的上級領導的姓名? 好比顯示員工‘FORD’的上級 SELECT worker.ename, boss.ename FROM emp worker,emp boss WHERE worker.mgr = boss.empno AND worker.ename = 'FORD'; 子查詢 ? 什麼是子查詢 子查詢是指嵌入在其餘sql語句中的select語句,也叫嵌套查詢。 ? 單行子查詢 單行子查詢是指只返回一行數據的子查詢語句 請思考:顯示與SMITH同部門的全部員工? 思路: 1 查詢出SMITH的部門號 select deptno from emp WHERE ename = 'SMITH'; 2 顯示 SELECT * FROM emp WHERE deptno = (select deptno from emp WHERE ename = 'SMITH'); 數據庫在執行sql 是從左到右掃描的, 若是有括號的話,括號裏面的先被優先執行。 ? 多行子查詢 多行子查詢指返回多行數據的子查詢 請思考:如何查詢和部門10的工做相同的僱員的名字、崗位、工資、部門號 SELECT DISTINCT job FROM emp WHERE deptno = 10; SELECT * FROM emp WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10); (注意:不能用job=..,由於等號=是一對一的) ? 在多行子查詢中使用all操做符
Oracle 筆記
11
問題:如何顯示工資比部門30的全部員工的工資高的員工的姓名、工資和部門號? SELECT ename, sal, deptno FROM emp WHERE sal &gt; all (SELECT sal FROM emp WHERE deptno = 30); 擴展要求: 你們想一想還有沒有別的查詢方法。 SELECT ename, sal, deptno FROM emp WHERE sal &gt; (SELECT MAX(sal) FROM emp WHERE deptno = 30); 執行效率上, 函數高得多 ? 在多行子查詢中使用any操做符 問題:如何顯示工資比部門30的任意一個員工的工資高的員工姓名、工資和部門號? SELECT ename, sal, deptno FROM emp WHERE sal &gt; ANY (SELECT sal FROM emp WHERE deptno = 30); 擴展要求: 你們想一想還有沒有別的查詢方法。 SELECT ename, sal, deptno FROM emp WHERE sal &gt; (SELECT min(sal) FROM emp WHERE deptno = 30); ? 多列子查詢 單行子查詢是指子查詢只返回單列、單行數據,多行子查詢是指返回單列多行數據,都是針對單列而言的,而多列子查詢是指查詢返回多個列數據的子查詢語句。 請思考如何查詢與SMITH的部門和崗位徹底相同的全部僱員。 SELECT deptno, job FROM emp WHERE ename = 'SMITH'; SELECT * FROM emp WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH'); ? 在from子句中使用子查詢 請思考:如何顯示高於本身部門平均工資的員工的信息 思路: 1. 查出各個部門的平均工資和部門號 SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno; 2. 把上面的查詢結果看作是一張子表 SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) ds WHERE e.deptno = ds.deptno AND e.sal &gt; ds.mysal; 如何衡量一個程序員的水平? 網絡處理能力, 數據庫, 程序代碼的優化程序的效率要很高 小總結: 在這裏須要說明的當在from子句中使用子查詢時,該子查詢會被做爲一個視圖來對待,所以叫作內嵌視圖,當在from子句中使用子查詢時,必須給子查詢指定別名。 注意:別名不能用as,如:SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) as ds WHERE e.deptno = ds.deptno AND e.sal &gt; ds.mysal; 在ds前不能加as,不然會報錯 (給表取別名的時候,不能加as;可是給列取別名,是能夠加as的) ? 分頁查詢 按僱員的id號升序取出 oracle的分頁一共有三種方式 1.根據rowid來分 select * from t_xiaoxi where rowid in (select rid from (select rownum rn, rid from(select rowid rid, cid from t_xiaoxi order by cid desc) where rownum&lt;10000) where rn&gt;9980) order by cid desc; 執行時間0.03秒 2.按分析函數來分 select * from (select t.*, row_number() over(order by cid desc) rk from t_xiaoxi t) where rk&lt;10000 and rk&gt;9980; 執行時間1.01秒 3.按rownum來分
Oracle 筆記
12
select * from (select t.*,rownum rn from(select * from t_xiaoxi order by cid desc)t where rownum&lt;10000) where rn&gt;9980; 執行時間0.1秒 其中t_xiaoxi爲表名稱,cid爲表的關鍵字段,取按cid降序排序後的第9981-9999條記錄,t_xiaoxi表有70000多條記錄。 我的感受1的效率最好,3次之,2最差。 //測試經過的分頁查詢okokok select * from (select a1.*, rownum rn from(select ename,job from emp) a1 where rownum&lt;=10)where rn&gt;=5; 下面最主要介紹第三種:按rownum來分 1. rownum 分頁 SELECT * FROM emp; 2. 顯示rownum[oracle分配的] SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e; rn至關於Oracle分配的行的ID號 3.挑選出6—10條記錄 先查出1-10條記錄 SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM &lt;= 10; 若是後面加上rownum&gt;=6是不行的, 4. 而後查出6-10條記錄 SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM &lt;= 10) WHERE rn &gt;= 6; 5. 幾個查詢變化 a. 指定查詢列,只須要修改最裏層的子查詢 只查詢僱員的編號和工資 SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT ename, sal FROM emp) e WHERE ROWNUM &lt;= 10) WHERE rn &gt;= 6; b. 排序查詢,只須要修改最裏層的子查詢 工資排序後查詢6-10條數據 SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT ename, sal FROM emp ORDER by sal) e WHERE ROWNUM &lt;= 10) WHERE rn &gt;= 6; ? 用查詢結果建立新表 這個命令是一種快捷的建表方式 CREATE TABLE mytable (id, name, sal, job, deptno) as SELECT empno, ename, sal, job, deptno FROM emp; 建立好以後,desc mytable;和select * from mytable;看看結果如何? 合併查詢 ? 合併查詢 有時在實際應用中,爲了合併多個select語句的結果,能夠使用集合操做符號union,union all,intersect,minus 多用於數據量比較大的數據局庫,運行速度快。 1). union 該操做符用於取得兩個結果集的並集。當使用該操做符時,會自動去掉結果集中重複行。 SELECT ename, sal, job FROM emp WHERE sal &gt;2500 UNION SELECT ename, sal, job FROM emp WHERE job = 'MANAGER'; 2).union all 該操做符與union類似,可是它不會取消重複行,並且不會排序。 SELECT ename, sal, job FROM emp WHERE sal &gt;2500 UNION ALL SELECT ename, sal, job FROM emp WHERE job = 'MANAGER';
Oracle 筆記
13
該操做符用於取得兩個結果集的並集。當使用該操做符時,會自動去掉結果集中重複行。 3). intersect 使用該操做符用於取得兩個結果集的交集。 SELECT ename, sal, job FROM emp WHERE sal &gt;2500 INTERSECT SELECT ename, sal, job FROM emp WHERE job = 'MANAGER'; 4). minus 使用改操做符用於取得兩個結果集的差集,他只會顯示存在第一個集合中,而不存在第二個集合中的數據。 SELECT ename, sal, job FROM emp WHERE sal &gt;2500 MINUS SELECT ename, sal, job FROM emp WHERE job = 'MANAGER'; (MINUS就是減法的意思) 建立數據庫有兩種方法: 1). 經過oracle提供的嚮導工具。√ database Configuration Assistant 【數據庫配置助手】 2).咱們能夠用手工步驟直接建立。
7.java操做oracle 內容介紹 1.上節回顧 2.java程序如何操做oracle √ 3.如何在oracle中操做數據 4.oracle事務處理 5.sql函數的使用 √ 指望目標 1.掌握oracle表對數據操做技巧 2.掌握在java程序中操做oracle 3.理解oracle事物概念 4.掌握oracle各類sql函數 java鏈接oracle ? 介紹 前面咱們一直在plsql中操做oracle,那麼如何在java 程序中操做數據庫呢? 下面咱們舉例說明,寫一個java,分頁顯示emp表的用戶信息。
package com.sp;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
//演示 如何使用 jdbc_odbc橋鏈接方式
public class TestOracle {
public static void main(String[] args) {
try {
// 1.加載驅動
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Oracle 筆記
14
// 2.獲得鏈接
Connection ct = DriverManager.getConnection(
"jdbc.odbc:testConnectOracle", "scott",
"tiger");
// 從下面開始,和SQL Server如出一轍
Statement sm = ct.createStatement();
ResultSet rs = sm.executeQuery("select * from emp");
while (rs.next()) {
//用戶名
System.out.println("用戶名: "+rs.getString(2));
//默認是從1開始編號的
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
在獲得鏈接那裏,要去配置數據源,點擊控制面板--&gt;系統和安全--&gt;管理工具--&gt;數據源(ODBC), 打開後點添加,如圖: 能夠看到,有個Oracle in OraDb10g_home1的驅動,它是Oracle安裝完後自動加上去的。 選中 後,點完成,再填以下信息,如圖: 這樣配好後基本就能夠了,但爲了安全起見,建議你們測試一下,點擊 Test Connection按鈕, 測試經過後點ok,而後數據源就生成了,如圖: 而後把數據源名稱寫進jdbc.odbc:???裏。 這裏要注意:jdbcodbc能不能遠程鏈接呢?不能遠程鏈接,也就是你這樣寫的話就意味着java程 序和oracle數據庫應該是在同一臺機器上,由於這裏沒有指定IP地址,確定默認就是本地。 如 果要遠程連,就用jdbc,jdbc是能夠遠程連的。 運行TestOracle.java,控制檯輸出....................... 惋惜我沒運行成功,說 java.sql.SQLException: No suitable driver found for jdbc.odbc:testConnectOracle at java.sql.DriverManager.getConnection(Unknown Source) at java.sql.DriverManager.getConnection(Unknown Source) at com.sp.TestOracle.main(TestOracle.java:18) 不知道爲何。。。 接下來說解用JDBC的方式鏈接Oracle
package com.sp;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
//使用 jdbc鏈接oracle
public class TestOracle2 {
public static void main(String[] args) {
try {
// 1.加載驅動
Oracle 筆記
15
Class.forName("oracle.jdbc.driver.OracleDriver");
// 2.獲得鏈接
Connection ct = DriverManager.getConnection
("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");
// 從下面開始,和SQL Server如出一轍
Statement sm = ct.createStatement();
ResultSet rs = sm.executeQuery("select * from emp");
while (rs.next()) {
//用戶名
System.out.println("用戶名: "+rs.getString(2));
//默認是從1開始編號的
}
} catch (Exception e) {
e.printStackTrace();
}
}
} 記得要把驅動包引入,classes12.jar 運行,。。。。 再次惋惜,我仍是沒運行成功,錯誤是: java.sql.SQLException: Io 異常: The Network Adapter could not establish the connection at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134) at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179) at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:334) at oracle.jdbc.driver.OracleConnection.&lt;init&gt;(OracleConnection.java:418) at oracle.jdbc.driver.OracleDriver.getConnectionInstance (OracleDriver.java:521) at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:325) at java.sql.DriverManager.getConnection(Unknown Source) at java.sql.DriverManager.getConnection(Unknown Source) at com.sp.TestOracle2.main(TestOracle2.java:18) 我也不知道爲何。。。 幽怨了。。 接下來建個web project,來測試oracle的分頁,挺麻煩,不記錄了。。 在oracle中操做數據 - 使用特定格式插入日期值 ? 使用 to_date函數 請你們思考: 如何插入列帶有日期的表,並按照年-月-日的格式插入? insert into emp values (9998, 'xiaohong', 'MANAGER', 7782, to_date('1988-12- 12', 'yyyy-mm-dd'), 78.9, 55.33, 10); 注意: insert into emp values (9998, 'xiaohong', 'MANAGER', 7782, '12-12月-1988', 78.9, 55.33, 10); 這句語句是能夠成功運行的 使用子查詢插入數據 ? 介紹 當使用valus子句時,一次只能插入一行數據,當使用子查詢插入數據時,一條inset語句能夠插
Oracle 筆記
16
入大量的數據。當處理行遷移或者裝載外部表的數據到數據庫時,能夠使用子查詢來插入數據。 把emp表中10號部門的數據導入到新表中 create table kkk(myId number(4), myName varchar2(50), myDept number(5)); insert into kkk (myId, myName, myDept) select empno, ename, deptno from emp where deptno = 10; ? 介紹 使用update語句更新數據時,既能夠使用表達式或者數值直接修改數據,也能夠使用子查詢修改 數據。 問題:但願員工SCOTT的崗位、工資、補助與SMITH員工同樣。 update emp set(job, sal, comm)=(select job, sal, comm from emp where ename='SMITH') where ename='SCOTT';
8.oracle中事務處理
? 什麼是事務 事務用於保證數據的一致性,它由一組相關的dml語句組成,該組的dml(數據操做語言,增刪改,沒有查詢)語句要麼所有成功,要麼所有失敗。 如:網上轉帳就是典型的要用事務來處理,用於保證數據的一致性。 dml 數據操做語言 銀行轉帳、QQ申請、車票購買 ? 事務和鎖 當執行事務操做時(dml語句),oracle會在被做用的表上加鎖,防止其它用戶修改表的結構。這裏對咱們的用戶來來說是很是重要的。 .....其它進程排序,知道1號進程完成,鎖打開,2號進程進入。依次進行,若是有進程級別較高的,能夠插隊。 ? 提交事務 當執行用commit語句能夠提交事務。當執行了commit語句以後,會確認事務的變化、結束事務。刪除保存點、釋放鎖,當使用commit語句結束事務以後,其它會話將能夠查看到事務變化後的新數據。 保存點就是爲回退作的。保存點的個數沒有限制 ? 回退事務 在介紹回退事務前,咱們先介紹一下保存點(savepoint)的概念和做用。保存點是事務中的一點。用於取消部分事務,當結束事務時,會自動的刪除該事務所定義的全部保存點。當執行rollback時,經過指定保存點能夠回退到指定的點,這裏咱們做圖說明。 ? 事務的幾個重要操做 1.設置保存點 savepoint a 2.取消部分事務 rollback to a 3.取消所有事務 rollback 注意:這個回退事務,必須是沒有commit前使用的;若是事務提交了,那麼不管你剛纔作了多少個保存點,都通通沒有。 若是沒有手動執行commit,而是exit了,那麼會自動提交 ? java程序中如何使用事務 在java操做數據庫時,爲了保證數據的一致性,好比帳戶操做(1)從一個帳戶中減掉10$(2)在另外一個帳戶上加入10$,咱們看看如何使用事務?
package com.sp;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
Oracle 筆記
17
import java.sql.Statement;
public class TestTrans {
public static void main(String[] args) {
try {
// 1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
// 2.獲得鏈接
Connection ct = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");
Statement sm = ct.createStatement();
// 從scott的sal中減去100
sm.executeUpdate("update emp set sal=sal-100 where ename='SCOTT'");
int i = 7 / 0;
// 給smith的sal加上100
sm.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");
// 關閉打開的資源
sm.close();
ct.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
運行,會出現異常,查看數據庫,SCOTT的sal減了100,可是SMITH的sal卻不變,很可怕。。。 咱們怎樣才能保證,這兩個操做要麼同時成功,要麼同時失敗呢?
package com.sp;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestTrans {
public static void main(String[] args) {
Connection ct = null;
try {
// 1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
// 2.獲得鏈接
ct = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");
// 加入事務處理
ct.setAutoCommit(false);// 設置不能默認提交
Statement sm = ct.createStatement();
// 從scott的sal中減去100
sm.executeUpdate("update emp set sal=sal-100 where ename='SCOTT'");
int i = 7 / 0;
Oracle 筆記
18
// 給smith的sal加上100
sm.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");
// 提交事務
ct.commit();
// 關閉打開的資源
sm.close();
ct.close();
} catch (Exception e) {
// 若是發生異常,就回滾
try {
ct.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
再運行一下,會出現異常,查看數據庫,數據沒變化。。 ? 只讀事務 只讀事務是指只容許執行查詢的操做,而不容許執行任何其它dml操做的事務,使用只讀事務能夠確保用戶只能取得某時間點的數據。假定機票代售點天天18點開始統計今天的銷售狀況,這時能夠使用只讀事務。在設置了只讀事務後,儘管其它會話可能會提交新的事務,可是隻讀事務將不會取得最新數據的變化,從而能夠保證取得特定時間點的數據信息。 ? 設置只讀事務 set transaction read only;
9.oracle的函數
sql函數的使用 字符函數? 介紹 字符函數是oracle中最經常使用的函數,咱們來看看有哪些字符函數: ? lower(char):將字符串轉化爲小寫的格式。 ? upper(char):將字符串轉化爲大寫的格式。 ? length(char):返回字符串的長度。 ? substr(char,m,n):取字符串的子串 n表明取n個的意思,不是表明取到第n個 ? replace(char1,search_string,replace_string) ? instr(char1,char2,[,n[,m]])取子串在字符串的位置 問題:將全部員工的名字按小寫的方式顯示 SQL&gt; select lower(ename) from emp; 問題:將全部員工的名字按大寫的方式顯示。 SQL&gt; select upper(ename) from emp; 問題:顯示正好爲5個字符的員工的姓名。 SQL&gt; select * from emp where length(ename)=5; 問題:顯示全部員工姓名的前三個字符。
Oracle 筆記
19
SQL&gt; select substr(ename,1,3) from emp; 問題:以首字母大寫,後面小寫的方式顯示全部員工的姓名。 SQL&gt; select upper(substr(ename,1,1)) || lower(substr(ename,2,length(ename)-1)) from emp; 問題:以首字母小寫,後面大寫的方式顯示全部員工的姓名。 SQL&gt; select lower(substr(ename,1,1)) || upper(substr(ename,2,length(ename)-1)) from emp; 問題:顯示全部員工的姓名,用「我是老虎」替換全部「A」 SQL&gt; select replace(ename,'A', '我是老虎') from emp; 數學函數? 介紹 數學函數的輸入參數和返回值的數據類型都是數字類型的。數學函數包括cos,cosh,exp,ln, log,sin,sinh,sqrt,tan,tanh,acos,asin,atan,round,咱們講最經常使用的: ? round(n,[m]) 該函數用於執行四捨五入,若是省掉m,則四捨五入到整數,若是m是正數,則四捨五入到小數點的m位後。若是m是負數,則四捨五入到小數點的m位前。 ? trunc(n,[m]) 該函數用於截取數字。若是省掉m,就截去小數部分,若是m是正數就截取到小數點的m位後,若是m是負數,則截取到小數點的前m位。 ? mod(m,n) ? floor(n) 返回小於或是等於n的最大整數 ? ceil(n) 返回大於或是等於n的最小整數 對數字的處理,在財務系統或銀行系統中用的最多,不一樣的處理方法,對財務報表有不一樣的結果。 問題:顯示在一個月爲30天的狀況下,全部員工的日薪金,忽略餘數。 SQL&gt; select trunc(sal/30), ename from emp; or SQL&gt; select floor(sal/30), ename from emp; 在作oracle測試的時候,能夠使用dual表 select mod(10,2) from dual;結果是0 select mod(10,3) from dual;結果是1 其它的數學函數,有興趣的同窗能夠本身去看看: abs(n): 返回數字n的絕對值 select abs(-13) from dual; acos(n): 返回數字的反餘弦值 asin(n): 返回數字的反正弦值 atan(n): 返回數字的反正切值 cos(n): exp(n): 返回e的n次冪 log(m,n): 返回對數值 power(m,n): 返回m的n次冪 日期函數? 介紹 日期函數用於處理date類型的數據。 默認狀況下日期格式是dd-mon-yy 即12-7月-78 (1)sysdate: 該函數返回系統時間 (2)add_months(d,n) (3)last_day(d):返回指定日期所在月份的最後一天 問題:查找已經入職8個月多的員工 SQL&gt; select * from emp where sysdate&gt;=add_months(hiredate,8); 問題:顯示滿10年服務年限的員工的姓名和受僱日期。
Oracle 筆記
20
SQL&gt; select ename, hiredate from emp where sysdate&gt;=add_months(hiredate,12*10); 問題:對於每一個員工,顯示其加入公司的天數。 SQL&gt; select floor(sysdate-hiredate) "入職天數",ename from emp; or SQL&gt; select trunc(sysdate-hiredate) "入職天數",ename from emp; 問題:找出各月倒數第3天受僱的全部員工。 SQL&gt; select hiredate,ename from emp where last_day(hiredate)-2=hiredate; 轉換函數 ? 介紹√ 轉換函數用於將數據類型從一種轉爲另一種。在某些狀況下,oracle server容許值的數據類型和實際的不同,這時oracle server會隱含的轉化數據類型 好比: create table t1(id int); insert into t1 values('10');--&gt;這樣oracle會自動的將'10' --&gt;10 create table t2 (id varchar2(10)); insert into t2 values(1); --&gt;這樣oracle就會自動的將1 --&gt;'1'; 咱們要說的是儘管oracle能夠進行隱含的數據類型的轉換,可是它並不適應全部的狀況,爲了提升程序的可靠性,咱們應該使用轉換函數進行轉換。 ? to_char 你能夠使用select ename, hiredate, sal from emp where deptno = 10;顯示信息,但是,在某些狀況下,這個並不能知足你的需求。 問題:日期是否能夠顯示 時/分/秒 SQL&gt; select ename, to_char(hiredate, 'yyyy-mm-dd hh24:mi:ss') from emp; 問題:薪水是否能夠顯示指定的貨幣符號 SQL&gt; yy:兩位數字的年份 2004--&gt;04 yyyy:四位數字的年份 2004年 mm:兩位數字的月份 8月--&gt;08 dd:兩位數字的天 30號--&gt;30 hh24: 8點--&gt;20 hh12:8點--&gt;08 mi、ss--&gt;顯示分鐘\秒 9:顯示數字,並忽略前面0 0:顯示數字,如位數不足,則用0補齊 .:在指定位置顯示小數點 ,:在指定位置顯示逗號 $:在數字前加美圓 L:在數字前面加本地貨幣符號 C:在數字前面加國際貨幣符號 G:在指定位置顯示組分隔符、 D:在指定位置顯示小數點符號(.) 問題:顯示薪水的時候,把本地貨幣單位加在前面 SQL&gt; select ename, to_char(hiredate, 'yyyy-mm-dd hh24:mi:ss'), to_char(sal,'L99999.99') from emp; 問題:顯示1980年入職的全部員工 SQL&gt; select * from emp where to_char(hiredate, 'yyyy')=1980;
Oracle 筆記
21
問題:顯示全部12月份入職的員工 SQL&gt; select * from emp where to_char(hiredate, 'mm')=12; ? to_date 函數to_date用於將字符串轉換成date類型的數據。 問題:可否按照中國人習慣的方式年—月—日添加日期。 系統函數 ? sys_context 1)terminal:當前會話客戶所對應的終端的標示符 2)lanuage: 語言 3)db_name: 當前數據庫名稱 4)nls_date_format: 當前會話客戶所對應的日期格式 5)session_user: 當前會話客戶所對應的數據庫用戶名 6)current_schema: 當前會話客戶所對應的默認方案名 7)host: 返回數據庫所在主機的名稱 經過該函數,能夠查詢一些重要信息,好比你正在使用哪一個數據庫? select sys_context('USERENV','db_name') from dual; 注意:USERENV是固定的,不能改的,db_name能夠換成其它,好比select sys_context('USERENV','lanuage') from dual;又好比select sys_context('USERENV','current_schema') from dual;
10.數據庫管理,表的邏輯備份與恢復
內容介紹 1.上節回顧 2.數據庫管理員 3.數據庫(表)的邏輯備份與恢復 √ 4.數據字典和動態性能視圖 √ 5.管理表空間和數據文件 √ 指望目標 1.瞭解oracle管理員的基本職責 2.掌握備份和恢復數據庫/表的方法 3.理解表空間、數據字典、性能視圖 數據庫管理員 ? 介紹 每一個oracle數據庫應該至少有一個數據庫管理員(dba),對於一個小的數據庫,一個dba就夠了,可是對於一個大的數據庫可能須要多個dba分擔不一樣的管理職責。那麼一個數據庫管理員的主要工做是什麼呢: ? 職責 1.安裝和升級oracle數據庫 2.建庫,表空間,表,視圖,索引? 3.制定並實施備份和恢復計劃 4.數據庫權限管理,調優,故障排除 5.對於高級dba,要求能參與項目開發,會編寫sql語句、存儲過程、觸發器、規則、約束、包 ? 管理數據庫的用戶主要是sys和system (sys好像是董事長,system好像是總經理,董事長比總經理大,可是一般是總經理幹事) 在前面咱們已經提到這兩個用戶,區別主要是: 1.最重要的區別,存儲的數據的重要性不一樣
Oracle 筆記
22
sys:全部oracle的數據字典的基表和視圖都存放在sys用戶中,這些基表和視圖對於oracle的運行是相當重要的,由數據庫本身維護,任何用戶都不能手動更改。sys用戶擁有dba,sysdba,sysoper角色或權限,是oracle權限最高的用戶。 system:用於存放次一級的內部數據,如oracle的一些特性或工具的管理信息。system用戶擁有dba,sysdba角色或系統權限。 看圖: sysdba能夠建數據庫,sysope不能建數據庫 2. 其次的區別,權限的不一樣。 sys用戶必須以as sysdba或as sysoper形式登陸。不能以normal方式登陸數據庫 system若是正常登陸,它其實就是一個普通的dba用戶,可是若是以as sysdba登陸,其結果實際上它是做爲sys用戶登陸的,從登陸信息裏面咱們能夠看出來。 sysdba和sysoper權限區別圖,看圖: sysdba&gt;sysoper&gt;dba 能夠看到:只要是sysoper擁有的權限,sysdba都有;藍色是它們區別的地方。(它們的最大區別是:sysdba能夠建立數據庫,sysoper不能夠建立數據庫) ? dba權限的用戶 dba用戶是指具備dba角色的數據庫用戶。特權用戶能夠執行啓動實例,關閉實例等特殊操做,而dba用戶只有在啓動數據庫後才能執行各類管理工做。 (至關於說dba連startup和shutdown這兩個權限都沒有) 兩個主要的用戶,三個重要權限,他們的區別和聯繫,你們要弄清楚 管理初始化參數 ? 管理初始化參數(調優的一個重要知識點,憑什麼能夠對數據庫進行調優呢?是由於它能夠對數據庫的一些參數進行修改修正) 初始化參數用於設置實例或是數據庫的特徵。oracle9i提供了200多個初始化參數,而且每一個初始化參數都有默認值。 ? 顯示初始化參數 (1) show parameter命令 ? 如何修改參數 須要說明的若是你但願修改這些初始化的參數,能夠到文件D:\oracle\admin\myoral\pfile\init.ora文件中去修改好比要修改實例的名字 數據庫(表)的邏輯備份與恢復 介紹 ? 介紹 邏輯備份是指使用工具export將數據對象的結構和數據導出到文件的過程,邏輯恢復是指當數據庫對象被誤操做而損壞後使用工具import利用備份的文件把數據對象導入到數據庫的過程。 物理備份便可在數據庫open的狀態下進行也可在關閉數據庫後進行,可是邏輯備份和恢復只能在open的狀態下進行。 看圖: ? 導出 導出具體的分爲:導出表,導出方案,導出數據庫三種方式。 導出使用exp命令來完成的,該命令經常使用的選項有: userid: 用於指定執行導出操做的用戶名,口令,鏈接字符串 tables: 用於指定執行導出操做的表 owner: 用於指定執行導出操做的方案 full=y: 用於指定執行導出操做的數據庫 inctype: 用於指定執行導出操做的增量類型 rows: 用於指定執行導出操做是否要導出表中的數據 file: 用於指定導出文件名
Oracle 筆記
23
? 導出表 1.導出本身的表 exp userid=scott/tiger@myoral tables=(emp,dept) file=d:\e1.dmp 2.導出其它方案的表 若是用戶要導出其它方案的表,則須要dba的權限或是exp_full_database的權限,好比system就能夠導出scott的表 E:\oracle\ora92\bin&gt;exp userid=system/manager@myoral tables=(scott.emp) file=d:\e2.emp 特別說明:在導入和導出的時候,要到oracle目錄的bin目錄下。 3. 導出表的結構 exp userid=scott/tiger@accp tables=(emp) file=d:\e3.dmp rows=n 4. 使用直接導出方式 exp userid=scott/tiger@accp tables=(emp) file=d:\e4.dmp direct=y 這種方式比默認的常規方式速度要快,當數據量大時,能夠考慮使用這樣的方法。 這時須要數據庫的字符集要與客戶端字符集徹底一致,不然會報錯... ? 導出方案 導出方案是指使用export工具導出一個方案或是多個方案中的全部對象(表,索引,約束...)和數據。並存放到文件中。 1. 導出本身的方案 exp userid=scott/tiger@myorcl owner=scott file=d:\scott.dmp 2. 導出其它方案 若是用戶要導出其它方案,則須要dba的權限或是exp_full_database的權限,好比system用戶就能夠導出任何方案 exp userid=system/manager@myorcl owner=(system,scott) file=d:\system.dmp ? 導出數據庫 導出數據庫是指利用export導出全部數據庫中的對象及數據,要求該用戶具備dba的權限或者是exp_full_database權限 增量備份(好處是第一次備份後,第二次備份就快不少了) exp userid=system/manager@myorcl full=y inctype=complete file=d:\all.dmp 導入 ? 介紹 導入就是使用工具import將文件中的對象和數據導入到數據庫中,可是導入要使用的文件必須是export所導出的文件。與導出類似,導入也分爲導入表,導入方案,導入數據庫三種方式。 imp經常使用的選項有 userid: 用於指定執行導入操做的用戶名,口令,鏈接字符串 tables: 用於指定執行導入操做的表 formuser: 用於指定源用戶 touser: 用於指定目標用戶 file: 用於指定導入文件名 full=y: 用於指定執行導入整個文件 inctype: 用於指定執行導入操做的增量類型 rows: 指定是否要導入錶行(數據) ignore: 若是表存在,則只導入數據 ? 導入表 1. 導入本身的表 imp userid=scott/tiger@myorcl tables=(emp) file=d:\xx.dmp 2. 導入表到其它用戶 要求該用戶具備dba的權限,或是imp_full_database imp userid=system/tiger@myorcl tables=(emp) file=d:\xx.dmp touser=scott 3. 導入表的結構
Oracle 筆記
24
只導入表的結構而不導入數據 imp userid=scott/tiger@myorcl tables=(emp) file=d:\xx.dmp rows=n 4. 導入數據 若是對象(如比表)已經存在能夠只導入表的數據 imp userid=scott/tiger@myorcl tables=(emp) file=d:\xx.dmp ignore=y ? 導入方案 導入方案是指使用import工具將文件中的對象和數據導入到一個或是多個方案中。若是要導入其它方案,要求該用戶具備dba的權限,或者imp_full_database 1. 導入自身的方案 imp userid=scott/tiger file=d:\xxx.dmp 2. 導入其它方案 要求該用戶具備dba的權限 imp userid=system/manager file=d:\xxx.dmp fromuser=system touser=scott ? 導入數據庫 在默認狀況下,當導入數據庫時,會導入全部對象結構和數據,案例以下: imp userid=system/manager full=y file=d:\xxx.dmp
11.數據字典和動態性能視圖 介紹:數據字典是什麼 數據字典是oracle數據庫中最重要的組成部分,它提供了數據庫的一些系統信息。 動態性能視圖記載了例程啓動後的相關信息。 ? 數據字典 數據字典記錄了數據庫的系統信息,它是隻讀表和視圖的集合,數據字典的全部者爲sys用戶。 用戶只能在數據字典上執行查詢操做(select語句),而其維護和修改是由系統自動完成的。 這裏咱們談談數據字典的組成:數據字典包括數據字典基表和數據字典視圖,其中基表存儲數據庫的基本信息,普通用戶不能直接訪問數據字典的基表。數據字典視圖是基於數據字典基表所創建的視圖,普通用戶能夠經過查詢數據字典視圖取得系統信息。數據字典視圖主要包括user_xxx,all_xxx,dba_xxx三種類型。 ? user_tables; 用於顯示當前用戶所擁有的全部表,它只返回用戶所對應方案的全部表 好比:select table_name from user_tables; ? all_tables; 用於顯示當前用戶能夠訪問的全部表,它不只會返回當前用戶方案的全部表,還會返回當前用戶能夠訪問的其它方案的表: 好比:select table_name from all_tables; ? dba_tables; 它會顯示全部方案擁有的數據庫表。可是查詢這種數據庫字典視圖,要求用戶必須是dba角色或是有select any table系統權限。 例如:當用system用戶查詢數據字典視圖dba_tables時,會返回system,sys,scott...方案所對應的數據庫表。 ? 用戶名,權限,角色 在創建用戶時,oracle會把用戶的信息存放到數據字典中,當給用戶授予權限或是角色時,oracle會將權限和角色的信息存放到數據字典。 經過查詢dba_users能夠顯示全部數據庫用戶的詳細信息; 經過查詢數據字典視圖dba_sys_privs,能夠顯示用戶所具備的系統權限; 經過查詢數據字典視圖dba_tab_privs,能夠顯示用戶具備的對象權限; 經過查詢數據字典dba_col_privs能夠顯示用戶具備的列權限; 經過查詢數據庫字典視圖dba_role_privs能夠顯示用戶所具備的角色。
Oracle 筆記
25
這裏給你們再講講角色和權限的關係。 例如:要查看scott具備的角色,可查詢dba_role_privs; SQL&gt; select * from dba_role_privs where grantee='SCOTT'; //查詢orale中全部的系統權限,通常是dba select * from system_privilege_map order by name; //查詢oracle中全部對象權限,通常是dba select distinct privilege from dba_tab_privs; //查詢oracle中全部的角色,通常是dba select * from dba_roles; //查詢數據庫的表空間 select tablespace_name from dba_tablespaces; 問題1:如何查詢一個角色包括的權限? a.一個角色包含的系統權限 select * from dba_sys_privs where grantee='角色名' 另外也能夠這樣查看: select * from role_sys_privs where role='角色名' b.一個角色包含的對象權限 select * from dba_tab_privs where grantee='角色名' 問題2:oracle究竟有多少種角色? SQL&gt; select * from dba_roles; 問題3:如何查看某個用戶,具備什麼樣的角色? select * from dba_role_privs where grantee='用戶名' ? 顯示當前用戶能夠訪問的全部數據字典視圖。 select * from dict where comments like '%grant%'; ? 顯示當前數據庫的全稱 select * from global_name; ? 其它說明 數據字典記錄有oracle數據庫的全部系統信息。經過查詢數據字典能夠取得如下系統信息:好比 1.對象定義狀況 2.對象佔用空間大小 3.列信息 4.約束信息 ... 可是由於這些個信息,能夠經過pl/sql developer工具查詢獲得,因此這裏我就飄過。 ? 動態性能視圖 動態性能視圖用於記錄當前例程的活動信息,當啓動oracle server時,系統會創建動態性能視圖;當中止oracle server時,系統會刪除動態性能視圖。oracle的全部動態性能視圖都是以v_$開始的,而且oracle爲每一個動態性能視圖都提供了相應的同義詞,而且其同義詞是以V$開始的,例如v_$datafile的同義詞爲v$datafile;動態性能視圖的全部者爲sys,通常狀況下,由dba或是特權用戶來查詢動態性能視圖。 由於這個在實際中用的較少,因此飛過。
12.數據庫管理 -- 管理表空間和數據文件 ? 介紹 表空間是數據庫的邏輯組成部分。從物理上講,數據庫數據存放在數據文件中;從邏輯上講,數據庫則是存放在表空間中,表空間由一個或多個數據文件組成。
Oracle 筆記
26
數據庫的邏輯結構 ? 介紹 oracle中邏輯結構包括表空間、段、區和塊。 說明一下數據庫由表空間構成,而表空間又是由段構成,而段又是由區構成,而區又是由oracle塊構成的這樣的一種結構,能夠提升數據庫的效率。 爲了讓你們明白,咱們畫圖說明邏輯關係:看圖: 表空間 ? 介紹 表空間用於從邏輯上組織數據庫的數據。數據庫邏輯上是由一個或是多個表空間組成的。經過表空間能夠達到如下做用: 1. 控制數據庫佔用的磁盤空間 2. dba能夠將不一樣數據類型部署到不一樣的位置,這樣有利於提升i/o性能,同時利於備份和恢復等管理操做。 ? 創建表空間 創建表空間是使用crate tablespace命令完成的,須要注意的是,通常狀況下,創建表空間是特權用戶或是dba來執行的,若是用其它用戶來建立表空間,則用戶必需要具備create tablespace的系統權限。 ? 創建數據表空間 在創建數據庫後,爲便於管理表,最好創建本身的表空間 create tablespace data01 datafile 'd:\test\dada01.dbf' size 20m uniform size 128k; 說明:執行完上述命令後,會創建名稱爲data01的表空間,併爲該表空間創建名稱爲data01.dbf的數據文件,區的大小爲128k ? 使用數據表空間 create table mypart(deptno number(4), dname varchar2(14), loc varchar2(13)) tablespace data01; ? 改變表空間的狀態 當創建表空間時,表空間處於聯機的(online)狀態,此時該表空間是能夠訪問的,而且該表空間是能夠讀寫的,便可以查詢該表空間的數據,並且還能夠在表空間執行各類語句。可是在進行系統維護或是數據維護時,可能須要改變表空間的狀態。通常狀況下,由特權用戶或是dba來操做。 1. 使表空間脫機 alter tablespace 表空間名 offline; 2. 使表空間聯機 alter tablespace 表空間名 online; 3. 只讀表空間 當創建表空間時,表空間能夠讀寫,若是不但願在該表空間上執行update,delete,insert操做,那麼能夠將表空間修改成只讀 alter tablespace 表空間名 read only; (修改成可寫是 alter tablespace 表空間名 read write;) ? 改變表空間的狀態 咱們給你們舉一個實例,說明只讀特性: 1. 知道表空間名,顯示該表空間包括的全部表 select * from all_tables where tablespace_name=’表空間名’; 2. 知道表名,查看該表屬於那個表空間 select tablespace_name, table_name from user_tables where table_name=’emp’; 經過2.咱們能夠知道scott.emp是在system這個表空間上,如今咱們能夠將system改成只讀的可是咱們不會成功,由於system是系統表空間,若是是普通表空間,那麼咱們就能夠將其設爲只讀的,給你們作一個演示,能夠增強理解。 3. 4. 使表空間可讀寫 alter tablespace 表空間名 read write; ? 刪除表空間
Oracle 筆記
27
通常狀況下,由特權用戶或是dba來操做,若是是其它用戶操做,那麼要求用戶具備drop tablespace系統權限。 drop tablespace ‘表空間’ including contents and datafiles; 說明:including contents表示刪除表空間時,刪除該空間的全部數據庫對象,而datafiles表示將數據庫文件也刪除。 ? 擴展表空間 表空間是由數據文件組成的,表空間的大小實際上就是數據文件相加後的大小。那麼咱們能夠想象,假定表employee存放到data01表空間上,初始大小就是2M,當數據滿2M空間後,若是在向employee表插入數據,這樣就會顯示空間不足的錯誤。 案例說明: 1. 創建一個表空間 sp01 2. 在該表空間上創建一個普通表 mydment 其結構和dept同樣 3. 向該表中加入數據 insert into mydment select * from dept; 4. 當必定時候就會出現沒法擴展的問題,怎麼辦? 5. 就擴展該表空間,爲其增長更多的存儲空間。有三種方法: 1. 增長數據文件 SQL&gt; alter tablespace sp01 add datafile ‘d:\test\sp01.dbf’ size 20m; 2. 增長數據文件的大小 SQL&gt; alter tablespace 表空間名 ‘d:\test\sp01.dbf’ resize 20m; 這裏須要注意的是數據文件的大小不要超過500m。 3. 設置文件的自動增加。 SQL&gt; alter tablespace 表空間名 ‘d:\test\sp01.dbf’ autoextend on next 10m maxsize 500m; ? 移動數據文件 有時,若是你的數據文件所在的磁盤損壞時,該數據文件將不能再使用,爲了可以從新使用,須要將這些文件的副本移動到其它的磁盤,而後恢復。 下面以移動數據文件sp01.dbf爲例來講明: 1. 肯定數據文件所在的表空間 select tablespace_name from dba_data_files where file_name=’d:\test\sp01.dbf’; 2. 使表空間脫機 確保數據文件的一致性,將表空間轉變爲offline的狀態。 alter tablespace sp01(表空間名) offline; 3. 使用命令移動數據文件到指定的目標位置 host move d:\test\sp01.dbf c:\test\sp01.dbf 4. 執行alter tablespace命令 在物理上移動了數據後,還必須執行alter tablespace命令對數據庫文件進行邏輯修改: alter tablespace sp01 rename datafile ‘d:\test\sp01.dbf’ to ‘c:\test\sp01.dbf’; 5. 使得表空間聯機 在移動了數據文件後,爲了使用戶能夠訪問該表空間,必須將其轉變爲online狀態。 alter tablespace sp01(表空間名) online; ? 顯示錶空間信息 查詢數據字典視圖dba_tablespaces,顯示錶空間的信息: select tablespace_name from dba_tablespaces; ? 顯示錶空間所包含的數據文件 查詢數據字典視圖dba_data_files,可顯示錶空間所包含的數據文件,以下: select file_name, bytes from dba_data_files where tablespce_name=’表空間’; ? 表空間小結 1. 瞭解表空間和數據文件的做用
Oracle 筆記
28
2. 掌握經常使用表空間,undo表空間和臨時表空間的創建方法 3. 瞭解表空間的各個狀態(online, offline, read write, read only)的做用,及如何改變表空間的狀態的方法。 4. 瞭解移動數據文件的緣由,及使用alter tablespace 和alter datatable命令移動數據文件的方法。 ? 其它表空間 除了最經常使用的數據表空間外,還有其它類型表空間: 1. 索引表空間 2. undo表空間 3. 臨時表空間 4. 非標準塊的表空間 這幾種表空間,你們夥能夠本身參考書籍研究,這裏我就不講。 ? 其它說明 關於表空間的組成部分 段/區/塊,咱們在後面給你們講解。
13.約束 玩轉oracle實戰教程(第五天) 指望目標 1.掌握維護oracle數據完整性的技巧 2.理解索引概念,會創建索引 3.管理oracle的權限和角色 維護數據的完整性 ? 介紹 數據的完整性用於確保數據庫數據聽從必定的商業和邏輯規則,在oracle中,數據完整性能夠使用約束、觸發器、應用程序(過程、函數)三種方法來實現,在這三種方法中,由於約束易於維護,而且具備最好的性能,因此做爲維護數據完整性的首選。 約束 ? 約束 約束用於確保數據庫數據知足特定的商業規則。在oracle中,約束包括:not null、 unique, primary key, foreign key,和check五種。 使用 ? not null(非空) 若是在列上定義了not null,那麼當插入數據時,必須爲列提供數據。 ? unique(惟一) 當定義了惟一約束後,該列值是不能重複的,可是能夠爲null。 ? primary key(主鍵) 用於惟一的標示錶行的數據,當定義主鍵約束後,該列不但不能重複並且不能爲null。 須要說明的是:一張表最多隻能有一個主鍵,可是能夠有多個unqiue約束。 ? foreign key(外鍵) 用於定義主表和從表之間的關係。外鍵約束要定義在從表上,主表則必須具備主鍵約束或是unique約束,當定義外鍵約束後,要求外鍵列數據必須在主表的主鍵列存在或是爲null。 ? check 用於強制行數據必須知足的條件,假定在sal列上定義了check約束,並要求sal列值在1000-2000之間若是不在1000-2000之間就會提示出錯。 ? 商店售貨系統表設計案例 現有一個商店的數據庫,記錄客戶及其購物狀況,由下面三個表組成:商品goods(商品號goodsId,商品名 goodsName,單價 unitprice,商品類別category,供應商provider); 客戶customer(客戶號customerId,姓名name,住在address,電郵email,性別sex,身份證cardId);
Oracle 筆記
29
購買purchase(客戶號customerId,商品號goodsId,購買數量nums); 請用SQL語言完成下列功能: 1. 建表,在定義中要求聲明: (1). 每一個表的主外鍵; (2). 客戶的姓名不能爲空值; (3). 單價必須大於0,購買數量必須在1到30之間; (4). 電郵不可以重複; (5). 客戶的性別必須是 男 或者 女,默認是男; SQL&gt; create table goods(goodsId char(8) primary key, --主鍵 goodsName varchar2(30), unitprice number(10,2) check(unitprice&gt;0), category varchar2(8), provider varchar2(30) ); SQL&gt; create table customer( customerId char(8) primary key, --主鍵 name varchar2(50) not null, --不爲空 address varchar2(50), email varchar2(50) unique, sex char(2) default '男' check(sex in ('男','女')), -- 一個char能存半個漢字,兩位char能存一個漢字 cardId char(18) ); SQL&gt; create table purchase( customerId char(8) references customer(customerId), goodsId char(8) references goods(goodsId), nums number(10) check (nums between 1 and 30) ); 表是默認建在SYSTEM表空間的 維護 ? 商店售貨系統表設計案例(2) 若是在建表時忘記創建必要的約束,則能夠在建表後使用alter table命令爲表增長約束。可是要注意:增長not null約束時,須要使用modify選項,而增長其它四種約束使用add選項。 1. 增長商品名也不能爲空 SQL&gt; alter table goods modify goodsName not null; 2. 增長身份證也不能重複 SQL&gt; alter table customer add constraint xxxxxx unique(cardId); 3. 增長客戶的住址只能是’海淀’,’朝陽’,’東城’,’西城’,’通州’,’崇文’,’昌平’; SQL&gt; alter table customer add constraint yyyyyy check (address in (’海淀’,’朝陽’,’東城’,’西城’,’通州’,’崇文’,’昌平’)); ? 刪除約束 當再也不須要某個約束時,能夠刪除。 alter table 表名 drop constraint 約束名稱; 特別說明一下: 在刪除主鍵約束的時候,可能有錯誤,好比: alter table 表名 drop primary key; 這是由於若是在兩張表存在主從關係,那麼在刪除主表的主鍵約束時,必須帶上cascade選項 如像:
Oracle 筆記
30
alter table 表名 drop primary key cascade; ? 顯示約束信息 1.顯示約束信息 經過查詢數據字典視圖user_constraints,能夠顯示當前用戶全部的約束的信息。 select constraint_name, constraint_type, status, validated from user_constraints where table_name = '表名'; 2.顯示約束列 經過查詢數據字典視圖user_cons_columns,能夠顯示約束所對應的表列信息。 select column_name, position from user_cons_columns where constraint_name = '約束名'; 3.固然也有更容易的方法,直接用pl/sql developer查看便可。簡單演示一下下... 表級定義 列級定義 ? 列級定義 列級定義是在定義列的同時定義約束。 若是在department表定義主鍵約束 create table department4(dept_id number(12) constraint pk_department primary key, name varchar2(12), loc varchar2(12)); ? 表級定義 表級定義是指在定義了全部列後,再定義約束。這裏須要注意: not null約束只能在列級上定義。 以在創建employee2表時定義主鍵約束和外鍵約束爲例: create table employee2(emp_id number(4), name varchar2(15), dept_id number(2), constraint pk_employee primary key (emp_id), constraint fk_department foreign key (dept_id) references department4(dept_id));
14.Oracle索引、權限
管理索引-原理介紹 ? 介紹 索引是用於加速數據存取的數據對象。合理的使用索引能夠大大下降i/o次數,從而提升數據訪問性能。索引有不少種咱們主要介紹經常使用的幾種: 爲何添加了索引後,會加快查詢速度呢? 建立索引 ? 單列索引 單列索引是基於單個列所創建的索引,好比: create index 索引名 on 表名(列名); ? 複合索引 複合索引是基於兩列或是多列的索引。在同一張表上能夠有多個索引,可是要求列的組合必須不一樣,好比: create index emp_idx1 on emp (ename, job); create index emp_idx1 on emp (job, ename); 使用原則 ? 使用原則 1. 在大表上創建索引纔有意義 2. 在where子句或是鏈接條件上常常引用的列上創建索引 3. 索引的層次不要超過4層 這裏能不能給學生演示這個效果呢? 如何構建一個大表呢?
Oracle 筆記
31
索引的缺點 ? 索引缺點分析 索引有一些先天不足: 1. 創建索引,系統要佔用大約爲表1.2倍的硬盤和內存空間來保存索引。 2. 更新數據的時候,系統必需要有額外的時間來同時對索引進行更新,以維持數據和索引的一致性。 實踐代表,不恰當的索引不但於事無補,反而會下降系統性能。由於大量的索引在進行插入、修改和刪除操做時比沒有索引花費更多的系統時間。 好比在以下字段創建索引應該是不恰當的: 1. 不多或從不引用的字段; 2. 邏輯型的字段,如男或女(是或否)等。 綜上所述,提升查詢效率是以消耗必定的系統資源爲代價的,索引不能盲目的創建,這是考驗一個DBA是否優秀的很重要的指標。 其它索引 ? 介紹 按照數據存儲方式,能夠分爲B*樹、反向索引、位圖索引; 按照索引列的個數分類,能夠分爲單列索引、複合索引; 按照索引列值的惟一性,能夠分爲惟一索引和非惟一索引。 此外還有函數索引,全局索引,分區索引... 對於索引我還要說: 在不一樣的狀況,咱們會在不一樣的列上創建索引,甚至創建不一樣種類的索引,請記住,技術是死的,人是活的。好比: B*樹索引創建在重複值不多的列上,而位圖索引則創建在重複值不少、不一樣值相對固定的列上。 顯示索引信息 ? 顯示錶的全部索引 在同一張表上能夠有多個索引,經過查詢數據字典視圖dba_indexs和user_indexs,能夠顯示索引信息。其中dba_indexs用於顯示數據庫全部的索引信息,而user_indexs用於顯示當前用戶的索引信息: select index_name, index_type from user_indexes where table_name = '表名'; ? 顯示索引列 經過查詢數據字典視圖user_ind_columns,能夠顯示索引對應的列的信息 select table_name, column_name from user_ind_columns where index_name = 'IND_ENAME'; ? 你也能夠經過pl/sql developer工具查看索引信息 管理權限和角色 介紹 ? 介紹 這一部分咱們主要看看oracle中如何管理權限和角色,權限和角色的區別在那裏。 當剛剛創建用戶時,用戶沒有任何權限,也不能執行任何操做。若是要執行某種特定的數據庫操做,則必須爲其授予系統的權限;若是用戶要訪問其它方案的對象,則必須爲其授予對象的權限。爲了簡化權限的管理,能夠使用角色。這裏咱們會詳細的介紹。看圖: 權限 ? 權限 權限是指執行特定類型sql命令或是訪問其它方案對象的權利,包括系統權限和對象權限兩種。 系統權限 ? 系統權限介紹 系統權限是指執行特定類型sql命令的權利。它用於控制用戶能夠執行的一個或是一組數據庫操做。好比當用戶具備create table權限時,能夠在其方案中建表,當用戶具備create any table權限時,能夠在任何方案中建表。oracle提供了100多種系統權限。
Oracle 筆記
32
經常使用的有: create session 鏈接數據庫 create table 建表 create view 建視圖 create public synonym 建同義詞 create procedure 建過程、函數、包 create trigger 建觸發器 create cluster 建簇 ? 顯示系統權限 oracle提供了100多種系統權限,並且oracle的版本越高,提供的系統權限就越多,咱們能夠查詢數據字典視圖system_privilege_map,能夠顯示全部系統權限。 select * from system_privilege_map order by name; ? 授予系統權限 通常狀況,授予系統權限是由dba完成的,若是用其餘用戶來授予系統權限,則要求該用戶必須具備grant any privilege的系統權限。在授予系統權限時,能夠帶有with admin option選項,這樣,被授予權限的用戶或是角色還能夠將該系統權限授予其它的用戶或是角色。爲了讓你們快速理解,咱們舉例說明: 1.建立兩個用戶ken,tom。初始階段他們沒有任何權限,若是登陸就會給出錯誤的信息。 create user ken identfied by ken; 2 給用戶ken受權 1). grant create session, create table to ken with admin option; 2). grant create view to ken; 3 給用戶tom受權 咱們能夠經過ken給tom受權,由於with admin option是加上的。固然也能夠經過dba給tom受權,咱們就用ken給tom受權: 1. grant create session, create table to tom; 2. grant create view to ken; --ok嗎?不ok ? 回收系統權限 通常狀況下,回收系統權限是dba來完成的,若是其它的用戶來回收系統權限,要求該用戶必須具備相應系統權限及轉授系統權限的選項(with admin option)。回收系統權限使用revoke來完成。 當回收了系統權限後,用戶就不能執行相應的操做了,可是請注意,系統權限級聯收回的問題?[不是級聯回收!] system ---------&gt;ken ----------&gt;tom (create session)(create session)( create session) 用system執行以下操做: revoke create session from ken; --請思考tom還能登陸嗎? 答案:能,能夠登陸 對象權限 ? 對象權限介紹 指訪問其它方案對象的權利,用戶能夠直接訪問本身方案的對象,可是若是要訪問別的方案的對象,則必須具備對象的權限。 好比smith用戶要訪問scott.emp表(scott:方案,emp:表) 經常使用的有: alter 修改 delete 刪除 select 查詢 insert 添加 update 修改 index 索引 references 引用 execute 執行 ? 顯示對象權限 經過數據字段視圖能夠顯示用戶或是角色所具備的對象權限。視圖爲dba_tab_privs SQL&gt; conn system/manager; SQL&gt; select distinct privilege from dba_tab_privs; SQL&gt; select grantor, owner, table_name, privilege from dba_tab_privs where grantee = 'BLAKE';
Oracle 筆記
33
1.授予對象權限 在oracle9i前,授予對象權限是由對象的全部者來完成的,若是用其它的用戶來操做,則須要用戶具備相應的(with grant option)權限,從oracle9i開始,dba用戶(sys,system)能夠將任何對象上的對象權限授予其它用戶。授予對象權限是用grant命令來完成的。 對象權限能夠授予用戶,角色,和public。在授予權限時,若是帶有with grant option選項,則能夠將該權限轉授給其它用戶。可是要注意with grant option選項不能被授予角色。 1.monkey用戶要操做scott.emp表,則必須授予相應的對象權限 1). 但願monkey能夠查詢scott.emp表的數據,怎樣操做? grant select on emp to monkey; 2). 但願monkey能夠修改scott.emp的表數據,怎樣操做? grant update on emp to monkey; 3). 但願monkey能夠刪除scott.emp的表數據,怎樣操做? grant delete on emp to monkey; 4). 有沒有更加簡單的方法,一次把全部權限賦給monkey? grant all on emp to monkey; 2.可否對monkey訪問權限更加精細控制。(授予列權限) 1). 但願monkey只能夠修改scott.emp的表的sal字段,怎樣操做? grant update on emp(sal) to monkey 2).但願monkey只能夠查詢scott.emp的表的ename,sal數據,怎樣操做? grant select on emp(ename,sal) to monkey ... 3.授予alter權限 若是black用戶要修改scott.emp表的結構,則必須授予alter對象權限 SQL&gt; conn scott/tiger SQL&gt; grant alter on emp to blake; 固然也能夠用system,sys來完成這件事。 4.授予execute權限 若是用戶想要執行其它方案的包/過程/函數,則須有execute權限。 好比爲了讓ken能夠執行包dbms_transaction,能夠授予execute權限。 SQL&gt; conn system/manager SQL&gt; grant execute on dbms_transaction to ken; 5.授予index權限 若是想在別的方案的表上創建索引,則必須具備index對象權限。 若是爲了讓black能夠在scott.emp表上創建索引,就給其index的對象權限 SQL&gt; conn scott/tiger SQL&gt; grant index on scott.emp to blake; 6.使用with grant option選項 該選項用於轉授對象權限。可是該選項只能被授予用戶,而不能授予角色 SQL&gt; conn scott/tiger; SQL&gt; grant select on emp to blake with grant option; SQL&gt; conn black/shunping SQL&gt; grant select on scott.emp to jones; ? 回收對象權限 在oracle9i中,收回對象的權限能夠由對象的全部者來完成,也能夠用dba用戶(sys,system)來完成。 這裏要說明的是:收回對象權限後,用戶就不能執行相應的sql命令,可是要注意的是對象的權限是否會被級聯收回?【級
Oracle 筆記
34
聯回收】 如:scott-------------&gt;blake--------------&gt;jones select on emp select on emp select on emp SQL&gt; conn scott/tiger@accp SQL&gt; revoke select on emp from blake 請你們思考,jones可否查詢scott.emp表數據。 答案:查不了了(和系統權限不同,恰好相反)
15.角色
? 介紹 角色就是相關權限的命令集合,使用角色的主要目的就是爲了簡化權限的管理,假定有用戶a,b,c爲了讓他們都擁有權限 1. 鏈接數據庫 2. 在scott.emp表上select,insert,update。 若是採用直接受權操做,則須要進行12次受權。 由於要進行12次受權操做,因此比較麻煩喔!怎麼辦? 若是咱們採用角色就能夠簡化: 首先將creat session,select on scott.emp,insert on scott.emp, update on scott.emp授予角色,而後將該角色授予a,b,c用戶,這樣就能夠三次受權搞定。 角色分爲預約義和自定義角色兩類: ? 預約義角色 預約義角色是指oracle所提供的角色,每種角色都用於執行一些特定的管理任務,下面咱們介紹經常使用的預約義角色connect,resource,dba 1.connect角色 connect角色具備通常應用開發人員須要的大部分權限,當創建了一個用戶後,多數狀況下,只要給用戶授予connect和resource角色就夠了,那麼connect角色具備哪些系統權限呢? alter session create cluster create database link create session create table create view create sequence 2.resource角色 resource角色具備應用開發人員所須要的其它權限,好比創建存儲過程,觸發器等。這裏須要注意的是resource角色隱含了unlimited tablespace系統權限。 resource角色包含如下系統權限: create cluster create indextype create table create sequence create type create procedure create trigger 3.dba角色
Oracle 筆記
35
dba角色具備全部的系統權限,及with admin option選項,默認的dba用戶爲sys和system,它們能夠將任何系統權限授予其餘用戶。可是要注意的是dba角色不具有sysdba和sysoper的特權(啓動和關閉數據庫)。 ? 自定義角色 顧名思義就是本身定義的角色,根據本身的須要來定義。通常是dba來創建,若是用別的用戶來創建,則須要具備create role的系統權限。在創建角色時能夠指定驗證方式(不驗證,數據庫驗證等)。 1.創建角色(不驗證) 若是角色是公用的角色,能夠採用不驗證的方式創建角色。 create role 角色名 not identified; 2.創建角色(數據庫驗證) 採用這樣的方式時,角色名、口令存放在數據庫中。當激活該角色時,必須提供口令。在創建這種角色時,須要爲其提供口令。 create role 角色名 identified by 密碼; 角色受權 當創建角色時,角色沒有任何權限,爲了使得角色完成特定任務,必須爲其授予相應的系統權限和對象權限。 1.給角色受權 給角色授予權限和給用戶受權沒有太多區別,可是要注意,系統權限的unlimited tablespace和對象權限的with grant option選項是不能授予角色的。 SQL&gt; conn system/manager; SQL&gt; grant create session to 角色名 with admin option SQL&gt; conn scott/tiger@myoral; SQL&gt; grant select on scott.emp to 角色名; SQL&gt; grant insert, update, delete on scott.emp to 角色名; 經過上面的步驟,就給角色受權了。 2.分配角色給某個用戶 通常分配角色是由dba來完成的,若是要以其它用戶身份分配角色,則要求用戶必須具備grant any role的系統權限。 SQL&gt; conn system/manager; SQL&gt; grant 角色名 to blake with admin option; 由於我給了with admin option選項,因此,blake能夠把system分配給它的角色分配給別的用戶。 ? 刪除角色 使用drop role,通常是dba來執行,若是其它用戶則要求該用戶具備drop any role系統權限。 SQL&gt; conn system/manager; SQL&gt; drop role 角色名; 問題:若是角色被刪除,那麼被授予角色的用戶是否還具備以前角色裏的權限? 答案:不具備了 ? 顯示角色信息 1.顯示全部角色 SQL&gt; select * from dba_roles; 2.顯示角色具備的系統權限 SQL&gt; select privilege, admin_option from role_sys_privs where role='角色名'; 3.顯示角色具備的對象權限 經過查詢數據字典視圖dba_tab_privs能夠查看角色具備的對象權限或是列的權限。 4.顯示用戶具備的角色,及默認角色 當以用戶的身份鏈接到數據庫時,oracle會自動的激活默認的角色,經過查詢數據字典視圖dba_role_privs能夠顯示某個用戶具備的全部角色及當前默認的角色
Oracle 筆記
36
SQL&gt; select granted_role, default_role from dba_role_privs where grantee = ‘用戶名’; ? 精細訪問控制 精細訪問控制是指用戶能夠使用函數,策略實現更加細微的安全訪問控制。若是使用精細訪問控制,則當在客戶端發出sql語句(select,insert,update,delete)時,oracle會自動在sql語句後追加謂詞(where子句),並執行新的sql語句,經過這樣的控制,能夠使得不一樣的數據庫用戶在訪問相同表時,返回不一樣的數據信息,如: 用戶 scott blake jones 策略 emp_access 數據庫表 emp 如上圖所示,經過策略emp_access,用戶scott,black,jones在執行相同的sql語句時,能夠返回不一樣的結果。例如:當執行select ename from emp; 時,根據實際狀況能夠返回不一樣的結果。
16.PL/SQL 塊的結構和實例 韓順平.玩轉oralce第24講.plsql編程(1) 玩轉orcle實戰教程(第六天) 內容介紹 1.上節回顧 2.pl/sql的介紹 √ 3.pl/sql的基礎 √ 指望目標 1.理解oracle的pl/sql概念 2.掌握pl/sql編程技術(包括編寫過程、函數、觸發器...) pl/sql的介紹 pl/sql是什麼 pl/sql(procedural language/sql)是oracle在標準的sql語言上的擴展。pl/sql不只容許嵌入sql語言,還能夠定義變量和常量,容許使用條件語句和循環語句,容許使用例外處理各類錯誤,這樣使得它的功能變得更增強大。 爲何學pl/sql ? 學習必要性 1.提升應用程序的運行性能 2.模塊化的設計思想【分頁的過程,訂單的過程,轉帳的過程。。】 3.減小網絡傳輸量 4.提升安全性(sql會包括表名,有時還可能有密碼,傳輸的時候會泄露。PL/SQL就不會) 爲何PL/SQL會快呢?看圖: 很差的地方: 移植性很差(換數據庫就用不了), 用什麼編寫pl/sql ? sqlplus開發工具 sqlplus是oracle公司提供的一個工具,這個由於咱們在之前介紹過的: 舉一個簡單的案例: 編寫一個存儲過程,該過程能夠向某表中添加記錄。 1.建立一個簡單的表
create table mytest(name varchar2(30),passwd varchar2(30));
2.建立過程
create or replace procedure sp_pro1 is
Oracle 筆記
37
begin--執行部分
insert into mytest values('韓順平','m1234');
end;
/ replace:表示若是有sp_pro1,就替換 如何查看錯誤信息:show error; 如何調用該過程: 1)exec 過程名(參數值1,參數值2...); 2)call 過程名(參數值1,參數值2...); ? pl/sql developer開發工具 pl/sql developer是用於開發pl/sql塊的集成開發環境(ide),它是一個獨立的產品,而不是oracle的一個附帶品。 舉一個簡單案例: 編寫一個存儲過程,該過程能夠刪除某表記錄。
create or replace procedure sp_pro2 is
begin--執行部分
delete from mytest where name='韓順平';
end; pl/sql基礎 pl/sql介紹 ? 介紹 開發人員使用pl/sql編寫應用模塊時,不只須要掌握sql語句的編寫方法,還要掌握pl/sql語句及語法規則。pl/sql編程能夠使用變量和邏輯控制語句,從而能夠編寫很是有用的功能模塊。好比:分頁存儲過程模塊、訂單處理存儲過程模塊、轉帳存儲過程模塊。並且若是使用pl/sql編程,咱們能夠輕鬆地完成很是複雜的查詢要求。 pl/sql能夠作什麼 ? 簡單分類 |————過程(存儲過程) | |————函數 塊(編程)—————| |————觸發器 | |————包 編寫規範 ? 編寫規範 1.註釋 單行註釋 --
select * from emp where empno=7788; --取得員工信息 多行註釋 /*...*/來劃分 2.標誌符號的命名規範 1).當定義變量時,建議用v_做爲前綴v_sal 2).當定義常量時,建議用c_做爲前綴c_rate 3).當定義遊標時,建議用_cursor做爲後綴emp_cursor 4).當定義例外時,建議用e_做爲前綴e_error pl/sql塊介紹 ? 介紹
Oracle 筆記
38
塊(block)是pl/sql的基本程序單元,編寫pl/sql程序實際上就是編寫pl/sql塊,要完成相對簡單的應用功能,可能只須要編寫一個pl/sql塊,可是若是想要實現複雜的功能,可能須要在一個pl/sql塊中嵌套其它的pl/sql塊。 ? 塊結構示意圖 pl/sql塊由三個部分構成:定義部分,執行部分,例外處理部分。 以下所示: declare /*定義部分——定義常量、變量、遊標、例外、複雜數據類型*/ begin /*執行部分——要執行的pl/sql語句和sql語句*/ exception /*例外處理部分——處理運行的各類錯誤*/ end; 定義部分是從declare開始的,該部分是可選的; 執行部分是從begin開始的,該部分是必須的; 例外處理部分是從exception開始的,該部分是可選的。 能夠和java編程結構作一個簡單的比較。 pl/sql塊的實例(1) ? 實例1-只包括執行部分的pl/sql塊
set serveroutput on --打開輸出選項
begin
dbms_output.put_line('hello');
end;
相關說明: dbms_output是oracle所提供的包(相似java的開發包),該包包含一些過程,put_line就是dbms_output包的一個過程。 pl/sql塊的實例(2) ? 實例2-包含定義部分和執行部分的pl/sql塊
declare
v_ename varchar2(5); --定義字符串變量
begin
select ename into v_ename from emp where empno=&amp;aa;
dbms_output.put_line('僱員名:'||v_ename);
end;
/ 若是要把薪水也顯示出來,那麼執行部分就應該這麼寫:
select ename,sal into v_ename,v_sal from emp where empno=&amp;aa;
相關說明: &amp; 表示要接收從控制檯輸入的變量。 pl/sql塊的實例(3) ? 實例3-包含定義部分,執行部分和例外處理部分 爲了不pl/sql程序的運行錯誤,提升pl/sql的健壯性,應該對可能的錯誤進行處理,這個頗有必要。 1.好比在實例2中,若是輸入了不存在的僱員號,應當作例外處理。 2.有時出現異常,但願用另外的邏輯處理,[網示] 咱們看看如何完成1的要求。 相關說明: oracle事先預約義了一些例外,no_data_found就是找不到數據的例外。
Oracle 筆記
39
declare
--定義變量
v_ename varchar2(5);
v_sal number(7,2);
begin
--執行部分
select ename,sal into v_ename,v_sal from emp where empno=&amp;aa;
--在控制檯顯示用戶名
dbms_output.put_line('用戶名是:'||v_ename||' 工資:'||v_sal);
--異常處理
exception
when no_data_found then
dbms_output.put_line('朋友,你的編號輸入有誤!');
end;
/
17.pl/sql分類 -- 過程,函數,包,觸發器
? 過程 過程用於執行特定的操做,當創建過程時,既能夠指定輸入參數(in),也能夠指定輸出參數(out), 經過在過程當中使用輸入參數,能夠將數據傳遞到執行部分;經過使用輸出參數,能夠將執行部分的數據傳遞到應用環境。在sqlplus中能夠使用create procedure命令來創建過程。 實例以下: 1.請考慮編寫一個過程,能夠輸入僱員名,新工資,可修改僱員的工資 2.如何調用過程有兩種方法; exec call 3.如何在java程序中調用一個存儲過程 問題:如何使用過程返回值? 特別說明: 對於過程咱們會在之後給你們詳細具體的介紹,如今請你們先有一個概念。 create procedure sp_pro3(spName varchar2, newSal number) is --不要寫成number(3,2),代表類型就能夠了,不須要大小。就好像Java寫方法時的參數同樣
begin
--執行部分,根據用戶名去修改工資
update emp set sal=newSal where ename=spName;
end;
/ java程序中調用一個存儲過程 //演示java程序去調用oracle的存儲過程案例
import java.sql.*;
public class TestOraclePro{
public static void main(String[] args){
try{
//1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.獲得鏈接
Oracle 筆記
40
Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");
//3.建立CallableStatement
CallableStatement cs = ct.prepareCall("{call sp_pro3(?,?)}");
//4.給?賦值
cs.setString(1,"SMITH");
cs.setInt(2,10);
//5.執行
cs.execute();
//關閉
cs.close();
ct.close();
} catch(Exception e){
e.printStackTrace();
}
}
} ? 函數 函數用於返回特定的數據,當創建函數時,在函數頭部必須包含return子句。而在函數體內必須包含return語句返回的數據。咱們能夠使用create function來創建函數,實際案例:
--輸入僱員的姓名,返回該僱員的年薪
create function annual_incomec(name varchar2)
return number is
annual_salazy number(7,2);
begin
--執行部分
select sal*12+nvl(comm, 0) into annual_salazy from emp where ename=name;
return annual_salazy;
end;
/
若是函數建立過程有編譯錯誤,能夠使用show error;命令顯示錯誤 在sqlplus中調用函數
SQL&gt; var income number
SQL&gt; call annual_incomec('scott') into: income;
SQL&gt; print income 一樣咱們能夠在java程序中調用該函數 select annual_income('SCOTT') from dual; 這樣能夠經過rs.getInt(l)獲得返回的結果。 ? 包 包用於在邏輯上組合過程和函數,它由包規範和包體兩部分組成。 1.咱們能夠使用create package命令來建立包。 實例: --建立一個包sp_package --聲明該包有一個過程update_sal --聲明該包有一個函數annual_income
Oracle 筆記
41
create package sp_package is
procedure update_sal(name varchar2, newsal number);
function annual_income(name varchar2) return number;
end; 包的規範只包含了過程和函數的說明,可是沒有過程和函數的實現代碼。包體用於實現包規範中的過程和函數。 2.創建包體能夠使用create package body命令 --給包sp_package實現包體
create or replace package body sp_package is
procedure update_sal(name varchar2, newsal number)
is
begin
update emp set sal = newsal where ename = name;
end;
function annual_income(name varchar2) return number is
annual_salary number;
begin
select sal * 12 + nvl(comm, 0) into annual_salary from emp
where ename = name;
return annual_salary;
end;
end;
/ 3.如何調用包的過程或是函數 當調用包的過程或是函數時,在過程和函數前須要帶有包名,若是要訪問其它方案的包,還須要在包名前加方案名。 如: SQL&gt; call sp_package.update_sal('SCOTT', 1500); 特別說明: 包是pl/sql中很是重要的部分,咱們在使用過程分頁時,將會再次體驗它的威力呵呵。 ? 觸發器 觸發器是指隱含的執行的存儲過程。當定義觸發器時,必需要指定觸發的事件和觸發的操做,經常使用的觸發事件包括insert,update,delete語句,而觸發操做實際就是一個pl/sql塊。能夠使用create trigger來創建觸發器。 特別說明: 咱們會在後面詳細爲你們介紹觸發器的使用,由於觸發器是很是有用的,可維護數據庫的安全和一致性。
18.定義並使用變量,複合類型 定義並使用變量 ? 介紹 在編寫pl/sql程序時,能夠定義變量和常量;在pl/sql程序中包括有: 1.標量類型(scalar) 2.複合類型(composite) 3.參照類型(reference) 4.lob(large object) ? 標量(scalar)——經常使用類型 在編寫pl/sql塊時,若是要使用變量,需在定義部分定義變量。pl/sql中定義變量和常量的語法以下: identifier [constant] datatype [not null] [:=| default expr]
Oracle 筆記
42
identifier : 名稱 constant :指定常量。須要指定它的初始值,且其值是不能改變的 datatype :數據類型 not null :指定變量值不能爲null := 給變量或是常量指定初始值 default 用於指定初始值 expr :指定初始值的pl/sql表達式,能夠是文本值、其它變量、函數等。 ? 標量定義的案例 1.定義一個變長字符串 v_ename varchar2(10); 2.定義一個小數,範圍 -9999.99~9999.99 v_sal number(6,2); 3.定義一個小數並給一個初始值爲5.4 :=是pl/sql的賦值號 v_sal2 number(6,2):=5.4; 4.定義一個日期類型的數據 v_hiredate date; 5.定義一個布爾變量,不能爲空,初始值爲false v_valid boolean not null default false; ? 標量(scalar)——使用標量 在定義好變量後,就能夠使用這些變量。這裏須要說明的是pl/sql塊爲變量賦值不一樣於其它的編程語言,須要在等號前面加冒號(:=) 下面以輸入員工號,顯示僱員姓名、工資、我的所得稅(稅率爲0.03)爲例。說明變量的使用,看看如何編寫。
declare
c_tax_rate number(3,2):=0.03;
--用戶名
v_ename varchar2(5);
v_sal number(7,2);
v_tax_sal number(7,2);
begin
--執行
select ename,sal into v_ename,v_sal from emp where empno=&amp;no;
--計算所得稅
v_tax_sal := v_sal*c_tax_rate;
--輸出
dbms_output.put_line('姓名是:'||v_ename||'工資:'||v_sal||' 交稅:'||v_tax_sal);
end;
/ ? 標量(scalar)——使用%type類型 對於上面的pl/sql塊有一個問題: 就是若是員工的姓名超過了5個字符的話,就會有錯誤,爲了下降pl/sql程序的維護工做量,能夠使用%type屬性定義變量,這樣它會按照數據庫列來肯定你定義的變量的類型和長度。 咱們看看這個怎麼使用: 標識符名 表名.列名%type; 好比上例的v_ename,這樣定義: v_ename emp.ename%type;
Oracle 筆記
43
? 複合變量(composite)——介紹 用於存放多個值的變量。主要包括這幾種: 1.pl/sql記錄 2.pl/sql表 3.嵌套表 4.varray ? 複合類型——pl/sql記錄 相似於高級語言中的結構體,須要注意的是,當引用pl/sql記錄成員時,必需要加記錄變量做爲前綴(記錄變量.記錄成員)以下:
declare
--定義一個pl/sql記錄類型emp_record_type,類型包含3個數據name,salary,title。說白了,就是一個類型能夠存放3個數據,主要是爲了好管理
type emp_record_type is record(
name emp.ename%type,
salary emp.sal%type,
title emp.job%type);
--定義了一個sp_record變量,這個變量的類型是emp_record_type
sp_record emp_record_type;
begin
select ename, sal, job into sp_record from emp where empno = 7788;
dbms_output.put_line ('員工名:' || sp_record.name);
end; ? 複合類型-pl/sql表 至關於高級語言中的數組,可是須要注意的是在高級語言中數組的下標不能爲負數,而pl/sql是能夠爲負數的,而且表元素的下標沒有限制。實例以下:
declare
--定義了一個pl/sql表類型sp_table_type,該類型是用於存放emp.ename%type
--index by binary_integer 表示下標是整數
type sp_table_type is table of emp.ename%type
index by binary_integer;
--定義了一個sp_table變量,這個變量的類型是sp_table_type
sp_table sp_table_type;
begin
select ename into sp_table(-1) from emp where empno = 7788;
dbms_output.put_line('員工名:' || sp_table(-1));
end;
說明: sp_table_type 是pl/sql表類型 emp.ename%type 指定了表的元素的類型和長度 sp_table 爲pl/sql表變量 sp_table(0) 則表示下標爲0的元素 注意:若是把select ename into sp_table(-1) from emp where empno = 7788;變成select ename into sp_table(-1) from emp;則運行時會出現錯誤,錯誤以下: ORA-01422:實際返回的行數超出請求的行數 解決方法是:使用參照變量(這裏不講)
Oracle 筆記
44
? 複合變量——嵌套表(nested table) ? 複合變量——變長數組(varray) ? 參照變量——介紹 參照變量是指用於存放數值指針的變量。經過使用參照變量,能夠使得應用程序共享相同對象,從而下降佔用的空間。在編寫pl/sql程序時,能夠使用遊標變量(ref cursor)和對象類型變量(ref obj_type)兩種參照變量類型。 ? 參照變量——ref cursor遊標變量 使用遊標時,當定義遊標時不須要指定相應的select語句,可是當使用遊標時(open時)須要指定select語句,這樣一個遊標就與一個select語句結合了。實例以下: 1.請使用pl/sql編寫一個塊,能夠輸入部門號,並顯示該部門全部員工姓名和他的工資。 2.在1的基礎上,若是某個員工的工資低於200元,就添加100元。 1.
declare
--定義遊標sp_emp_cursor
type sp_emp_cursor is ref cursor;
--定義一個遊標變量
test_cursor sp_emp_cursor;
--定義變量
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
--執行
--把test_cursor和一個select結合
open test_cursor for select ename,sal from emp where deptno=&amp;no;
--循環取出
loop
fetch test_cursor into v_ename,v_sal;
--判斷是否test_cursor爲空
exit when test_cursor%notfound;
dbms_output.put_line('名字:'||v_ename||' 工資:'||v_sal);
end loop;
end;
/
19.pl/sql的進階--控制結構(分支,循環,控制)
玩轉oracle實戰教程(第七天) 內容介紹 1.上節回顧 2.pl/sql的進階 √ 3.oracle的視圖(具備安全性,和簡化複雜查詢的功能) √ 4.oracle的觸發器 √ 指望目標 1.掌握pl/sql的高級用法(能縮寫分頁過程模塊,下訂單過程模塊...) 2.會處理oracle常見的例外 3.會編寫oracle各類觸發器
Oracle 筆記
45
4.理解視圖的概念並能靈活使用視圖 pl/sql的進階--控制結構 ? 介紹 在任何計算機語言(c,java,pascal)都有各類控制語句(條件語句,循環結構,順序控制結構...)在pl/sql中也存在這樣的控制結構。 在本部分學習完成後,但願你們達到: 1.使用各類if語句 2.使用循環語句 3.使用控制語句——goto和null; ? 條件分支語句 pl/sql中提供了三種條件分支語句if—then,if – then – else,if – then – elsif – then 這裏咱們能夠和java語句進行一個比較 ? 簡單的條件判斷 if – then 問題:編寫一個過程,能夠輸入一個僱員名,若是該僱員的工資低於2000,就給該員工工資增長10%。
create or replace procedure sp_pro6(spName varchar2) is
--定義
v_sal emp.sal%type;
begin
--執行
select sal into v_sal from emp where ename=spName;
--判斷
if v_sal&lt;2000 then
update emp set sal=sal+sal*10% where ename=spName;
end if;
end;
/ ? 二重條件分支 if – then – else 問題:編寫一個過程,能夠輸入一個僱員名,若是該僱員的補助不是0就在原來的基礎上增長100;若是補助爲0就把補助設爲200;
create or replace procedure sp_pro6(spName varchar2) is
--定義
v_comm emp.comm%type;
begin
--執行
select comm into v_comm from emp where ename=spName;
--判斷
if v_comm&lt;&gt;0 then
update emp set comm=comm+100 where ename=spName;
else
update emp set comm=comm+200 where ename=spName;
end if;
end;
/ ? 多重條件分支 if – then – elsif – then
Oracle 筆記
46
問題:編寫一個過程,能夠輸入一個僱員編號,若是該僱員的職位是PRESIDENT就給他的工資增長1000,若是該僱員的職位是MANAGER就給他的工資增長500,其它職位的僱員工資增長200。
create or replace procedure sp_pro6(spNo number) is
--定義
v_job emp.job%type;
begin
--執行
select job into v_job from emp where empno=spNo;
if v_job='PRESIDENT' then
update emp set sal=sal+1000 where empno=spNo;
elsif v_job='MANAGER' then
update emp set sal=sal+500 where empno=spNo;
else
update emp set sal=sal+200 where empno=spNo;
end if;
end;
/ ? 循環語句 –loop 是pl/sql中最簡單的循環語句,這種循環語句以loop開頭,以end loop結尾,這種循環至少會被執行一次。 案例:現有一張表users,表結構以下: 用戶id | 用戶名 | 請編寫一個過程,能夠輸入用戶名,並循環添加10個用戶到users表中,用戶編號從1開始增長。
create or replace procedure sp_pro6(spName varchar2) is
--定義 :=表示賦值
v_num number:=1;
begin
loop
insert into users values(v_num,spName);
--判斷是否要退出循環
exit when v_num=10;
--自增
v_num:=v_num+1;
end loop;
end;
/ ? 環語句 –while循環 基本循環至少要執行循環體一次,而對於while循環來講,只有條件爲true時,纔會執行循環體語句,while循環以while...loop開始,以end loop結束。 案例:現有一張表users,表結構以下: 用戶id 用戶名 問題:請編寫一個過程,能夠輸入用戶名,並循環添加10個用戶到users表中,用戶編號從11開始增長。
create or replace procedure sp_pro6(spName varchar2) is
--定義 :=表示賦值
v_num number:=11;
Oracle 筆記
47
begin
while v_num&lt;=20 loop
--執行
insert into users values(v_num,spName);
v_num:=v_num+1;
end loop;
end;
/ ? 循環語句 –for循環 基本for循環的基本結構以下
begin
for i in reverse 1..10 loop
insert into users values (i, 'shunping');
end loop;
end;
咱們能夠看到控制變量i,在隱含中就在不停地增長。 ? 順序控制語句 –goto,null 1.goto語句 goto語句用於跳轉到特定符號去執行語句。注意因爲使用goto語句會增長程序的複雜性,並使得應用程序可讀性變差,因此在作通常應用開發時,建議你們不要使用goto語句。 基本語法以下 goto lable,其中lable是已經定義好的標號名,
declare
i int := 1;
begin
loop
dbms_output.put_line('輸出i=' || i);
if i = 1{} then
goto end_loop;
end if;
i := i + 1;
end loop;
&lt;&lt;end_loop&gt;&gt;
dbms_output.put_line('循環結束');
end; 2.null null語句不會執行任何操做,而且會直接將控制傳遞到下一條語句。使用null語句的主要好處是能夠提升pl/sql的可讀性。
declare
v_sal emp.sal%type;
v_ename emp.ename%type;
begin
select ename, sal into v_ename, v_sal from emp where empno = &amp;no;
if v_sal &lt; 3000 then
update emp set comm = sal * 0.1 where ename = v_ename;
else
null;
Oracle 筆記
48
end if;
end;
20.PL/SQL分頁 編寫分頁過程 ? 介紹 分頁是任何一個網站(bbs,網上商城,blog)都會使用到的技術,所以學習pl/sql編程開發就必定要掌握該技術。看圖: ? 無返回值的存儲過程 古人云:欲速則不達,爲了讓你們夥比較容易接受分頁過程編寫,我仍是從簡單到複雜,按部就班的給你們講解。首先是掌握最簡單的存儲過程,無返回值的存儲過程: 案例:現有一張表book,表結構以下:看圖: 書號 書名 出版社 請寫一個過程,能夠向book表添加書,要求經過java程序調用該過程。 --in:表示這是一個輸入參數,默認爲in --out:表示一個輸出參數
create or replace procedure sp_pro7(spBookId in number,spbookName in varchar2,sppublishHouse in varchar2) is
begin
insert into book values(spBookId,spbookName,sppublishHouse);
end;
/ --在java中調用
//調用一個無返回值的過程
import java.sql.*;
public class Test2{
public static void main(String[] args){
try{
	//1.加載驅動
	Class.forName("oracle.jdbc.driver.OracleDriver");
	//2.獲得鏈接
	Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");
	//3.建立CallableStatement
	CallableStatement cs = ct.prepareCall("{call sp_pro7(?,?,?)}");
	//4.給?賦值
	cs.setInt(1,10);
	cs.setString(2,"笑傲江湖");
	cs.setString(3,"人民出版社");
	//5.執行
	cs.execute();
	} catch(Exception e){
		e.printStackTrace();
	} finally{
	//6.關閉各個打開的資源
	cs.close
	//Oracle 筆記
	ct.close();
	}
	}
}
執行,記錄被加進去了 ? 有返回值的存儲過程(非列表) 再看如何處理有返回值的存儲過程: 案例:編寫一個過程,能夠輸入僱員的編號,返回該僱員的姓名。 案例擴張:編寫一個過程,能夠輸入僱員的編號,返回該僱員的姓名、工資和崗位。
--有輸入和輸出的存儲過程
create or replace procedure sp_pro8
(spno in number, spName out varchar2) is
begin
select ename into spName from emp where empno=spno;
end;
/
import java.sql.*;
public class Test2{
public static void main(String[] args){
try{
//1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.獲得鏈接
Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");
//3.建立CallableStatement
/*CallableStatement cs = ct.prepareCall("{call sp_pro7(?,?,?)}");
//4.給?賦值
cs.setInt(1,10);
cs.setString(2,"笑傲江湖");
cs.setString(3,"人民出版社");*/
//看看如何調用有返回值的過程
//建立CallableStatement
/*CallableStatement cs = ct.prepareCall("{call sp_pro8(?,?)}");
//給第一個?賦值
cs.setInt(1,7788);
//給第二個?賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);
//5.執行
cs.execute();
//取出返回值,要注意?的順序
String name=cs.getString(2);
System.out.println("7788的名字"+name);
} catch(Exception e){
e.printStackTrace();
Oracle 筆記
50
} finally{
//6.關閉各個打開的資源
cs.close();
ct.close();
}
}
}
運行,成功得出結果。。 案例擴張:編寫一個過程,能夠輸入僱員的編號,返回該僱員的姓名、工資和崗位。
--有輸入和輸出的存儲過程
create or replace procedure sp_pro8
(spno in number, spName out varchar2,spSal out number,spJob out varchar2) is
begin
select ename,sal,job into spName,spSal,spJob from emp where empno=spno;
end;
/
import java.sql.*;
public class Test2{
public static void main(String[] args){
try{
//1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.獲得鏈接
Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");
//3.建立CallableStatement
/*CallableStatement cs = ct.prepareCall("{call sp_pro7(?,?,?)}");
//4.給?賦值
cs.setInt(1,10);
cs.setString(2,"笑傲江湖");
cs.setString(3,"人民出版社");*/
//看看如何調用有返回值的過程
//建立CallableStatement
/*CallableStatement cs = ct.prepareCall("{call sp_pro8(?,?,?,?)}");
//給第一個?賦值
cs.setInt(1,7788);
//給第二個?賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);
//給第三個?賦值
cs.registerOutParameter(3,oracle.jdbc.OracleTypes.DOUBLE);
//給第四個?賦值
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);
//5.執行
cs.execute();
//取出返回值,要注意?的順序
Oracle 筆記
51
String name=cs.getString(2);
String job=cs.getString(4);
System.out.println("7788的名字"+name+" 工做:"+job);
} catch(Exception e){
e.printStackTrace();
} finally{
//6.關閉各個打開的資源
cs.close();
ct.close();
}
}
}
運行,成功找出記錄 ? 有返回值的存儲過程(列表[結果集]) 案例:編寫一個過程,輸入部門號,返回該部門全部僱員信息。 對該題分析以下: 因爲oracle存儲過程沒有返回值,它的全部返回值都是經過out參數來替代的,列表一樣也不例外,但因爲是集合,因此不能用通常的參數,必需要用pagkage了。因此要分兩部分: 返回結果集的過程 1.創建一個包,在該包中,我定義類型test_cursor,是個遊標。 以下:
create or replace package testpackage as
TYPE test_cursor is ref cursor;
end testpackage; 2.創建存儲過程。以下:
create or replace procedure sp_pro9(spNo in number,p_cursor out testpackage.test_cursor) is
begin
open p_cursor for
select * from emp where deptno = spNo;
end sp_pro9; 3.如何在java程序中調用該過程
import java.sql.*;
public class Test2{
public static void main(String[] args){
try{
//1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.獲得鏈接
Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");
//看看如何調用有返回值的過程
//3.建立CallableStatement
/*CallableStatement cs = ct.prepareCall("{call sp_pro9(?,?)}");
//4.給第?賦值
cs.setInt(1,10);
//給第二個?賦值
Oracle 筆記
52
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);
//5.執行
cs.execute();
//獲得結果集
ResultSet rs=(ResultSet)cs.getObject(2);
while(rs.next()){
System.out.println(rs.getInt(1)+" "+rs.getString(2));
}
} catch(Exception e){
e.printStackTrace();
} finally{
//6.關閉各個打開的資源
cs.close();
ct.close();
}
}
}
運行,成功得出部門號是10的全部用戶 ? 編寫分頁過程 有了上面的基礎,相信你們能夠完成分頁存儲過程了。 要求,請你們編寫一個存儲過程,要求能夠輸入表名、每頁顯示記錄數、當前頁。返回總記錄數,總頁數,和返回的結果集。 若是你們忘了oracle中如何分頁,請參考第三天的內容。 先本身完成,老師在後面給出答案,並講解。 --oracle的分頁
select t1.*, rownum rn from (select * from emp) t1 where rownum&lt;=10;
--在分頁時,你們能夠把下面的sql語句當作一個模板使用
select * from
(select t1.*, rownum rn from (select * from emp) t1 where rownum&lt;=10)
where rn&gt;=6; --開發一個包 --創建一個包,在該包中,我定義類型test_cursor,是個遊標。 以下:
create or replace package testpackage as
TYPE test_cursor is ref cursor;
end testpackage;
--開始編寫分頁的過程
create or replace procedure fenye
(tableName in varchar2,
Pagesize in number,--一頁顯示記錄數
pageNow in number,
myrows out number,--總記錄數
myPageCount out number,--總頁數
p_cursor out testpackage.test_cursor--返回的記錄集
) is
--定義部分
--定義sql語句 字符串
Oracle 筆記
53
v_sql varchar2(1000);
--定義兩個整數
v_begin number:=(pageNow-1)*Pagesize+1;
v_end number:=pageNow*Pagesize;
begin
--執行部分
v_sql:='select * from (select t1.*, rownum rn from (select * from '||tableName||') t1 where rownum&lt;='||v_end||') where rn&gt;='||v_begin;
--把遊標和sql關聯
open p_cursor for v_sql;
--計算myrows和myPageCount
--組織一個sql語句
v_sql:='select count(*) from '||tableName;
--執行sql,並把返回的值,賦給myrows;
execute inmediate v_sql into myrows;
--計算myPageCount
--if myrows%Pagesize=0 then這樣寫是錯的
if mod(myrows,Pagesize)=0 then
myPageCount:=myrows/Pagesize;
else
myPageCount:=myrows/Pagesize+1
end if;
--關閉遊標
close p_cursor;
end;
/ --使用java測試 //測試分頁
import java.sql.*;
public class FenYe{
public static void main(String[] args){
try{
//1.加載驅動
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.獲得鏈接
Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");
//3.建立CallableStatement
CallableStatement cs = ct.prepareCall("{call fenye(?,?,?,?,?,?)}");
//4.給第?賦值
cs.seString(1,"emp");
cs.setInt(2,5);
cs.setInt(3,2);
//註冊總記錄數
Oracle 筆記
54
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);
//註冊總頁數
cs.registerOutParameter(5,oracle.jdbc.OracleTypes.INTEGER);
//註冊返回的結果集
cs.registerOutParameter(6,oracle.jdbc.OracleTypes.CURSOR);
//5.執行
cs.execute();
//取出總記錄數 /這裏要注意,getInt(4)中4,是由該參數的位置決定的
int rowNum=cs.getInt(4);
int pageCount = cs.getInt(5);
ResultSet rs=(ResultSet)cs.getObject(6);
//顯示一下,看看對不對
System.out.println("rowNum="+rowNum);
System.out.println("總頁數="+pageCount);
while(rs.next()){
System.out.println("編號:"+rs.getInt(1)+" 名字:"+rs.getString(2)+" 工資:"+rs.getFloat(6));
}
} catch(Exception e){
e.printStackTrace();
} finally{
//6.關閉各個打開的資源
cs.close();
ct.close();
}
}
}
運行,控制檯輸出: rowNum=19 總頁數:4 編號:7369 名字:SMITH 工資:2850.0 編號:7499 名字:ALLEN 工資:2450.0 編號:7521 名字:WARD 工資:1562.0 編號:7566 名字:JONES 工資:7200.0 編號:7654 名字:MARTIN 工資:1500.0 --新的須要,要求按照薪水從低到高排序,而後取出6-10 過程的執行部分作下改動,以下:
begin
--執行部分
v_sql:='select * from (select t1.*, rownum rn from (select * from '||tableName||' order by sal) t1 where rownum&lt;='||v_end||') where rn&gt;='||v_begin; 從新執行一次procedure,java不用改變,運行,控制檯輸出: rowNum=19 總頁數:4 編號:7900 名字:JAMES 工資:950.0 編號:7876 名字:ADAMS 工資:1100.0
Oracle 筆記
55
編號:7521 名字:WARD 工資:1250.0 編號:7654 名字:MARTIN 工資:1250.0 編號:7934 名字:MILLER 工資:1300.0
21.例外處理 例外處理 ? 例外的分類 oracle將例外分爲預約義例外,非預約義例外和自定義例外三種。 預約義例外用於處理常見的oracle錯誤 非預約義例外用於處理預約義例外不能處理的例外 自定義例外用於處理與oracle錯誤無關的其它狀況 ? 例外傳遞 若是不處理例外咱們看看會出現什麼狀況: 案例,編寫一個過程,可接收僱員的編號,並顯示該僱員的姓名。 問題是,若是輸入的僱員編號不存在,怎樣去處理呢?
--例外案例
declare
--定義
v_ename emp.ename%type;
begin
--
select ename into v_ename from emp where empno=&amp;gno;
dbms_output.put_line('名字:'||v_ename)
/ 執行,彈出框,看圖: 隨便輸個不在的編號,回車,會拋出異常,顯示: ORA-01403: 未找到數據 ORA-06512: 在line 6
declare
--定義
v_ename emp.ename%type;
begin
--
select ename into v_ename from emp where empno=&amp;gno;
dbms_output.put_line('名字:'||v_ename)
exception
when no_data_found then
dbms_output.put_line('編號沒有!');
/
執行,輸入一個不存在的編號,回車,顯示: 編號沒有! ? 處理預約義例外 預約義例外是由pl/sql所提供的系統例外。當pl/sql應用程序違反了oracle 規定的限制時,則會隱含的觸發一個內部例外。pl/sql爲開發人員提供了二十多個預約義例外。咱們給你們介紹經常使用的例外。
Oracle 筆記
56
? 預約義例外 case_not_found 在開發pl/sql塊中編寫case語句時,若是在when子句中沒有包含必須的條件分支,就會觸發case_not_found的例外:
create or replace procedure sp_pro6(spno number) is
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno = spno;
case
when v_sal &lt; 1000 then
update emp set sal = sal + 100 where empno = spno;
when v_sal &lt; 2000 then
update emp set sal = sal + 200 where empno = spno;
end case;
exception
when case_not_found then
dbms_output.put_line('case語句沒有與' || v_sal || '相匹配的條件');
end; ? 預約義例外 cursor_already_open 當從新打開已經打開的遊標時,會隱含的觸發例外cursor_already_open
declare
cursor emp_cursor is select ename, sal from emp;
begin
open emp_cursor;
for emp_record1 in emp_cursor loop
dbms_output.put_line(emp_record1.ename);
end loop;
exception
when cursor_already_open then
dbms_output.put_line('遊標已經打開');
end;
/ ? 預約義例外 dup_val_on_index 在惟一索引所對應的列上插入重複的值時,會隱含的觸發例外dup_val_on_index例外
begin
insert into dept values (10, '公關部', '北京');
exception
when dup_val_on_index then
dbms_output.put_line('在deptno列上不能出現重複值');
end; ? 預約義例外 invalid_cursor 當試圖在不合法的遊標上執行操做時,會觸發該例外 例如:試圖從沒有打開的遊標提取數據,或是關閉沒有打開的遊標。則會觸發該例外
declare
cursor emp_cursor is select ename, sal from emp;
emp_record emp_cursor%rowtype;
begin
Oracle 筆記
57
--open emp_cursor; --打開遊標
fetch emp_cursor into emp_record;
dbms_output.put_line(emp_record.ename);
close emp_cursor;
exception
when invalid_cursor then
dbms_output.put_line('請檢測遊標是否打開');
end; ? 預約義例外 invalid_number 當輸入的數據有誤時,會觸發該例外 好比:數字100寫成了loo就會觸發該例外
begin
update emp set sal= sal + 'loo';
exception
when invalid_number then
dbms_output.put_line('輸入的數字不正確');
end; 預約義例外 no_data_found 下面是一個pl/sql塊,當執行select into 沒有返回行,就會觸發該例外
declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp
when ename='&amp;name';
exception
when no_data_found then
dbms_output.put_line('不存在該員工');
end; ? 預約義例外 too_many_rows 當執行select into語句時,若是返回超過了一行,則會觸發該例外。
declare
v_ename emp.ename%type;
begin
select ename into v_ename from emp;
exception
when too_many_rows then
dbms_output.put_line('返回了多行');
end; ? 預義例外 zero_divide 當執行2/0語句時,則會觸發該例外。 ? 預約義例外 value_error 當在執行賦值操做時,若是變量的長度不足以容納實際數據,則會觸發該例外value_error,好比:
declare
v_ename varchar2(5);
begin
Oracle 筆記
58
select ename into v_ename from emp where empno = &amp;no1;
dbms_output.put_line(v_ename);
exception
when value_error then
dbms_output.put_line('變量尺寸不足');
end; ? 其它預約義例外(這些例外不是在pl/sql裏觸發的,而是在用oracle時觸發的,因此取名叫其它預約義例外) 1.login_denied 當用戶非法登陸時,會觸發該例外 2.not_logged_on 若是用戶沒有登陸就執行dml操做,就會觸發該例外 3.storage_error 若是超過了內存空間或是內存被損壞,就觸發該例外 4.timeout_on_resource 若是oracle在等待資源時,出現了超時就觸發該例外 ? 非預約義例外 非預約義例外用於處理與預約義例外無關的oracle錯誤。使用預約義例外只能處理21個oracle錯誤,而當使用pl/sql開發應用程序時,可能會遇到其它的一些oracle錯誤。好比在pl/sql塊中執行dml語句時,違反了約束規定等等。在這樣的狀況下,也能夠處理oracle的各類例外,由於非預約義例外用的很少,這裏我就不舉例了。 ? 處理自定義例外 預約義例外和自定義例外都是與oracle錯誤相關的,而且出現的oracle錯誤會隱含的觸發相應的例外;而自定義例外與oracle錯誤沒有任何關聯,它是由開發人員爲特定狀況所定義的例外. 問題:請編寫一個pl/sql塊,接收一個僱員的編號,並給該僱員工資增長1000元,若是該僱員不存在,請提示。
--自定義例外
create or replace procedure ex_test(spNo number)
is
begin
--更新用戶sal
update emp set sal=sal+1000 where empno=spNo;
end;
/ 運行,該過程被成功建立。 SQL&gt; exec ex_test(56); PL/SQL過程被成功完成 這裏,編號爲56是不存在的,剛纔的報異常了,爲何如今不報異常呢? 由於剛纔的是select語句 怎麼解決這個問題呢? 修改代碼,以下:
--自定義例外
create or replace procedure ex_test(spNo number)
is
--定義一個例外
myex exception;
begin
--更新用戶sal
update emp set sal=sal+1000 where empno=spNo;
Oracle 筆記
59
--sql%notfound這是表示沒有update
--raise myex;觸發myex
if sql%notfound then
raise myex;
end if;
exception
when myex then
dbms_output.put_line('沒有更新任何用戶');
end;
/ 如今再測試一次: SQL&gt; exec ex_test(56); 沒有更新任何用戶
22.oracle的視圖 oracle的視圖 ? 介紹 視圖是一個虛擬表,其內容由查詢定義,同真實的表同樣,視圖包含一系列帶有名稱的列和行數據。可是,視圖並不在數據庫中以存儲的數據值集形式存在。行和列數據來自由定義視圖的查詢所引用的表,而且在引用視圖時動態生成。(視圖不是真實存在磁盤上的) 看圖: 視與表的區別 ? 視圖與表的區別 1.表須要佔用磁盤空間,視圖不須要 2.視圖不能添加索引(因此查詢速度略微慢點) 3.使用視圖能夠簡化,複雜查詢 好比:學生選課系統 4.視圖的使用利於提升安全性 好比:不一樣用戶查看不一樣視圖 建立/修改視圖 ? 建立視圖 create view 視圖名 as select 語句 [with read only] ? 建立或修改視圖 create or replace view 視圖名 as select 語句 [with read only] ? 刪除視圖 drop view 視圖名 當表結構國語複雜,請使用視圖吧! --建立視圖,把emp表的sal&lt;1000的僱員映射到該視圖(view)
create view myview as select * from emp where sal&lt;1000; --爲簡化操做,用一個視圖解決 顯示僱員編號,姓名和部門名稱
create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno; 視圖之間也能夠作聯合查詢</pre>
<p> </p>
<pre name="code" >1、基礎
一、說明:建立數據庫
CREATE DATABASE database-name 
二、說明:刪除數據庫
drop database dbname
三、說明:備份sql server
--- 建立 備份數據的 device
USE master
EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'
--- 開始 備份
BACKUP DATABASE pubs TO testBack 
四、說明:建立新表
create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
根據已有的表建立新表: 
A:create table tab_new like tab_old (使用舊錶建立新表)
B:create table tab_new as select col1,col2… from tab_old definition only
五、說明:刪除新表
drop table tabname 
六、說明:增長一個列
Alter table tabname add column col type
注:列增長後將不能刪除。DB2中列加上後數據類型也不能改變,惟一能改變的是增長varchar類型的長度。
七、說明:添加主鍵: Alter table tabname add primary key(col) 
說明:刪除主鍵: Alter table tabname drop primary key(col) 
八、說明:建立索引:create [unique] index idxname on tabname(col….) 
刪除索引:drop index idxname
注:索引是不可更改的,想更改必須刪除從新建。
九、說明:建立視圖:create view viewname as select statement 
刪除視圖:drop view viewname
十、說明:幾個簡單的基本的sql語句
選擇:select * from table1 where 範圍
插入:insert into table1(field1,field2) values(value1,value2)
刪除:delete from table1 where 範圍
更新:update table1 set field1=value1 where 範圍
查找:select * from table1 where field1 like ’%value1%’ ---like的語法很精妙,查資料!
排序:select * from table1 order by field1,field2 [desc]
總數:select count as totalcount from table1
求和:select sum(field1) as sumvalue from table1
平均:select avg(field1) as avgvalue from table1
最大:select max(field1) as maxvalue from table1
最小:select min(field1) as minvalue from table1
十一、說明:幾個高級查詢運算詞
A: UNION 運算符 
UNION 運算符經過組合其餘兩個結果表(例如 TABLE1 和 TABLE2)並消去表中任何重複行而派生出一個結果表。當 ALL 隨 UNION 一塊兒使用時(即 UNION ALL),不消除重複行。兩種狀況下,派生表的每一行不是來自 TABLE1 就是來自 TABLE2。 
B: EXCEPT 運算符 
EXCEPT 運算符經過包括全部在 TABLE1 中但不在 TABLE2 中的行並消除全部重複行而派生出一個結果表。當 ALL 隨 EXCEPT 一塊兒使用時 (EXCEPT ALL),不消除重複行。 
C: INTERSECT 運算符
INTERSECT 運算符經過只包括 TABLE1 和 TABLE2 中都有的行並消除全部重複行而派生出一個結果表。當 ALL 隨 INTERSECT 一塊兒使用時 (INTERSECT ALL),不消除重複行。 
注:使用運算詞的幾個查詢結果行必須是一致的。 
十二、說明:使用外鏈接 
A、left (outer) join: 
左外鏈接(左鏈接):結果集幾包括鏈接表的匹配行,也包括左鏈接表的全部行。 
SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
B:right (outer) join: 
右外鏈接(右鏈接):結果集既包括鏈接表的匹配鏈接行,也包括右鏈接表的全部行。 
C:full/cross (outer) join: 
全外鏈接:不只包括符號鏈接表的匹配行,還包括兩個鏈接表中的全部記錄。
十二、分組:Group by:
 	一張表,一旦分組 完成後,查詢後只能獲得組相關的信息。
	組相關的信息:(統計信息) count,sum,max,min,avg  分組的標準)
    在SQLServer中分組時:不能以text,ntext,image類型的字段做爲分組依據
	在selecte統計函數中的字段,不能和普通的字段放在一塊兒;
1三、對數據庫進行操做:
	分離數據庫: sp_detach_db; 附加數據庫:sp_attach_db 後接代表,附加須要完整的路徑名
14.如何修改數據庫的名稱:
sp_renamedb 'old_name', 'new_name' 

2、提高
一、說明:複製表(只複製結構,源表名:a 新表名:b) (Access可用)
法一:select * into b from a where 1&lt;&gt;1(僅用於SQlServer)
法二:select top 0 * into b from a
二、說明:拷貝表(拷貝數據,源表名:a 目標表名:b) (Access可用)
insert into b(a, b, c) select d,e,f from b;
三、說明:跨數據庫之間表的拷貝(具體數據使用絕對路徑) (Access可用)
insert into b(a, b, c) select d,e,f from b in ‘具體數據庫’ where 條件
例子:..from b in '"&amp;Server.MapPath(".")&amp;"\data.mdb" &amp;"' where..
四、說明:子查詢(表名1:a 表名2:b)
select a,b,c from a where a IN (select d from b ) 或者: select a,b,c from a where a IN (1,2,3)
五、說明:顯示文章、提交人和最後回覆時間
select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
六、說明:外鏈接查詢(表名1:a 表名2:b)
select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
七、說明:在線視圖查詢(表名1:a )
select * from (SELECT a,b,c FROM a) T where t.a &gt; 1;
八、說明:between的用法,between限制查詢數據範圍時包括了邊界值,not between不包括
select * from table1 where time between time1 and time2
select a,b,c, from table1 where a not between 數值1 and 數值2
九、說明:in 的使用方法
select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)
十、說明:兩張關聯表,刪除主表中已經在副表中沒有的信息 
delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )
十一、說明:四表聯查問題:
select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....
十二、說明:日程安排提早五分鐘提醒 
SQL: select * from 日程安排 where datediff('minute',f開始時間,getdate())&gt;5
1三、說明:一條sql 語句搞定數據庫分頁
select top 10 b.* from (select top 20 主鍵字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主鍵字段 = a.主鍵字段 order by a.排序字段
具體實現:
關於數據庫分頁:
  declare @start int,@end int 
  @sql  nvarchar(600)
  set @sql=’select top’+str(@end-@start+1)+’+from T where rid not in(select top’+str(@str-1)+’Rid from T where Rid&gt;-1)’
  exec sp_executesql @sql

注意:在top後不能直接跟一個變量,因此在實際應用中只有這樣的進行特殊的處理。Rid爲一個標識列,若是top後還有具體的字段,這樣作是很是有好處的。由於這樣能夠避免 top的字段若是是邏輯索引的,查詢的結果後實際表中的不一致(邏輯索引中的數據有可能和數據表中的不一致,而查詢時若是處在索引則首先查詢索引)
1四、說明:前10條記錄
select top 10 * form table1 where 範圍
1五、說明:選擇在每一組b值相同的數據中對應的a最大的記錄的全部信息(相似這樣的用法能夠用於論壇每個月排行榜,每個月熱銷產品分析,按科目成績排名,等等.)
select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)
1六、說明:包括全部在 TableA 中但不在 TableB和TableC 中的行並消除全部重複行而派生出一個結果表
(select a from tableA ) except (select a from tableB) except (select a from tableC)
1七、說明:隨機取出10條數據
select top 10 * from tablename order by newid()
1八、說明:隨機選擇記錄
select newid()
1九、說明:刪除重複記錄
1),delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
2),select distinct * into temp from tablename
  delete from tablename
  insert into tablename select * from temp
評價: 這種操做牽連大量的數據的移動,這種作法不適合大容量但數據操做
3),例如:在一個外部表中導入數據,因爲某些緣由第一次只導入了一部分,但很難判斷具體位置,這樣只有在下一次所有導入,這樣也就產生好多重複的字段,怎樣刪除重複字段
alter table tablename
--添加一個自增列
add  column_b int identity(1,1)
 delete from tablename where column_b not in(
select max(column_b)  from tablename group by column1,column2,...)
alter table tablename drop column column_b
20、說明:列出數據庫裏全部的表名
select name from sysobjects where type='U' // U表明用戶
2一、說明:列出表裏的全部的列名
select name from syscolumns where id=object_id('TableName')
2二、說明:列示type、vender、pcs字段,以type字段排列,case能夠方便地實現多重選擇,相似select 中的case。
select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type
顯示結果:
type vender pcs
電腦 A 1
電腦 A 1
光盤 B 2
光盤 A 2
手機 B 3
手機 C 3
2三、說明:初始化表table1
TRUNCATE TABLE table1
2四、說明:選擇從10到15的記錄
select top 5 * from (select top 15 * from table order by id asc) table_別名 order by id desc
3、技巧
一、1=1,1=2的使用,在SQL語句組合時用的較多
「where 1=1」 是表示選擇所有    「where 1=2」所有不選,
如:
if @strWhere !='' 
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere 
end
else 
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + ']' 
end 
咱們能夠直接寫成
錯誤!未找到目錄項。
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere 二、收縮數據庫
--重建索引
DBCC REINDEX
DBCC INDEXDEFRAG
--收縮數據和日誌
DBCC SHRINKDB
DBCC SHRINKFILE
三、壓縮數據庫
dbcc shrinkdatabase(dbname)
四、轉移數據庫給新用戶以已存在用戶權限
exec sp_change_users_login 'update_one','newname','oldname'
go
五、檢查備份集
RESTORE VERIFYONLY from disk='E:\dvbbs.bak'
六、修復數據庫
ALTER DATABASE [dvbbs] SET SINGLE_USER
GO
DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
GO
ALTER DATABASE [dvbbs] SET MULTI_USER
GO
七、日誌清除
SET NOCOUNT ON
DECLARE @LogicalFileName sysname,
 @MaxMinutes INT,
 @NewSize INT

USE tablename -- 要操做的數據庫名
SELECT  @LogicalFileName = 'tablename_log', -- 日誌文件名
@MaxMinutes = 10, -- Limit on time allowed to wrap log.
 @NewSize = 1  -- 你想設定的日誌文件的大小(M)
Setup / initialize
DECLARE @OriginalSize int
SELECT @OriginalSize = size 
 FROM sysfiles
 WHERE name = @LogicalFileName
SELECT 'Original Size of ' + db_name() + ' LOG is ' + 
 CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' + 
 CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
 FROM sysfiles
 WHERE name = @LogicalFileName
CREATE TABLE DummyTrans
 (DummyColumn char (8000) not null)

DECLARE @Counter    INT,
 @StartTime DATETIME,
 @TruncLog   VARCHAR(255)
SELECT @StartTime = GETDATE(),
 @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
EXEC (@TruncLog)
-- Wrap the log if necessary.
WHILE @MaxMinutes &gt; DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
 AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)  
 AND (@OriginalSize * 8 /1024) &gt; @NewSize  
 BEGIN -- Outer loop.
SELECT @Counter = 0
 WHILE   ((@Counter &lt; @OriginalSize / 16) AND (@Counter &lt; 50000))
 BEGIN -- update
 INSERT DummyTrans VALUES ('Fill Log') DELETE DummyTrans
 SELECT @Counter = @Counter + 1
 END
 EXEC (@TruncLog)  
 END
SELECT 'Final Size of ' + db_name() + ' LOG is ' +
 CONVERT(VARCHAR(30),size) + ' 8K pages or ' + 
 CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
 FROM sysfiles 
 WHERE name = @LogicalFileName
DROP TABLE DummyTrans
SET NOCOUNT OFF 
八、說明:更改某個表
exec sp_changeobjectowner 'tablename','dbo'
九、存儲更改所有表
CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
@OldOwner as NVARCHAR(128),
@NewOwner as NVARCHAR(128)
AS
DECLARE @Name    as NVARCHAR(128)
DECLARE @Owner   as NVARCHAR(128)
DECLARE @OwnerName   as NVARCHAR(128)
DECLARE curObject CURSOR FOR 
select 'Name'    = name,
   'Owner'    = user_name(uid)
from sysobjects
where user_name(uid)=@OldOwner
order by name
OPEN   curObject
FETCH NEXT FROM curObject INTO @Name, @Owner
WHILE(@@FETCH_STATUS=0)
BEGIN     
if @Owner=@OldOwner 
begin
   set @OwnerName = @OldOwner + '.' + rtrim(@Name)
   exec sp_changeobjectowner @OwnerName, @NewOwner
end
-- select @name,@NewOwner,@OldOwner
FETCH NEXT FROM curObject INTO @Name, @Owner
END
close curObject
deallocate curObject
GO

十、SQL SERVER中直接循環寫入數據
declare @i int
set @i=1
while @i&lt;30
begin
    insert into test (userid) values(@i)
    set @i=@i+1
end
案例:
有以下表,要求就裱中全部沒有及格的成績,在每次增長0.1的基礎上,使他們剛好及格:
	Name     score
	Zhangshan	80
	Lishi       59
	Wangwu      50
	Songquan	69
while((select min(score) from tb_table)&lt;60)
begin
update tb_table set score =score*1.01 
where score&lt;60
if  (select min(score) from tb_table)&gt;60
  break
 else
    continue
end

數據開發-經典

1.按姓氏筆畫排序:
Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as //從少到多
2.數據庫加密:
select encrypt('原始密碼')
select pwdencrypt('原始密碼')
select pwdcompare('原始密碼','加密後密碼') = 1--相同;不然不相同 encrypt('原始密碼')
select pwdencrypt('原始密碼')
select pwdcompare('原始密碼','加密後密碼') = 1--相同;不然不相同
3.取回表中字段:
declare @list varchar(1000),
@sql nvarchar(1000) 
select @list=@list+','+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name='表A'
set @sql='select '+right(@list,len(@list)-1)+' from 表A' 
exec (@sql)
4.查看硬盤分區:
EXEC master..xp_fixeddrives
5.比較A,B表是否相等:
if (select checksum_agg(binary_checksum(*)) from A)
     =
    (select checksum_agg(binary_checksum(*)) from B)
print '相等'
else
print '不相等'
6.殺掉全部的事件探察器進程:
DECLARE hcforeach CURSOR GLOBAL FOR SELECT 'kill '+RTRIM(spid) FROM master.dbo.sysprocesses
WHERE program_name IN('SQL profiler',N'SQL 事件探查器')
EXEC sp_msforeach_worker '?'
7.記錄搜索:
開頭到N條記錄
Select Top N * From 表
-------------------------------
N到M條記錄(要有主索引ID)
Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID   Desc
----------------------------------
N到結尾記錄
Select Top N * From 表 Order by ID Desc
案例
例如1:一張表有一萬多條記錄,表的第一個字段 RecID 是自增加字段, 寫一個SQL語句, 找出表的第31到第40個記錄。
 select top 10 recid from A where recid not  in(select top 30 recid from A)
分析:若是這樣寫會產生某些問題,若是recid在表中存在邏輯索引。
	select top 10 recid from A where……是從索引中查找,然後面的select top 30 recid from A則在數據表中查找,這樣因爲索引中的順序有可能和數據表中的不一致,這樣就致使查詢到的不是原本的欲獲得的數據。
解決方案
1,	用order by select top 30 recid from A order by ricid 若是該字段不是自增加,就會出現問題
2,	在那個子查詢中也加條件:select top 30 recid from A where recid&gt;-1
例2:查詢表中的最後以條記錄,並不知道這個表共有多少數據,以及表結構。
set @s = 'select top 1 * from T   where pid not in (select top ' + str(@count-1) + ' pid  from  T)'
print @s      exec  sp_executesql  @s
9:獲取當前數據庫中的全部用戶表
select Name from sysobjects where xtype='u' and status&gt;=0
10:獲取某一個表的全部字段
select name from syscolumns where id=object_id('表名')
select name from syscolumns where id in (select id from sysobjects where type = 'u' and name = '表名')
兩種方式的效果相同
11:查看與某一個表相關的視圖、存儲過程、函數
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like '%表名%'
12:查看當前數據庫中全部存儲過程
select name as 存儲過程名稱 from sysobjects where xtype='P'
13:查詢用戶建立的全部數據庫
select * from master..sysdatabases D where sid not in(select sid from master..syslogins where name='sa')
或者
select dbid, name AS DB_NAME from master..sysdatabases where sid &lt;&gt; 0x01
14:查詢某一個表的字段和數據類型
select column_name,data_type from information_schema.columns
where table_name = '表名' 
15:不一樣服務器數據庫之間的數據操做
--建立連接服務器 
exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '遠程服務器名或ip地址 ' 
exec sp_addlinkedsrvlogin  'ITSV ', 'false ',null, '用戶名 ', '密碼 ' 
--查詢示例 
select * from ITSV.數據庫名.dbo.表名 
--導入示例 
select * into 表 from ITSV.數據庫名.dbo.表名 
--之後再也不使用時刪除連接服務器 
exec sp_dropserver  'ITSV ', 'droplogins ' 

--鏈接遠程/局域網數據(openrowset/openquery/opendatasource) 
--一、openrowset 
--查詢示例 
select * from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名) 
--生成本地表 
select * into 表 from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名) 

--把本地表導入遠程表 
insert openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名) 
select *from 本地表 
--更新本地表 
update b 
set b.列A=a.列A 
 from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)as a inner join 本地表 b 
on a.column1=b.column1 
--openquery用法須要建立一個鏈接 
--首先建立一個鏈接建立連接服務器 
exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '遠程服務器名或ip地址 ' 
--查詢 
select * 
FROM openquery(ITSV,  'SELECT *  FROM 數據庫.dbo.表名 ') 
--把本地表導入遠程表 
insert openquery(ITSV,  'SELECT *  FROM 數據庫.dbo.表名 ') 
select * from 本地表 
--更新本地表 
update b 
set b.列B=a.列B 
FROM openquery(ITSV,  'SELECT * FROM 數據庫.dbo.表名 ') as a  
inner join 本地表 b on a.列A=b.列A 

--三、opendatasource/openrowset 
SELECT   * 
FROM   opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登錄名;Password=密碼 ' ).test.dbo.roy_ta 
--把本地表導入遠程表 
insert opendatasource( 'SQLOLEDB ',  'Data Source=ip/ServerName;User ID=登錄名;Password=密碼 ').數據庫.dbo.表名 
select * from 本地表  
SQL Server基本函數
SQL Server基本函數
1.字符串函數 長度與分析用 
1,datalength(Char_expr) 返回字符串包含字符數,但不包含後面的空格
2,substring(expression,start,length) 取子串,字符串的下標是從「1」,start爲起始位置,length爲字符串長度,實際應用中以len(expression)取得其長度
3,right(char_expr,int_expr) 返回字符串右邊第int_expr個字符,還用left於之相反
4,isnull( check_expression , replacement_value )若是check_expression為空,則返回replacement_value的值,不為空,就返回check_expression字符操做類 
5,Sp_addtype 自定義數據類型
例如:EXEC sp_addtype birthday, datetime, 'NULL'
6,set nocount {on|off}
使返回的結果中不包含有關受 Transact-SQL 語句影響的行數的信息。若是存儲過程當中包含的一些語句並不返回許多實際的數據,則該設置因爲大量減小了網絡流量,所以可顯著提升性能。SET NOCOUNT 設置是在執行或運行時設置,而不是在分析時設置。
SET NOCOUNT 爲 ON 時,不返回計數(表示受 Transact-SQL 語句影響的行數)。
SET NOCOUNT 爲 OFF 時,返回計數
常識

在SQL查詢中:from後最多能夠跟多少張表或視圖:256
在SQL語句中出現 Order by,查詢時,先排序,後取
在SQL中,一個字段的最大容量是8000,而對於nvarchar(4000),因爲nvarchar是Unicode碼。  
	
SQLServer2000同步複製技術實現步驟
1、 預備工做
1.發佈服務器,訂閱服務器都建立一個同名的windows用戶,並設置相同的密碼,作爲發佈快照文件夾的有效訪問用戶
--管理工具
--計算機管理
--用戶和組
--右鍵用戶
--新建用戶
--創建一個隸屬於administrator組的登錄windows的用戶(SynUser)
2.在發佈服務器上,新建一個共享目錄,作爲發佈的快照文件的存放目錄,操做:
個人電腦--D:\ 新建一個目錄,名爲: PUB
--右鍵這個新建的目錄
--屬性--共享
--選擇"共享該文件夾"
--經過"權限"按紐來設置具體的用戶權限,保證第一步中建立的用戶(SynUser) 具備對該文件夾的全部權限

--肯定
3.設置SQL代理(SQLSERVERAGENT)服務的啓動用戶(發佈/訂閱服務器均作此設置)
開始--程序--管理工具--服務
--右鍵SQLSERVERAGENT
--屬性--登錄--選擇"此帳戶"
--輸入或者選擇第一步中建立的windows登陸用戶名(SynUser)
--"密碼"中輸入該用戶的密碼
4.設置SQL Server身份驗證模式,解決鏈接時的權限問題(發佈/訂閱服務器均作此設置)
企業管理器
--右鍵SQL實例--屬性
--安全性--身份驗證
--選擇"SQL Server 和 Windows"
--肯定
5.在發佈服務器和訂閱服務器上互相註冊
企業管理器
--右鍵SQL Server組
--新建SQL Server註冊...
--下一步--可用的服務器中,輸入你要註冊的遠程服務器名 --添加
--下一步--鏈接使用,選擇第二個"SQL Server身份驗證"
--下一步--輸入用戶名和密碼(SynUser)
--下一步--選擇SQL Server組,也能夠建立一個新組
--下一步--完成
6.對於只能用IP,不能用計算機名的,爲其註冊服務器別名(此步在實施中沒用到)
 (在鏈接端配置,好比,在訂閱服務器上配置的話,服務器名稱中輸入的是發佈服務器的IP)
開始--程序--Microsoft SQL Server--客戶端網絡實用工具
--別名--添加
--網絡庫選擇"tcp/ip"--服務器別名輸入SQL服務器名
--鏈接參數--服務器名稱中輸入SQL服務器ip地址
--若是你修改了SQL的端口,取消選擇"動態決定端口",並輸入對應的端口號
2、 正式配置
一、配置發佈服務器
打開企業管理器,在發佈服務器(B、C、D)上執行如下步驟:
(1) 從[工具]下拉菜單的[複製]子菜單中選擇[配置發佈、訂閱服務器和分發]出現配置發佈和分發嚮導 
(2) [下一步] 選擇分發服務器 能夠選擇把發佈服務器本身做爲分發服務器或者其餘sql的服務器(選擇本身)
(3) [下一步] 設置快照文件夾
採用默認\\servername\Pub
(4) [下一步] 自定義配置 
能夠選擇:是,讓我設置分發數據庫屬性啓用發佈服務器或設置發佈設置
否,使用下列默認設置(推薦)
(5) [下一步] 設置分發數據庫名稱和位置 採用默認值
(6) [下一步] 啓用發佈服務器 選擇做爲發佈的服務器
(7) [下一步] 選擇須要發佈的數據庫和發佈類型
(8) [下一步] 選擇註冊訂閱服務器
(9) [下一步] 完成配置
二、建立出版物
發佈服務器B、C、D上
(1)從[工具]菜單的[複製]子菜單中選擇[建立和管理髮布]命令
(2)選擇要建立出版物的數據庫,而後單擊[建立發佈]
(3)在[建立發佈嚮導]的提示對話框中單擊[下一步]系統就會彈出一個對話框。對話框上的內容是複製的三個類型。咱們如今選第一個也就是默認的快照發布(其餘兩個你們能夠去看看幫助)
(4)單擊[下一步]系統要求指定能夠訂閱該發佈的數據庫服務器類型,
SQLSERVER容許在不一樣的數據庫如 orACLE或ACCESS之間進行數據複製。
可是在這裏咱們選擇運行"SQL SERVER 2000"的數據庫服務器
(5)單擊[下一步]系統就彈出一個定義文章的對話框也就是選擇要出版的表
注意: 若是前面選擇了事務發佈 則再這一步中只能選擇帶有主鍵的表
(6)選擇發佈名稱和描述
(7)自定義發佈屬性 嚮導提供的選擇:
是 我將自定義數據篩選,啓用匿名訂閱和或其餘自定義屬性
否 根據指定方式建立發佈 (建議採用自定義的方式)
(8)[下一步] 選擇篩選發佈的方式 
(9)[下一步] 能夠選擇是否容許匿名訂閱
1)若是選擇署名訂閱,則須要在發佈服務器上添加訂閱服務器
方法: [工具]-&gt;[複製]-&gt;[配置發佈、訂閱服務器和分發的屬性]-&gt;[訂閱服務器] 中添加
不然在訂閱服務器上請求訂閱時會出現的提示:改發佈不容許匿名訂閱
若是仍然須要匿名訂閱則用如下解決辦法 
[企業管理器]-&gt;[複製]-&gt;[發佈內容]-&gt;[屬性]-&gt;[訂閱選項] 選擇容許匿名請求訂閱
2)若是選擇匿名訂閱,則配置訂閱服務器時不會出現以上提示
(10)[下一步] 設置快照 代理程序調度
(11)[下一步] 完成配置
當完成出版物的建立後建立出版物的數據庫也就變成了一個共享數據庫
有數據 
srv1.庫名..author有字段:id,name,phone, 
srv2.庫名..author有字段:id,name,telphone,adress 

要求: 
srv1.庫名..author增長記錄則srv1.庫名..author記錄增長 
srv1.庫名..author的phone字段更新,則srv1.庫名..author對應字段telphone更新 
--*/ 

--大體的處理步驟 
--1.在 srv1 上建立鏈接服務器,以便在 srv1 中操做 srv2,實現同步 
exec sp_addlinkedserver 'srv2','','SQLOLEDB','srv2的sql實例名或ip' 
exec sp_addlinkedsrvlogin 'srv2','false',null,'用戶名','密碼' 
go
--2.在 srv1 和 srv2 這兩臺電腦中,啓動 msdtc(分佈式事務處理服務),而且設置爲自動啓動
。個人電腦--控制面板--管理工具--服務--右鍵 Distributed Transaction Coordinator--屬性--啓動--並將啓動類型設置爲自動啓動 
go 


--而後建立一個做業定時調用上面的同步處理存儲過程就好了 

企業管理器 
--管理 
--SQL Server代理 
--右鍵做業 
--新建做業 
--"常規"項中輸入做業名稱 
--"步驟"項 
--新建 
--"步驟名"中輸入步驟名 
--"類型"中選擇"Transact-SQL 腳本(TSQL)" 
--"數據庫"選擇執行命令的數據庫 
--"命令"中輸入要執行的語句: exec p_process 
--肯定 
--"調度"項 
--新建調度 
--"名稱"中輸入調度名稱 
--"調度類型"中選擇你的做業執行安排 
--若是選擇"反覆出現" 
--點"更改"來設置你的時間安排 


而後將SQL Agent服務啓動,並設置爲自動啓動,不然你的做業不會被執行 

設置方法: 
個人電腦--控制面板--管理工具--服務--右鍵 SQLSERVERAGENT--屬性--啓動類型--選擇"自動啓動"--肯定. 


--3.實現同步處理的方法2,定時同步 

--在srv1中建立以下的同步處理存儲過程 
create proc p_process 
as 
--更新修改過的數據 
update b set name=i.name,telphone=i.telphone 
from srv2.庫名.dbo.author b,author i 
where b.id=i.id and
(b.name &lt;&gt; i.name or b.telphone &lt;&gt; i.telphone) 

--插入新增的數據 
insert srv2.庫名.dbo.author(id,name,telphone) 
select id,name,telphone from author i 
where not exists( 
select * from srv2.庫名.dbo.author where id=i.id) 

--刪除已經刪除的數據(若是須要的話) 
delete b 
from srv2.庫名.dbo.author b 
where not exists( 
select * from author where id=b.id)
go
相關文章
相關標籤/搜索