實驗一 練習1、請查詢表DEPT中所有部門的情況。 select * from dept; 練習2、查詢表DEPT中的部門號、部門名稱兩個字段的所有信息。 select deptno,dname from dept; 練習3、請從表EMP中查詢10號部門工作的雇員姓名和工資。 select ename,sal from emp where deptno=10; 練習4、請從表EMP中查找工種是職員CLERK或經理MANAGER的雇員姓名、工資。 select ename,sal from emp where job='CLERK' or job='MANAGER'; 練習5、請在EMP表中查找部門號在10-30之間的雇員的姓名、部門號、工資、工作。 select ename,deptno,sal,job from emp where deptno between 10 and 30; 練習6、請從表EMP中查找姓名以J開頭所有雇員的姓名、工資、職位。 select ename,sal,job from emp where ename like 'J%'; 練習7、請從表EMP中查找工資低於2000的雇員的姓名、工作、工資,並按工資降序排列。 select ename,job,sal from emp where sal<=2000 order by sal desc; 練習8、請從表中查詢工作是CLERK的所有人的姓名、工資、部門號、部門名稱以及部門地址的信息。 select ename,sal,emp.deptno,dname,loc from emp,dept where emp.deptno=dept.deptno and job=’CLERK’; 練習9、查詢表EMP中所有的工資大於等於2000的雇員姓名和他的經理的名字。 select a.ename,b.ename from emp a,emp b where a.mgr=b.empno(+) and a.sal>=2000; 練習10、在表EMP中查詢所有工資高於JONES的所有雇員姓名、工作和工資。 select ename,job,sal from emp where sal>(select sal from emp where ename=’JONES’); 練習11、列出沒有對應部門表信息的所有雇員的姓名、工作以及部門號。 select ename,job,deptno from emp where deptno not in (select deptno from dept); 練習12、查找工資在1000~3000之間的雇員所在部門的所有人員信息 select * from emp where deptno in (select distinct deptno from emp where sal between 1000 and 3000); 練習13、雇員中誰的工資最高。 select ename from emp where sal=(select max(sal) from emp); select ename from (select * from emp order by sal desc) where rownum<=1; *練習14、雇員中誰的工資第二高(考慮並列第一的情況,如何處理)。 select ename from (select ename ,sal from (select * from emp order by sal desc) where rownum<=2 order by sal) where rownum<=1; 實驗二 1. 查詢所有雇員的姓名、SAL與COMM之和。 select ename,sal+nvl(comm,0) “sal-and-comm” from emp; 2. 查詢所有81年7月1日以前來的員工姓名、工資、所屬部門的名字 select ename,sal,dname from emp,dept where emp.deptno=dept.deptno and hiredate<=to_date(‘1981-07-01’,’yyyy-mm-dd’); 3. 查詢各部門中81年1月1日以后來的員工數 select deptno,count(*) from emp where hiredate>=to_date(‘1981-01-01’,’yyyy-mm-dd’) group by deptno; 4. 查詢所有在CHICAGO工作的經理MANAGER和銷售員SALESMAN的姓名、工資 select ename,sal from emp where (job=’MANAGER’ or job=’SALES’) and deptno in (select deptno from dept where loc=’CHICAGO’); 5. 查詢列出來公司就職時間超過24年的員工名單 select ename from emp where hiredate<=add_months(sysdate,-288); 6. 查詢於81年來公司所有員工的總收入(SAL和COMM) select sum(sal+nvl(comm,0)) from emp where to_char(hiredate,’yyyy’)=’1981’; 7. 查詢顯示每個雇員加入公司的准確時間,按××××年××月××日 時分秒顯示。 select ename,to_char(hiredate,'yyyy-mm-dd hh24:mi:ss') from emp; 8. 查詢公司中按年份月份統計各地的錄用職工數量 select to_char(hiredate,'yyyy-mm'),loc,count(*) from emp,dept where emp.deptno=dept.deptno group by to_char(hiredate,'yyyy-mm'),loc; 9. 查詢列出各部門的部門名和部門經理名字 select dname,ename from emp,dept where emp.deptno=dept.deptno and job=’MANAGER’; 10. 查詢部門平均工資最高的部門名稱和最低的部門名稱 select dname from dept where deptno=(select deptno from (select deptno from emp group by deptno order by avg(sal) ) where rownum<=1) union all select dname from dept where deptno=(select deptno from (select deptno from emp group by deptno order by avg(sal) desc ) where rownum<=1); 11. *查詢與雇員號為7521員工的最接近的在其后進入公司的員工姓名及其所在部門名 select ename,dname from (select ename,deptno from (select ename,deptno from emp where hiredate>(select hiredate from emp where empno=7521) order by hiredate ) where rownum<=1) e,dept where e.deptno=dept.deptno 實驗三、 1. 建立一個表(表名自定),表結構與EMP相同,沒有任何記錄。 create table my_emp as select * from emp; 2. 用Insert語句輸入5條記錄,並提交。 3. 擴大該表的記錄數到約40條,並使雇員號不重復;每個雇員都有所屬部門,雇員在同一部門的經理是同一人。 insert …. update … commit 4. 建立一個與DEPT表結構和記錄完全相同的新表,並與前項新表建立參照完整性約束。 alter table my_dept add( constraint s1 primary key(deptno)); alter table my_emp add(constraint s2 foreign key(deptno) references dept(deptno)); 5. 對在‘NEW YORK’工作的雇員加工資,每人加200。 6. *如果雇員姓名與部門名稱中有一個或一個以上相同的字母,則該雇員的COMM增加500。 update my_emp a set comm=NVL(comm,0)+500 where a.ename<>( select translate(a.ename,b.dname,CHR(27)) from my_dept b where b.deptno=a.deptno ); --a.deptno與b.deptno必須有主外鍵連接,否則可能出錯,為什么? commit; 7. 刪除部門號為30的記錄,並刪除該部門的所有成員。 delete from emp where deptno=30; delete from dept where deptno=30; commit 8. 新增列性別SEX,字符型。 alter table emp add(sex char(2)); 9. 修改新雇員表中的MGR列,為字符型。 該列數據必須為空 alter table emp modify(mgr varchar2(20)); 10. 試着去刪除新表中的一個列。 alter table my_emp drop (comm); 實驗四、 1. 查詢部門號為30的所有人員的管理層次圖。 select level,ename from emp connect by mgr=prior empno start with deptno=30 and job='MANAGER'; 2. 查詢員工SMITH的各個層次領導。 select level,ename from emp connect by prior mgr= empno start with ENAME='SMITH'; 3. 查詢顯示EMP表各雇員的工作類型,並翻譯為中文顯示 用decode函數 4. *查詢顯示雇員進入公司當年是什么屬相年(不考慮農歷的年份算法) 用decode函數 5. 建立一個視圖myV_emp,視圖包括myEMP表的empno、ename、sal,並按sal從大到小排列。 create view myV_EMP as select empno,ename,sal from emp; 6. 定義一個mySeq,對select mySeq.nextval,my_emp.* from my_emp的執行結果進行說明。 7. 定義序列mySeq、myEMP、myV_emp的同義詞,能否用同義詞對上述對象進行訪問。 8. 在myEMP表中建立ename的唯一性索引。 9. 如何在sql*plus中,運行sql的腳本(即后綴為.sql的文件) 實驗五、 1. 觀察下列PL/SQL的執行結果 declare s emp%rowtype; begin select * into s from emp where ename='KING'; DBMS_OUTPUT.PUT_LINE(s.empno||s.ename||s.job||s.sal); END; 2. 編寫一個PL/SQL,顯示ASC碼值從32至120的字符。 begin for i in 32..120 loop dbms_output.put_line(chr(i)); end loop; end; 3. 計算myEMP表中COMM最高與最低的差值,COMM值為空時按0計算。 declare var1 number; var2 number; val_comm number; begin select max(nvl(comm,0)) into var1 from myemp; select min(nvl(comm,0)) into var2 from myemp; val_comm:=var1-var2; dbms_output.put_line(val_comm); end; 4. 根據表myEMP中deptno字段的值,為姓名為‘JONES’的雇員修改工資;若部門號為10,則工資加100;部門號為20,加200;其他部門加400。 declare c1 number; c2 number; begin select deptno into c1 from emp where ename=’JONES’; if c1=10 then c2:=100; elsif c1=20 then c2:=200; else c2:=400; end if; update emp set sal=sal+c2 where ename=’JONES’; commit; end; 5. 計算顯示部門人數最多的部門號、人數、工資總和,以及部門人數最少的部門號、人數、工資總和。 6. 計算myEMP中所有雇員的所得稅總和。假設所得稅為累進稅率,所得稅算法為:工資收入為0-1000為免稅;收入1000-2000者,超過1000的部分稅率10%;2000-3000者超過2000部分按20%稅率計算;3000-4000者超過3000部分按30%稅率計算;4000以上收入,超過4000部分按40%稅率計算。(請查閱累進稅率的概念) declare sum_xx number:=0; xx number; begin --計算收入為1000-2000的所得稅總額 select sum((sal-1000)*0.1) into xx from emp where sal >1000 and sal<=2000; sum_xx:=sum_xx+xx; --計算收入為2000-3000的所得稅總額 select sum((sal-2000)*0.2+100) into xx from emp where sal >2000 and sal<=3000; sum_xx:=sum_xx+xx; --計算收入為3000-4000的所得稅總額 select sum((sal-3000)*0.3+300) into xx from emp where sal >3000 and sal<=4000; sum_xx:=sum_xx+xx; --計算收入為4000以上的所得稅總額 select sum((sal-4000)*0.4+600) into xx from emp where sal >4000; sum_xx:=sum_xx+xx; dbms_output.put_line(sum_xx); end; 7. *(可選做,難題)假設有個表如myEMP,未建立主鍵,含有多條記錄重復(列值完全相同),試編制一個PL/SQL,將多余的重復記錄刪除。 實驗六、 1. 用外部變量,實現兩個PL/SQL程序間的數據交換。 SQL> variable a1 number; SQL> begin 2 :a1:=1000; 3 end; 4 / PL/SQL 過程已成功完成。 SQL> begin 2 dbms_output.put_line(:a1); 3 end; 4 / 1000 PL/SQL 過程已成功完成。 2. 插入myEMP表中的數據記錄,考慮可能出現的例外,並提示。 主要的例外提示:唯一性索引值重復DUP_VAL_ON_INDEX 3. 刪除myDEPT表中的數據記錄一條,考慮例外情況,並提示。 主要的例外提示:違反完整約束條件 4. 將下列PL/SQL改為FOR游標 declare cursor cur_myemp is select * from emp; r emp%rowtype; begin open cur_myemp; fetch cur_myemp into r; while cur_myemp%found loop dbms_output.put_line(r.ename); fetch cur_myemp into r; end loop; close cur_myemp; end; 5. 工資級別的表salgrade,列出各工資級別的人數。(用游標來完成) declare v1 number; cursor cur1 is select * from salgrade; begin for c1 in cur1 loop select count(*) into v1 from emp where sal between c1.losal and c1.hisal; dbms_output.put_line('grade'||c1.grade||' '||v1); end loop; end; 實驗七、 1. 在myEMP表中增加一個字段,字段名為EMPPASS,類型為可變長字符。 2. 建立一個存儲過程,用於操作用戶登錄的校驗,登錄需要使用EMPNO和EMPPASS,並需要提示登錄中的錯誤,如是EMPNO不存在,還是EMPNO存在而是EMPPASS錯誤等。 create or replace procedure p_login( in_empno in emp.empno%type, in_emppass in emp.emppass%type, out_code out number, out_desc out varchar2) is x1 emp.ename%type; x2 number; begin select ename into x1 from emp where empno=in_empno; select count(*) into x2 from emp where empno=in_empno and emppass=in_emppass; if x2=1 then out_code:=0; out_desc:=x1; else out_code:=2; out_desc:=’用戶登陸密碼錯誤!’; end if; exception when NO_DATA_FOUND then out_code:=1; out_desc:=’該用戶號存在!’; when TOO_MANY_ROWS then out_code:=3; out_desc:=’該用戶號有重復值!’; when others then out_code:=100; out_desc:=’其他錯誤!’; end; 3. 建立一個存儲過程,實現myEMP表中指定雇員的EMPPASS字段的修改,修改前必須進行EMPPASS舊值的核對。 Create or REPLACE PROCEDURE P_CHANGEPASS( IN_EMPNO IN EMP.EMPNO%TYPE, IN_OLDPASS IN EMP.EMPPASS%TYPE, IN_NEWPASS IN EMP.EMPPASS%TYPE, OUT_CODE OUT NUMBER, OUT_DESC OUT VARCHAR2) IS X1 NUMBER; BEGIN Select COUNT(*) INTO X1 FROM EMP Where EMPNO=IN_EMPNO AND EMPPASS=IN_OLDPASS; IF X1=1 THEN update emp set emppass=in_newpass where empno=in_empno; commit; OUT_CODE:=0; OUT_DESC:=’修改口令成功’; ELSE OUT_CODE:=1; OUT_DESC:=’修改口令不成功’; END IF; exception when others then out_code:=100; out_desc:=’其他錯誤’; END; 4. 建立一個函數,輸入一個雇員號,返回該雇員的所在同一部門的最高級別上司姓名。 create or replace function f_leader( in_empno in emp.empno%type) return varchar2 is v1 number; v2 number; v3 emp.ename%type; v4 emp.deptno%type; begin v1:=in_empno; v3:='未找到'; select deptno into v4 from emp where empno=v1; loop select mgr into v2 from emp where empno=v1; select ename into v3 from emp where empno=v2 and deptno=v4; v1:=v2; end loop; exception when others then return v3; end; 5. 試用上題函數,實現各雇員的同一部門最高級別上司的Select查詢。 select f_leader(7521) from dual; 6. *編寫實驗五中第六題,關於各雇員工資的所得稅計算函數 實驗八、 1. 建立一個觸發器,當myEMP表中部門號存在時,該部門不允許刪除。 create or replace trigger dept_line_delete before delete on dept for each row declare v1 number; begin select count(*) into v1 from emp where deptno=:old.deptno; if v1>=1 then RAISE_APPLICATION_ERROR(-20000,’錯誤’); end if; end; 實驗九、 1. 建立一個示例包emp_mgmt中,新增一個修改雇員所在部門的過程。 create or replace package emp_mgmt as procedure change_dept( in_newdept in emp.deptno%type, out_code out number, out_desc out varchar2); mgmt_empno emp.empno%type; procedure mgmt_login( in_empno in emp.empno%type, in_emppass in emp.emppass%type, out_code out number, out_desc out varchar2); end; create or replace package body emp_mgmt as procedure change_dept( in_newdept in emp.deptno%type, out_code out number, out_desc out varchar2) is begin update emp set deptno=in_newdept where empno=mgmt_empno; commit; out_code:=0; out_desc:=’ok’; end; procedure mgmt_login( in_empno in emp.empno%type, in_emppass in emp.emppass%type, out_code out number, out_desc out varchar2) is begin --登陸過程見實驗七第2題 mgmt_empno:=in_empno; out_code:=0; out_desc:=’ok’; end; end; 2. 假設myEMP表中有口令字段password,試在包emp_mgmt中建立一個登錄的過程,並將登錄成功的雇員號存入包變量。 見前一題 3. 示例包emp_mgmt中,將remove_emp操作設限,只有本部門經理操作才能刪除本部門雇員記錄,只有公司頭頭PRESIDENT才能刪除部門經理的雇員記錄。 -- procedure remove_emp( remove_empno emp.empno%type, out_code number, out_desc varchar2) is x emp.job%type; y number; begin select job,deptno into x,y from emp where empno=mgmt_empno; if x=’PRESIDENT’ then delete from emp where empno=remove_empno and job=’MANAGER’; else delete from emp where empno=remove_empno and deptno=y and x=’MANAGER’; end if if sql%found then out_code:=0; out_desc:=’ok’; else out_code:=1; out_desc:=’未刪除記錄’; end if; commit; end; 4. *用DELPHI+ORACLE實現上題的軟件功能。 實驗十 1. 編寫一段PL/SQL,利用系統工具包,實現對SERVER端數據文件D:\DATA\A.TXT的讀取輸出至緩沖區。 2. 編寫一個存儲過程,就myEMP表,輸入參數為字段名和匹配值(字符型),對符合匹配條件的工資加100。 3. 編寫一個存儲過程,輸入參數為一個表名,通過存儲過程處理將該表刪除Drop,並返回是否成功的信息。 實驗十一 1. 以雇員作為對象類型,試根據myEMP表結構設計其屬性,方法主要有雇員更換部門、更換工種、MAP排序的定義。 2. 編制一個雇員類型的對象表myOBJ_EMP。 3. 添加對象表myOBJ_EMP的數據10條。 4. 試對對象表排序輸出。 5. 給對象表中部門號為20的記錄的工資增加10%。 6. 顯示每個雇員所在的雇員名、部門名稱。