IT/오라클

PL/SQL 기초

Beautifulkim 2018. 4. 11. 15:44

-- PL/SQL 기초


-- 행 여러번 입력 절차 ( 스크립트 )

/* 

    PL/SQL은 SQL에 없는 다음과 같은 기능이 제공

    

    - 변수 선언을 할 수 있습니다.

    - 비교 처리를 할 수 있습니다. 

    - 반복 처리를 할 수 있습니다. 

*/

/*

    스칼라

    PL/SOL에서 변수를 선언할 때 사용되는 자료형은 SQL에서 사용하던 자료형과 

    거의 유사하다. 숫자를 저장하려면 NUMBER를 사용하고 문자를 저장하려면 

    VARCHAR2를 사용해서 선언합니다. 


    레퍼런스

    이전에 선언된 다른 변수 또는 데이터베이스 컬럼에 맞추어 변수를 선언하기 위해 

    %TYPE속성을 사용할 수 있습니다. 

    그 변수나 컬럼과 같은 타입의 형을 쓰겠다.


*/


-- SCOTT 출력 절차

SET SERVEROUTPUT ON

DECLARE

    vename varchar2(10);

    VENAME VARCHAR(20);

BEGIN

    VENAME := 'SCOTT';

    DBMS_OUTPUT.PUT_LINE(VENAME);

END;


-- 7788번 사원명 출력 절차

SELECT ENAME 

FROM EMP

WHERE EMPNO=7788;


    -- 7788번 사원명 출력 절차 (출력형식 사원명 = XXX , 컬럼명 비노출)

DECLARE

    -- 컬럼 미참조 스칼라변수 선언

    VENAME VARCHAR(20);

    -- 컬럼 참조 레퍼런스(참조)변수 선언

    VENAME emp.ename%type;

BEGIN

    /* 

        INTO 절에는 반드시 컬럼이 와야함 

        (SELECT 컬럼명DMF INTO 다음에 있는 VENAME에 넣고 출력을 해야 함

    */

    SELECT ENAME INTO VENAME

    FROM EMP

    WHERE EMPNO=7788;

    DBMS_OUTPUT.PUT_LINE(' 사원명 = ' || VENAME);

END;

/*

    DECLARE - > 생략가능

    BEGIN

    END는 반드시 와야함

    

    DECLARE에 있으면 변수

    테이블에 선언되면 컬럼

*/

-- 프로그래밍에서 값, 양을 '스칼라'라고 칭함

-- 값을 가지는 것을 참조 : 레퍼런스



DECLARE

    -- 컬럼 참조 스칼라변수 선언

    VENAME EMP.ENAME%TYPE;

BEGIN

    SELECT ENAME INTO VENAME

    FROM EMP

    WHERE EMPNO=7788;

    DBMS_OUTPUT.PUT_LINE('사원명 = ' || VENAME);

END;

/*

PL/SQL의 SELECT 문으로 EMP 테이블에서 사원번호와 이름을 조회합시다. 


1. ED 다음에 파일이름을 입력하여 새로 생긴 SQL 파일에 

다음과 같이 입력하시오.(파일이름:EXAM02.sql)

*/



declare

    vempno emp.empno%type;

    vename emp.ename%type;    

begin

    dbms_output.put_line( ' 사번 / 이름' ); -- put_line : 출력 후 개행

    dbms_output.put_line( ' ------------- ' );

    

    select empno, ename into vempno, vename

    from emp

    where ename='SCOTT';

    dbms_output.put_line(vempno || ' / ' || vename);

end;


-------------- *( 모든 컬럼 )의 행 참조변수

DECLARE

    vemp EMP%ROWTYPE;

BEGIN

    dbms_output.put_line( ' 사번 / 이름' ); -- put_line : 출력 후 개행

    dbms_output.put_line( ' ------------- ' );

    

    SELECT * INTO vemp -- 모든 컬럼을 가지는 행의 입력

    FROM emp

    WHERE ename='SCOTT';

    -- 행 참조변수.컬럼

    dbms_output.put_line(vemp.empno || ' / ' || vemp.ename);

END;






SET SERVEROUTPUT ON

DECLARE

  -- 레코드 타입을 정의

  -- 하나의 레코드의 네가지의 변수타입 선언

    TYPE emp_record IS RECORD 

    (

        v_empno emp.empno%TYPE,

        v_ename emp.ename%TYPE,

        v_job emp.job%TYPE,

        v_deptno emp.deptno%TYPE 

    );

    -- 레코드로 변수 선언

    emp_rec emp_record;

