經典練習題

輸入一個數字,根據這個數是奇數還是偶數
如果這個數是奇數,則打印出 這個數的3次方的結果,比如 3 ,則打印出9 ,5 則打印出 125
如果這個數是偶數,則打印出 這個數的2次方的結果,比如 2 ,則打印出4 ,10則打印出 100
如果是 0 的話 ,則打印出 1024

解題方法:

DECLARE
  X  NUMBER(10) := &請輸入一個數字;
  SQ NUMBER(10);
BEGIN
  IF X = 0 THEN
    SQ := 1024;
  ELSIF MOD(X, 2) = 1 THEN
    SQ := POWER(X, 3);
  ELSE
    SQ := POWER(X, 2);
  END IF;
  DBMS_OUTPUT.PUT_LINE(X || ' ' || SQ);
END;

方法二:

DECLARE
X NUMBER(10) :=&輸入正整數;

BEGIN 
  
IF  X=0 THEN 
    DBMS_OUTPUT.put_line ('輸入數字是 :'|| X || ' 1024');
  ELSIF MOD(X,2) != 0 THEN 
  DBMS_OUTPUT.put_line ('輸入數字是 :'|| X || '是一個奇數'||'它的三次方爲 :'||  POWER(X,3));
  ELSIF MOD(X,2) = 0 THEN 
     DBMS_OUTPUT.put_line ('輸入數字是 :'|| X || '是一個偶數'||'它的二次方爲 :'||  POWER(X,2));  
END IF ;
END;

輸入 三個大於0的數 ,a , b, c 判斷 這2個數作爲邊長能否組成三角形
如果 兩邊之和大於第三邊 則打印出這三個數可以組成三角形。 – 條件1
滿足條件1的情況下
如果 2邊相等,則打印 組成等腰三角形
如果 兩三邊相等,則打印出這是一個等邊三角形
否則 打印出 無法組成三角形。

解題方法一:

DECLARE
  A NUMBER(7) := &請輸入邊長A;
  B NUMBER(7) := &請輸入邊長B;
  C NUMBER(7) := &請輸入邊長C;
BEGIN
  IF (A + B) <= C OR (A + C) <= B OR (B + C) <= A THEN
    DBMS_OUTPUT.PUT_LINE('無法組成三角形');
  ELSIF A = B AND A = C THEN
    DBMS_OUTPUT.PUT_LINE('這是一個等邊三角形'); -- 判斷等邊和等腰的情況下,優先判斷等邊
  ELSIF A = B OR B = C OR A = C THEN
    DBMS_OUTPUT.PUT_LINE('這是一個等腰三角形'); -- 如果先判斷等腰三角形,那麼就無法判斷出等邊三角形了。
  ELSE
    DBMS_OUTPUT.PUT_LINE('組成一個普通三角形');
  END IF;
END;

解題方法二:

DECLARE
 a NUMBER(8) :=&請輸入一個正整數a;
 b NUMBER(8) :=&請輸入一個正整數b;
 c NUMBER(8) :=&請輸入一個正整數c;
 
 BEGIN 
 
     IF (a+b>c AND a+c>b AND b+c>a)AND (a=b AND a=c AND b=c) THEN
          dbms_output.put_line('這三個數可以組成等邊三角形');
          
          ELSIF (a+b>c AND a+c>b AND b+c>a) AND (a=b OR a=c OR b=c) THEN
          dbms_output.put_line('這三個數可以組成等腰三角形');
          
        ELSIF a+b>c AND a+c>b AND b+c>a THEN
     dbms_output.put_line('這三個數可以組成三角形');
     
      ELSE
        dbms_output.put_line('這三個數無法組成三角形');
        
        END IF;
     END;

100-1000之間的所有奇數之和

解題方法一:

DECLARE
    x NUMBER(10) :=101;
    y NUMBER(10) :=0;
BEGIN
        WHILE x<1000 LOOP 
        y :=x+y;
        x :=x+2;
         
    END LOOP;
    dbms_output.put_line(y);
