개발/대덕인재개발원

대덕240930- 자바:중첩 클래스 / DB: 반복문,프로시저

월은 2024. 9. 30. 17:37

<자바> 

중첩 클래스 

서로 긴밀하게 연결되어 상호작용하는  클래스라면 애초에 서로 합쳐놓으면 되지 않을까? 라는 생각에서 만들어진 클래스.

내부 클래스와 외부 클래스로 중첩되어지며 이러한 중첩의 원리는 인터페이스에도 적용된다. 

- 클래스 내부에 선언한 클래스

- 두 클래스의 멤버들을 서로 쉽게 접근(내부 클래스에서 바깥쪽 클래스의 변수에 직접 접근 가능)하게 하고, 불필요한 관계 클래스 감춤

- 코드 복잡성 줄임

 

중첩 인터페이스 

-

- 인터페이스 역시 클래스 내부에 선언 가능

- 해당 클래스와 긴밀한 관계 갖는 구현 클래스 만들기 위함

 

멤버 클래스 

- 클래스의 멤버로서 선언되는 중첩 클래스

 

로컬 클래스

- 메소드 내부에서 선언되는 중첩 클래스

- 메소드 실행될 때만 사용되고 메소드 종료되면 사라짐

- 인스턴스 변수는 객체가 생성해야지만 쓸 수 있듯이 인스턴스 멤버 클래스도 바깥쪽의 객체를 생성해야 사용될 수 있다

- static 붙이면 정적 메소드 안에 만들어지면 정적, 이것은 기존 정적의 특성을 그대로 가져와 클래스 이름만 가지고도 접근하여 사용 가능

- 로컬 클래스는 메소드가 호출되어 실행되어야만 사용 가능하다

 

중첩 클래스를 컴파일하면 바이트코드 파일(.class)이 별도로 생성 

중첩클래스는 아니지만 예시:파일은 하나지만 클래스는 여러개!

멤버 클래스의 경우

로컬 클래스의 경우

 

인스턴스 멤버 클래스 

- static 키워드 없이 중첩 선언된 클래스

- 인스턴스 필드와 메소드만 선언 가능하고 정적 필드와 메서드는 선언 불가, 왜? 스태틱은 객체 생성 없이 사용 가능한데 인스턴스는

   객체 생성  없이도 사용 가능하여 위 예제의 클래스B를 인식하지 못한다.  

A클래스의 외부에서 B객체 생성하려면 먼저 A객체 생성 후 B객체 생성이 필요하다

 

정적 멤버 클래스 

- static 키워드로 선언된 클래스

- A클래스 외부에서 정적 멤버 클래스 C객체를 생성할 경우 A객체 생성이 필요하지 않다

 

로컬 클래스 

- 메서드 내부에 만들어진 클래스 (접근 제한자 및 static 붙일 수 없음)

- 인스턴스 필드와 메서드만 사용가능

 

로컬 클래스에서의 사용제한 

- 로컬 클래스는 메서드 호출이 끝나게 되면 사라지는 것이 기본인데 추후 배울 스레드의 경우를 제외하고는 자동으로 사라진다

- 매개 변수/로컬 변수들은 final 키워드로 선언해야 한다(자바 8 버전 이후부터는 final을 선언하지 않아도 컴파일러가 알아서 특성을 부여)

 

중첩 클래스에서 바깥 클래스 참조 얻기 

- 바깥 클래스의 이름을 this 앞에 붙임

 

익명 객체 

- 이름이 없는 객체

- 어떤 클래스를 상속하거나 인터페이스를 구현해야 함

 

<DB> 

반복문 

반복문
- 오라클 반복문은 loop, while, for 문이 제공됨