BEGIN

  -- SCOTT 사원의 정보를 레코드 변수에 저장

    SELECT empno,ename, job, deptno

    INTO emp_rec

    FROM emp

    WHERE ename = UPPER('SCOTT');


  -- 레코드 변수에 저장된 사원 정보를 출력

  DBMS_OUTPUT.PUT_LINE('사원번호 : '    ||  TO_CHAR(emp_rec.v_empno));

  DBMS_OUTPUT.PUT_LINE('이      름 : '    ||  emp_rec.v_ename);

  DBMS_OUTPUT.PUT_LINE('담당업무 : '    ||  emp_rec.v_job);

  DBMS_OUTPUT.PUT_LINE('부서번호 : '    ||  TO_CHAR(emp_rec.v_deptno));

END;






/*

    1. 상품 테이블 생성 

    (

        상품번호 문자(4) 기본키,

        상품명 문자(20),

        판매수량 숫자,

        가격 숫자

    )

*/

desc product;

create table product

(

    p_idx char (4) primary key ,

    p_name varchar2 (20) ,

    p_sum number ,

    p_price number 

);

COMMENT ON column product.p_idx is '상품번호 형식 : p001 .. p999 ( 999개 )';   

-- 행 전체 삭제

delete from product;

drop table product;

/*

    조건

    상품번호 형식 : P001 .. P999 (999개)

*/



/*

    2. 상품번호는 자동증가컬럼으로 시퀀스가  입력

    조건 :1..999(999개)

*/

drop sequence product_p_idx_seq;

create sequence product_p_idx_seq

start with 1

maxvalue 999

increment by 1;


commit;

/*

    3. 임의의 4 개행  입력(상품번호 입력시 lpad() 적용)

    진라면, 신라면, 너구리, 비빔면

    (예) 

    insert into 상품

    values(concat('P',lpad(????),3,'0')),'진라면',5,100)

    p, 번호 1..999 -> 번호 왼쪽 자리는 0으로 채움

*/


insert into product values(concat('P', LPAD(to_char( product_p_idx_seq.nextval ), 3, '0' )), '진라면', 5, 100);

insert into product values(concat('P', LPAD(to_char( product_p_idx_seq.nextval ), 3, '0' ), '신라면', 10, 200);

insert into product values(concat('P', LPAD(to_char( product_p_idx_seq.nextval ), 3, '0' )), '너구리', 15, 300);

insert into product values(concat('P', LPAD(to_char( product_p_idx_seq.nextval ), 3, '0' )), '비빔면', 20, 400);

insert into product values(concat('P', LPAD(to_char( product_p_idx_seq.nextval ), 3, '0' )), '짜파게티', 25, 500);

insert into product values(concat('P', LPAD(to_char( product_p_idx_seq.nextval ), 3, '0' )), '짬뽕', 30, 600);


commit;


select * from PRODUCT;

-- 4. 현재 총매출액(각 상품의 판매수량 * 가격의 합)을 구하여 p_view 뷰로 정의

create or replace view p_view

as

select sum(p_sum * p_price) as "총매출액"

from product;

-- 여기서 별명을 지정해야함 안그러면 오류

룹 함수 SUM과 AVG를 사용해서 각 부서별 급여 총액과 평균을 구하는 뷰를 작성해 봅시다. 뷰를 작성하기 위해서 SELECT 절 다음에 SUM이란 그룹 함수를 사용하면 결과를 뷰의 특정 컬럼처럼 사용하는 것입니다. 따라서 물리적인 칼럼이 존재하지 않는 가상 칼럼이기에 칼럼 명도 상속 받을 수 없습니다. 뷰를 생성할 때 가상 칼럼을 사용하려면 사용자가 반드시 이름을 따로 설정해야 한다는 것을 명심하기 바랍니다. 

emample

CREATE VIEW VIEW_SAL

AS

SELECT DEPTNO, SUM(SAL) AS "SalSum", AVG(SAL) AS "SalAvg"

FROM EMP_COPY

GROUP BY DEPTNO;



-- 정의한 뷰를 축약시켜서 쿼리문 실행

select * from product_view;

select * from product_view2;


drop view product_view;



/*

5. 가장많이 팔린(판매수량 높은) 2개 상품의 상품명,판매수량을

뷰를 사용하여 출력(TOP 2)

*/

--인라인 뷰 : 인라인 뷰는 FROM 절에 사용되는 서브 쿼리를 의미한다. 

--[출처] [오라클/Oracle] 인라인뷰(inline view) / ROWNUM|작성자 JOKER

select ROWNUM, p_name, p_sum

from (select p_name, p_sum

from product

order by p_sum desc)

where rownum<=2;


-- 인라인뷰 재사용 : 수정될수도 있으므로 or replace 삽입

create or replace view view_qty

as

select p_name, p_sum

from product

order by p_sum desc;

--------------분리

select ROWNUM, p_name, p_sum

from view_qty

where rownum<=2;