END;

方法二:

DECLARE
    x NUMBER(10) :=101;
    y NUMBER(10) :=0;
BEGIN
        FOR x IN 100 .. 1000 LOOP 
           IF MOD(x,2)=1 THEN
            y:=y+x;
            END IF;
         
    END LOOP;
    dbms_output.put_line(y);
END;

解題方法三:

DECLARE 
 SUMJ NUMBER(10);
 S    NUMBER(8);
 J    NUMBER(8) ;
 BEGIN
   FOR S IN 100 .. 1000 LOOP
     IF MOD(S,2) != 0 THEN DBMS_OUTPUT.put_line('結果是:'||S); 
       J := S;
     SUMJ := J + SUMJ; 
     END IF;
     END LOOP;
     
     DBMS_OUTPUT.put_line('結果是:'||SUMJ);
  END;

求100…999之間的所有水仙花數(個位數的3次方 + 十位數的3次方 + 百位數的三次方 = 這個數值本身)

最佳解題方法:

DECLARE
     x NUMBER(1);
     y NUMBER(1); 
     z NUMBER(1);
BEGIN 
    FOR x IN 1..9 LOOP   -- 百位
        FOR  y IN 0..9 LOOP   -- 十位
            FOR z IN 0..9 LOOP  --個位
              
                IF POWER(x,3)+POWER(y,3)+POWER(z,3) =x*100+y*10+z
                THEN dbms_output.put_line(x*100+y*10+z); 
                   END IF;
            END LOOP;
        END LOOP;
    END LOOP;
END;

解題方法二:

DECLARE
  X NUMBER(10):=100;
  a NUMBER(2);
  b NUMBER(2);
  c NUMBER(2);
BEGIN
    WHILE X <=999 LOOP
     a:=TRUNC(X/100);
     b:=TRUNC((X-a*100)/10);
     c:= X-a*100-b*10;
     IF X=POWER(a,3)+POWER(b,3)+POWER(c,3) 
       THEN DBMS_OUTPUT.PUT_LINE(X);
     END IF;
     X:=X+1;
     END LOOP;
 END;

要求:sno能被3整除,gender爲男,其餘爲女
sno 被3整除餘1,姓張;被3整除餘2,姓王;能被3整除,姓李

解題方法:

BEGIN 
   FOR X IN 1..100 LOOP
   INSERT INTO   STU 
         VALUES (X , 
         CASE WHEN MOD(X,3) = 0 THEN '李'||X 
              WHEN MOD(X,3) = 1 THEN '張'||X
               ELSE '王'||X END  , 
         DECODE(MOD(X,3) ,0,'男','女'));
   END LOOP;
   COMMIT;
END ;

解題方法二:

CREATE TABLE STU (SNO NUMBER(10),
                  SNAME VARCHAR2(10),
                  GENDER VARCHAR2(10));

SELECT * FROM STU;

DECLARE
  x NUMBER(5) :=1;
BEGIN
    FOR x IN 1..100 LOOP
    IF MOD(x,3) = 0 THEN 
      INSERT INTO STU (SNO,GENDER)VALUES(x,'男');
      ELSE  INSERT INTO STU (SNO,GENDER)VALUES(x,'女');
    END IF;
    IF MOD(x,3)=1
    THEN UPDATE STU SET sname='張' WHERE sno = x;
     ELSIF MOD(X,3)=2
   THEN UPDATE STU  SET SNAME='王' WHERE SNO=x;
  ELSE 
    UPDATE STU  SET SNAME='李' WHERE SNO=x;
    END IF ;
    END LOOP;
END;

輸入一個數,判斷它的奇偶性, 打印出 您輸入的數字是 xx,它是一個 奇/偶數

解題方法:

--SELECT MOD(4,2) FROM DUAL;
DECLARE 
   X  NUMBER(10) :=&請輸入一個正整數 ;
