oracle sql練習題

kingsql發表於2017-05-17


實驗一
練習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;

實驗二
. 查詢所有僱員的姓名、SAL與COMM之和。
select ename,sal nvl(comm,0) “sal-and-comm” from emp;
. 查詢所有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’);
. 查詢各部門中81年1月1日以後來的員工數
select deptno,count(*) from emp where hiredate>=to_date(‘1981-01-01’,’yyyy-mm-dd’) group by deptno;
. 查詢所有在CHICAGO工作的經理MANAGER和銷售員SALESMAN的姓名、工資
select ename,sal from emp where (job=’MANAGER’ or job=’SALES’) and deptno in (select deptno from dept where loc=’CHICAGO’);
. 查詢列出來公司就職時間超過24年的員工名單
select ename from emp where hiredate<=add_months(sysdate,-288);
. 查詢於81年來公司所有員工的總收入(SAL和COMM)
select sum(sal nvl(comm,0)) from emp where to_char(hiredate,’yyyy’)=’1981’;
. 查詢顯示每個僱員加入公司的準確時間,按××××年××月××日 時分秒顯示。
select ename,to_char(hiredate,'yyyy-mm-dd hh24:mi:ss') from emp;
. 查詢公司中按年份月份統計各地的錄用職工數量
select to_char(hiredate,'yyyy-mm'),loc,count(*) from emp,dept
where emp.deptno=dept.deptno group by to_char(hiredate,'yyyy-mm'),loc;
. 查詢列出各部門的部門名和部門經理名字
select dname,ename from emp,dept where emp.deptno=dept.deptno and job=’MANAGER’;
. 查詢部門平均工資最高的部門名稱和最低的部門名稱
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);
. *查詢與僱員號為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

實驗三、
. 建立一個表(表名自定),表結構與EMP相同,沒有任何記錄。
create table my_emp as select * from emp;
. 用Insert語句輸入5條記錄,並提交。
. 擴大該表的記錄數到約40條,並使僱員號不重複;每個僱員都有所屬部門,僱員在同一部門的經理是同一人。
insert ….
update …
commit
. 建立一個與DEPT表結構和記錄完全相同的新表,並與前項新表建立參照完整性約束。
alter table my_dept add( constraint s1 primary key(deptno));
alter table my_emp add(constraint s2 foreign key(deptno) references dept(deptno));
. 對在‘NEW YORK’工作的僱員加工資,每人加200。
. *如果僱員姓名與部門名稱中有一個或一個以上相同的字母,則該僱員的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;
. 刪除部門號為30的記錄,並刪除該部門的所有成員。
delete from emp where deptno=30;
delete from dept where deptno=30;
commit
. 新增列性別SEX,字元型。
alter table emp add(sex char(2));
. 修改新僱員表中的MGR列,為字元型。
該列資料必須為空
alter table emp modify(mgr varchar2(20));
. 試著去刪除新表中的一個列。
alter table my_emp drop (comm);

實驗四、
. 查詢部門號為30的所有人員的管理層次圖。
select level,ename from emp
connect by mgr=prior empno
start with deptno=30 and job='MANAGER';
. 查詢員工SMITH的各個層次領導。
select level,ename from emp
connect by prior mgr= empno
start with ENAME='SMITH';
. 查詢顯示EMP表各僱員的工作型別,並翻譯為中文顯示
用decode函式
. *查詢顯示僱員進入公司當年是什麼屬相年(不考慮農曆的年份演算法)
用decode函式
. 建立一個檢視myV_emp,檢視包括myEMP表的empno、ename、sal,並按sal從大到小排列。
create view myV_EMP as select empno,ename,sal from emp;
. 定義一個mySeq,對select mySeq.nextval,my_emp.* from my_emp的執行結果進行說明。
. 定義序列mySeq、myEMP、myV_emp的同義詞,能否用同義詞對上述物件進行訪問。
. 在myEMP表中建立ename的唯一性索引。
. 如何在sql*plus中,執行sql的指令碼(即字尾為.sql的檔案)

實驗五、
. 觀察下列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;
. 編寫一個PL/SQL,顯示ASC碼值從32至120的字元。
begin
for i in 32..120
loop
dbms_output.put_line(chr(i));
end loop;
end;
. 計算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;
. 根據表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;
. 計算顯示部門人數最多的部門號、人數、工資總和,以及部門人數最少的部門號、人數、工資總和。
. 計算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;
. *(可選做,難題)假設有個表如myEMP,未建立主鍵,含有多條記錄重複(列值完全相同),試編制一個PL/SQL,將多餘的重複記錄刪除。
實驗六、
. 用外部變數,實現兩個PL/SQL程式間的資料交換。
SQL> variable a1 number;
SQL> begin
:a1:=1000;
end;
/

PL/SQL 過程已成功完成。

SQL> begin
dbms_output.put_line(:a1);
end;
/


PL/SQL 過程已成功完成。
. 插入myEMP表中的資料記錄,考慮可能出現的例外,並提示。
主要的例外提示:唯一性索引值重複DUP_VAL_ON_INDEX
. 刪除myDEPT表中的資料記錄一條,考慮例外情況,並提示。
主要的例外提示:違反完整約束條件
. 將下列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;
. 工資級別的表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;

實驗七、
. 在myEMP表中增加一個欄位,欄位名為EMPPASS,型別為可變長字元。
. 建立一個儲存過程,用於操作使用者登入的校驗,登入需要使用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;
. 建立一個儲存過程,實現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;
. 建立一個函式,輸入一個僱員號,返回該僱員的所在同一部門的最高階別上司姓名。
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;
. 試用上題函式,實現各僱員的同一部門最高階別上司的Select查詢。
select f_leader(7521) from dual;
. *編寫實驗五中第六題,關於各僱員工資的所得稅計算函式

實驗八、
. 建立一個觸發器,當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;

實驗九、
. 建立一個示例包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;
. 假設myEMP表中有口令欄位password,試在包emp_mgmt中建立一個登入的過程,並將登入成功的僱員號存入包變數。
見前一題
. 示例包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;
. *用DELPHI+ORACLE實現上題的軟體功能。

實驗十
. 編寫一段PL/SQL,利用系統工具包,實現對SERVER端資料檔案D:\DATA\A.TXT的讀取輸出至緩衝區。
. 編寫一個儲存過程,就myEMP表,輸入引數為欄位名和匹配值(字元型),對符合匹配條件的工資加100。
. 編寫一個儲存過程,輸入引數為一個表名,透過儲存過程處理將該表刪除Drop,並返回是否成功的資訊。

實驗十一
. 以僱員作為物件型別,試根據myEMP表結構設計其屬性,方法主要有僱員更換部門、更換工種、MAP排序的定義。
. 編制一個僱員型別的物件表myOBJ_EMP。
. 新增物件表myOBJ_EMP的資料10條。
. 試對物件表排序輸出。
. 給物件表中部門號為20的記錄的工資增加10%。
. 顯示每個僱員所在的僱員名、部門名稱。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28389881/viewspace-2139251/,如需轉載,請註明出處,否則將追究法律責任。