1.LOOP문 
 - 반복문의 기본 구조를 제공하는 반복문
 - 무한 루프의 기능을 제공함
 (사용형식)
 LOOP
    반복처리 명령문(들);
    [EXIT WHEN 조건문;]
    [반복처리 명령문(들);
          :
   END LOOP;      
   
사용예) 구구단의 7단을 출력하는 블록을 작성하시오
 DECLARE
  V_CNT NUMBER:=1;
 BEGIN
   LOOP
     EXIT WHEN V_CNT>9;
     DBMS_OUTPUT.PUT_LINE('7 * '||V_CNT||' = '||V_CNT *7);
     V_CNT:=V_CNT+1;
   END LOOP;
 END;
 
 사용예) 키보드로 월을 입력받아 해당월에 판매된 상품의 상품코드,판매수량합계를 조회하는
       익명블록을 작성하시오 
 ACCEPT P_MONTH PROMPT '월 입력(01 ~ 12) : ' 
 DECLARE
  V_SDATE VARCHAR2(7):='2020'||TRIM('&P_MONTH')||'%';
  --V_EDATE VARCHAR2(8):=TO_CHAR(LAST_DAY(TO_DATE(V_SDATE)),'YYYYMMDD');
  --&: 엔퍼센트 ==> 변수 내에 있는 값을 참조한다
  -- TRIM: 컴퓨터의 비트 읽는 체계로 인해 혹시 발생할지 모르는 '공백 제거'
  V_PID MJY.PROD.PROD_ID%TYPE;
  V_SUM NUMBER:=0;
  
  CURSOR CUR_CART02 IS 
    SELECT PROD_ID, 
           SUM(CART_QTY)
    FROM MJY.CART
    WHERE CART_NO LIKE V_SDATE
    GROUP BY PROD_ID;
 BEGIN
   OPEN CUR_CART02;
   LOOP
    FETCH CUR_CART02 INTO V_PID,V_SUM;
    EXIT WHEN CUR_CART02%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(V_PID||'  '||TO_CHAR(V_SUM,'9,999'));
    DBMS_OUTPUT.PUT_LINE('-----------------------------------');
   END LOOP;
   
   EXCEPTION WHEN OTHERS THEN
     DBMS_OUTPUT.PUT_LINE('오류발생' ||SQLERRM);
     
     CLOSE CUR_CART02;
 END;
 
 2. WHILE문
  . 개발언어의 WHILE문과 동일 기능 제공
  (사용형식)
   WHILE 조건 LOOP 
     반복처리 명령문(들);
          :
   END LOOP;
   - '조건'의 평과 결과가 참이면(true) 반복 실행
   - '조건'의 평과 결과가 거짓이면(false) 반복 종료
   
사용얘)구구단의 7단을 WHILE 문으로 출력하시오

DECLARE
    V_CNT NUMBER:=0;
BEGIN
    WHILE (V_CNT<9) LOOP
    V_CNT:=V_CNT+1;
    DBMS_OUTPUT.PUT_LINE('7 * '||V_CNT' = '||V_CNT*7);
    END LOOP;
END;
   
사용예) 키보드로 월을 입력받아 해당월에 판매된 상품의 상품코드,판매수량합계를 조회하는
      익명블록을 작성하시오 
ACCEPT P_MONTH PROMPT '월 입력(01 ~ 12) : ' 
 DECLARE
  V_PERIOD VARCHAR2(7):='2020'||TRIM('&P_MONTH')||'%';
  
  V_PID MJY.PROD.PROD_ID%TYPE;
  V_SUM NUMBER:=0;
  
  CURSOR CUR_CART02 IS 
    SELECT PROD_ID, 
           SUM(CART_QTY)
    FROM MJY.CART
    WHERE CART_NO LIKE V_PERIOD
    GROUP BY PROD_ID;
 BEGIN
   OPEN CUR_CART02;
   FETCH CUR_CART02 INTO V_PID,V_SUM;
   WHILE CUR_CART02%FOUND LOOP
    DBMS_OUTPUT.PUT_LINE(V_PID||'  '||TO_CHAR(V_SUM,'9,999'));
    DBMS_OUTPUT.PUT_LINE('-----------------------------------');
    FETCH CUR_CART02 INTO V_PID,V_SUM;
   END LOOP;
   
   EXCEPTION WHEN OTHERS THEN
     DBMS_OUTPUT.PUT_LINE('오류발생' ||SQLERRM);
     
     CLOSE CUR_CART02;
 END;
 
 3.일반 FOR 문
 . 개발언어의 FOR문과 동일 기능 제공
 (사용형식)
  FOR 제어변수 IN[REVERSE] 값1..값2 LOOP
   반복처리 명령문(들);
         :
  END LOOP;
  - 제어변수에 '값1'을 할당하고 '값2'와 비교하여 범위안의 값ㅇ이면(즉, 제어변수의 값<='값2')
    반복수행
  - 반복수행 후 다시 제어가 FOR문으로 이동하여 제어변수 값을  1(또는-1)증가 시킨 후
    위 과정을 반복 수행 
      
사용예)구구단의 7단을 출력
DECLARE
BEGIN
    FOR CNT IN REVERSE 1..9 LOOP
      DBMS_OUTPUT.PUT_LINE('7 * '||CNT||' = '||'7*CNT');
    END LOOP;