BEGIN 
   IF  MOD(X,2) = 0 THEN 
     DBMS_OUTPUT.PUT_LINE('您輸入的數字是:'|| X ||',它是一個 偶數');
   ELSE 
      DBMS_OUTPUT.PUT_LINE('您輸入的數字是:'|| X ||',它是一個 奇數');
   END IF ;
END ; 

根據員工的入職時間打印出員工的 轉正日期和社保繳納如期,
如果入職日期是10號之前,則當月繳納,反之則次月開始繳納,打印出 社保繳納的 年和月
如果是12月10號之後日誌的員工,次月繳納時,爲次年的1月份。

解題方法一:

SELECT TO_CHAR(TO_DATE('20191211','YYYY/MM/DD'),'YYYY-MM') ,
       TO_CHAR(ROUND(TO_DATE('20191211','YYYY/MM/DD')+5,'MM'),'YYYY-MM') FROM DUAL

在這裏插入圖片描述

DECLARE
  CURSOR c_emp
  IS 
  SELECT e.hiredatE ,
         to_char(add_months(e.hiredate,6),'yyyy-mm-dd') 轉正日期,
          to_char(ROUND(E.hiredate + 5 ,'MM'),'yyyy-mm')   社保繳納日期     
  FROM emp e;
  
  v_cemp c_emp%ROWTYPE;
BEGIN
  FOR v_cemp IN c_emp LOOP
  dbms_output.put_line('入職日期:'||to_char(v_cemp.hiredate,'YYYY/MM/DD')||' '
      ||v_cemp.轉正日期||' '||v_cemp.社保繳納日期);
  END LOOP;
END;

解題方法二:

DECLARE

CURSOR C_EMP IS
 SELECT E.HIREDATE,
        ADD_MONTHS(E.HIREDATE,6) ZZDATE,
        /*TO_CHAR(E.HIREDATE,'DD') DD,*/
        ROUND(E.HIREDATE,'MM')NEXTMM,
        TRUNC(E.HIREDATE,'MM')DMM,
        TO_NUMBER(TO_CHAR(E.HIREDATE,'DD')) DD
 FROM EMP E;
 V_CEMP C_EMP%ROWTYPE;
 
 BEGIN 
   FOR V_CEMP IN C_EMP LOOP
     
   IF V_CEMP.DD > 10 THEN   
   DBMS_OUTPUT.PUT_LINE('入職時間: '||to_char(V_CEMP.HIREDATE,'yyyy/mm/dd') ||'  '||'轉正時間:'|| to_char(V_CEMP.ZZDATE,'yyyy/mm/dd') 
   ||' 購買社保時間:'|| TO_CHAR(V_CEMP.NEXTMM,'YYYY/MM')); 
   ELSIF V_CEMP.DD <=10 THEN
     DBMS_OUTPUT.PUT_LINE('入職時間: '||to_char(V_CEMP.HIREDATE,'yyyy/mm/dd') ||'  '||'轉正時間:'|| to_char(V_CEMP.ZZDATE,'yyyy/mm/dd') 
   ||' 購買社保時間:'|| TO_CHAR(V_CEMP.DMM,'YYYY/MM'));  
   END IF;
     END LOOP;       
 END;

打印出各個部門的人數(包括部門編號爲40),打印結果爲:
部門10的員工:
AAA

部門20的員工:
XXX

部門30的員工:
XXX

部門40的員工:

DECLARE 
CURSOR C_ED(P_DEPTNO NUMBER) IS --定義遊標
       SELECT wm_concat(E.ENAME) ENAME ,
             COUNT(EMPNO)RS
       FROM EMP E,DEPT D
       WHERE E.DEPTNO(+) = D.DEPTNO
       AND E.DEPTNO = D.DEPTNO;

V_CED C_ED%ROWTYPE;--定義遊標變量

BEGIN
  DBMS_OUTPUT.PUT_LINE('部門10的員工');
  FOR V_CED IN C_ED(10) LOOP
    DBMS_OUTPUT.PUT_LINE(V_CED.ENAME||' 人數 :'||V_CED.RS);
    END LOOP;
    
     DBMS_OUTPUT.PUT_LINE('部門20的員工');
  FOR V_CED IN C_ED(20) LOOP
    DBMS_OUTPUT.PUT_LINE(V_CED.ENAME||' 人數 :'||V_CED.RS);
    END LOOP;
       
     DBMS_OUTPUT.PUT_LINE('部門30的員工');
  FOR V_CED IN C_ED(30) LOOP
    DBMS_OUTPUT.PUT_LINE(V_CED.ENAME||' 人數 :'||V_CED.RS);
    END LOOP;
    
     DBMS_OUTPUT.PUT_LINE('部門40的員工');
  FOR V_CED IN C_ED(40) LOOP
    DBMS_OUTPUT.PUT_LINE(V_CED.ENAME||' 人數 :'||V_CED.RS);
    END LOOP;

END ;

打印出各個部門的員工(包括部門編號爲40),打印結果爲:
部門10的員工:
AAA

部門20的員工:
XXX

部門30的員工:
XXX

部門40的員工:

左外關聯

DECLARE
  CURSOR C_DEPT IS
    SELECT DEPT.DEPTNO ,
          COUNT(EMP.EMPNO) CT 
          FROM DEPT LEFT JOIN EMP 
          ON  EMP.DEPTNO = DEPT.DEPTNO 
          GROUP BY DEPT.DEPTNO 
          ORDER BY DEPT.DEPTNO;
  CURSOR C_EMP IS
    SELECT DEPTNO, 
           ENAME, 
           COUNT(1) OVER(PARTITION BY DEPTNO) CT 
           FROM EMP;
  V_CDEPT C_DEPT%ROWTYPE;
  V_CEMP  C_EMP%ROWTYPE;
BEGIN
  FOR V_CDEPT IN C_DEPT LOOP
    DBMS_OUTPUT.PUT_LINE('部門' || V_CDEPT.DEPTNO || '的員工:');
    DBMS_OUTPUT.PUT_LINE( '  人數爲'||V_CDEPT.CT);
    FOR V_CEMP IN C_EMP LOOP
      IF V_CEMP.DEPTNO = V_CDEPT.DEPTNO THEN
      
        DBMS_OUTPUT.PUT_LINE('  ' || V_CEMP.ENAME);
      END IF;
    END LOOP;
  END LOOP;
END;



**右外關聯**
DECLARE
  CURSOR C_ED IS
    SELECT D.DEPTNO, COUNT(E.DEPTNO) RS
      FROM EMP E
     RIGHT JOIN DEPT D
        ON E.DEPTNO = D.DEPTNO
     GROUP BY D.DEPTNO;
  V_CED C_ED%ROWTYPE;
BEGIN
  FOR V_CED IN C_ED LOOP
    DBMS_OUTPUT.PUT_LINE(V_CED.DEPTNO || ' ' || V_CED.RS);
  END LOOP;
END;

按照salgrade表中的標準,給員工加薪,1:5%,2:4%,3:3%,4:2%,5:1%,打印出每個人,加薪前後的工資。

參考答案:

DECLARE
  CURSOR C_ES IS
    SELECT E.ENAME,
           E.SAL,
           S.GRADE,
           DECODE(S.GRADE, 1,1.05 * E.SAL,
                  2,1.04 * E.SAL,
                  3,1.03 * E.SAL,
                  4,1.02 * E.SAL,
                  5,1.01 * E.SAL) NSAL
      FROM EMP E, SALGRADE S
     WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL;
  V_CES C_ES%ROWTYPE;
BEGIN
  FOR V_CES IN C_ES LOOP
    DBMS_OUTPUT.PUT_LINE(V_CES.ENAME || ' ' || V_CES.SAL || ' ' ||V_CES.GRADE|| ' ' ||V_CES.NSAL);
  END LOOP;