END;
      
      
 (커서용사용형식)
  FOR 레코드 커서명|인라인서브쿼리 LOOP
   반복처리 명령문(들);
         :
  END LOOP;  
  .레코드명은 시스템에서 제공하며 커서의 맨 첫번째 행부터 마지막
   행까지 차례대로 지칭함 
  .커서이름 대신 커서를 구성하는 SELECT문이 서브쿼리로 올 수 있음
  .FOR문을 사용하면 OPEN,FETCH,CLOSE문은 생략됨
  .커서 내의 컬럼명은 '레코드명.컬럼명'으로 참조됨 
  -- 레코드명: 커서(테이블)에 있는 한 행에 붙여진 이름
  -- 인라인 서브쿼리로 SELECT 바로 집어넣기
  
  사용예) 키보드로 월을 입력받아 해당월에 판매된 상품의 상품코드,판매수량합계를 조회하는
      익명블록을 작성하시오 
      
ACCEPT P_MONTH PROMPT '월 입력(01 ~ 12) : ' 
 DECLARE
  V_PERIOD VARCHAR2(7):='2020'||TRIM('&P_MONTH')||'%';
  CURSOR CUR_CART02 IS 
    SELECT PROD_ID, SUM(CART_QTY) AS CSUM
    FROM MJY.CART
    WHERE CART_NO LIKE V_PERIOD
    GROUP BY PROD_ID;
 BEGIN
    FOR REC IN CUR_CART02 LOOP
    DBMS_OUTPUT.PUT_LINE(REC.PROD_ID||'  '||TO_CHAR(REC.CSUM,'9,999'));
    END LOOP;
 END;
   
   
SUB QUERRY 사용)   
ACCEPT P_MONTH PROMPT '월 입력(01 ~ 12) : ' 
 DECLARE
  V_PERIOD VARCHAR2(7):='2020'||TRIM('&P_MONTH')||'%';
 BEGIN
    FOR REC IN ( SELECT PROD_ID, SUM(CART_QTY) AS CSUM
                 FROM MJY.CART
                 WHERE CART_NO LIKE V_PERIOD
                 GROUP BY PROD_ID )
    LOOP
    DBMS_OUTPUT.PUT_LINE(REC.PROD_ID||'  '||TO_CHAR(REC.CSUM,'9,999'));
    END LOOP;
 END;
 -- 직접 for문 안에서 커서를 만들어서 쓸 수도 있다

 

저장 프로시저 

저장 프로시저(STORED PROCEDURE : PROCEDURE)
 - 미리 작성된 프로그램을 컴파일하여 내부 캐시에 실행 가능한 형태의 파일로 보관=>처리속도 증가
 - 클라이언트 간에 처리루틴 공유 가능 => 모든 응용프로그램에서 사용 가능하도록 캡슐화=>
   일관성과 데이터 무결성 보장
 - 데이터베이스 보안 강화 
 - 프로시저는다 반환 값이 없음
 - 반복문의 기본은 루프,엔드루프이듯 프로시저의 기본은 익명 블록이
(구문 생성 사용형식)
 CREATE [OR REPLACE] PROCEDURE 프로시저명[(
   변수명 [IN|OUT|INOUT] 데이터 타입[,] --생략하면 기보값은 'IN;;
            :
   변수명 [IN|OUT|INOUT] 데이터 타입)]
   IS | AS
    선언영역
   BEGIN
    실행영역 
   END;
 
 (생성 구문 사용형식)
  EXECUTE|EXEC 프로시저명[(변수list)];
 OR
  OUT 매개변수가 사용된 프로시저는 반드시 블록 내에서 실행시켜야 하고'EXECUTE|EXEC'는 생략함  
  
  프로시저명[(변수list)];

사용예) 부서번호를 입력 받아 부서번호,부서명,관리사원이름을 출력하는 프로시저 작성
 CREATE OR REPLACE PROCEDURE proc_dept_info(
  P_DEPT_ID IN HR.DEPARTMENTS.DEPARTMENT_ID%TYPE)
 IS
   P_DEPT_NAME VARCHAR2(100);
   P_MANAGER VARCHAR2(50);
 BEGIN
   SELECT A.DEPARTMENT_NAME, B.EMP_NAME
     INTO P_DEPT_NAME, P_MANAGER
     FROM HR.DEPARTMENTS A, HR.EMPLOYEES B 
    WHERE A.DEPARTMENT_ID = P_DEPT_ID
      AND A.MANAGER_ID=B.EMPLOYEE_ID;
  -- 자료출력
  DBMS_OUTPUT.PUT_LINE('부서번호 : '||P_DEPT_ID);
  DBMS_OUTPUT.PUT_LINE('부서명 : '||P_DEPT_NAME);
  DBMS_OUTPUT.PUT_LINE('관리사원명 : '||P_MANAGER);
  
 END;
 
 EXECUTE proc_dept_info(60);