END;

編寫一個PL/SQL程序塊,從emp表中對名字以"A"或"S"開始的所有僱員
按他們基本薪水的10%給他們加薪,
打印出員工的姓名,薪水,加薪後的薪水。

參考答案:

DECLARE
  CURSOR c_emp
  IS 
  SELECT e.ename,
  	     e.sal,
         E.SAL*1.1 nsal
  FROM emp e
  WHERE E.ename LIKE 'A%' OR E.ename LIKE 'S%';
  
  v_cemp c_emp%ROWTYPE;
  
BEGIN
  FOR v_cemp IN c_emp LOOP
  dbms_output.put_line(v_cemp.ename||' '||v_cemp.sal||' '||v_cemp.nsal);
  END LOOP;
END;

建個目標表 EMP_SALES (DEPTNO ,DNAME ,SAL_L1,SAL_L2,SAL_L3,mark) SAL_L1 ~ SAL_L3 分別對應工資排名前1~3
檢查字段,要求使用 序列實現。
編寫存儲過程,使用全量同步的方式,更新目標表 EMP_SALES

CREATE TABLE EMP_SALES ( 
DEPTNO VARCHAR2(20),
DNAME VARCHAR2(20),
SAL_L1 NUMBER(7,2),
SAL_L2 NUMBER(7,2),
SAL_L3 NUMBER(7,2),
MARK NUMBER(10));
CREATE SEQUENCE SE1 /*INCREMENT BY 1 START WITH 1*/;
CREATE OR REPLACE PROCEDURE SP_SALES
IS 
V_MARK NUMBER(10);
BEGIN
  V_MARK := SE1.NEXTVAL;  -- MARK 檢查字段
  DELETE FROM EMP_SALES WHERE 1=1;
  
INSERT INTO EMP_SALES
  		(DEPTNO, 
  		 DNAME, 
  		 SAL_L1, 
  		 SAL_L2, 
  		 SAL_L3, 
  		 MARK) -- MARK 檢查字段
  SELECT DEPTNO,
         MAX(DNAME),
         MAX(DECODE(RN, 1, SAL)) SAL_L1,
         MAX(DECODE(RN, 2, SAL)) SAL_L2,
         MAX(DECODE(RN, 3, SAL)) SAL_L3,
         V_MARK
    FROM (SELECT D.DEPTNO,
                 D.DNAME,
                 E.SAL,
                 ROW_NUMBER() OVER(PARTITION BY E.DEPTNO ORDER BY E.SAL DESC) RN
            FROM EMP E, DEPT D
           WHERE E.DEPTNO = D.DEPTNO)
   GROUP BY DEPTNO;
COMMIT;
END;
BEGIN
  SP_SALES;
END;  

假設有100塊錢,打算買100只雞,公雞一隻5元,母雞一隻3元,小雞3只1元,
請問100塊錢剛好花完,每種雞至少買1只,每種雞各可以買多少隻?
通過存儲過程 ,打印出所有可能的組合。

參考答案:

 CREATE OR REPLACE PROCEDURE SP_J IS
  V_GJ NUMBER(2); V_MJ NUMBER(2); V_XJ NUMBER(2);
BEGIN
  FOR V_GJ IN 1 .. 20 LOOP 
   FOR V_MJ IN 1 .. 33 LOOP 
    FOR V_XJ IN 3 .. 100 LOOP 
      IF V_GJ + V_MJ + V_XJ = 100 /*數量*/
   AND V_GJ * 5 + V_MJ * 3 + V_XJ/3 = 100 /*價格*/
  THEN DBMS_OUTPUT.PUT_LINE(V_GJ || ' ' || V_MJ || ' ' || V_XJ);
END IF;
END LOOP;
END LOOP;
END LOOP;
END SP_J;
BEGIN
  SP_J;
END;

創建存儲過程,根據輸入的入職時間範圍,
打印出 在這個時間內 各地區工資前2名的員工的姓名,入職時間,工資

CREATE OR REPLACE PROCEDURE SP_D_EMP(P_1 VARCHAR2, 
                                     P_2 VARCHAR2)
                                     IS
  CURSOR C_EMP 
  IS
  SELECT * 
  FROM(SELECT D.LOC, 
  			  E.HIREDATE, 
  			  E.ENAME, 
  			  E.SAL, 
  	 DENSE_RANK() OVER(PARTITION BY D.LOC ORDER BY E.SAL DESC) RN     	    FROM EMP E, DEPT D 
    WHERE E.DEPTNO = D.DEPTNO 
    AND E.HIREDATE BETWEEN TO_DATE(P_1, 'YYYY-MM-DD') AND TO_DATE(P_2, 'YYYY-MM-DD')) X WHERE X.RN <= 2;

  V_CEMP C_EMP%ROWTYPE;
BEGIN
  FOR V_CEMP IN C_EMP LOOP 
  DBMS_OUTPUT.PUT_LINE(V_CEMP.LOC || ' ' || TO_CHAR(V_CEMP.HIREDATE, 'YYYY-MM-DD') || ' ' || V_CEMP.ENAME || ' ' || V_CEMP.SAL || ' ' || V_CEMP.RN);
END LOOP;
END;
BEGIN
  SP_D_EMP('1980-01-01', '1981-06-06');
END;

創建一個存儲過程,以員工號和部門號作爲參數,修改員工所在的部門爲所輸入的部門號。??
如果修改成功,則顯示“員工由……號部門調入調入……號部門”; – ① 原部門 新部門,
如果不存在該員工,則顯示?? – ② 判斷員工編號或者部門要輸入正確,否則就不會判斷 ① 條件
“員工號不存在,請輸入正確的員工號。”;
如果不存在該部門,則顯示??
“該部門不存在,請輸入正確的部門號。”。

CREATE OR REPLACE PROCEDURE SP_EMPNO_DEPT(P_EMPNO IN OUT NUMBER,
                                          P_DEPTNO IN NUMBER) 
                                          IS
  V_EMPNO NUMBER(4);
  V_DEPTNO1 NUMBER(2); 
  V_DEPTNO2 NUMBER(2); 
  V_CTEMPNO NUMBER(20); 
  V_CTDNO NUMBER(20);
BEGIN
  SELECT COUNT(1) 
  INTO V_CTEMPNO 
  FROM EMP 
  WHERE EMPNO = P_EMPNO; 
  IF V_CTEMPNO = 0 
  THEN DBMS_OUTPUT.PUT_LINE('員工號不存在,請輸入正確的員工號。'); 
  ELSE 
  SELECT COUNT(1) 
  INTO V_CTDNO 
  FROM DEPT 
  WHERE DEPTNO = P_DEPTNO; 
  IF V_CTDNO = 0 
  THEN DBMS_OUTPUT.PUT_LINE('該部門不存在,請輸入正確的部門號。'); 
  ELSE 
  SELECT DEPTNO 
  INTO V_DEPTNO1 
  FROM EMP 
  WHERE EMPNO = P_EMPNO;

  UPDATE EMP SET DEPTNO = P_DEPTNO WHERE EMPNO = P_EMPNO;

  SELECT DEPTNO /*,EMPNO*/
  INTO V_DEPTNO2 /*,V_EMPNO*/
  FROM EMP 
  WHERE EMPNO = P_EMPNO;
END IF;
END IF; 
DBMS_OUTPUT.PUT_LINE('員工' || P_EMPNO || '由' || V_DEPTNO1 || '號部門調入調入' || V_DEPTNO2 || '號部門');
END;

調用存儲過程

  DECLARE V_EMPNO NUMBER(4) := 7788;
BEGIN
  SP_EMPNO_DEPT(V_EMPNO, 40);
END;
  SELECT * FROM EMP WHERE EMPNO = 7788;
發佈了46 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章