데이터베이스

DATABASE STEP 31 - PL/SQL

2023. 3. 27. 21:34
728x90

★  PL/SQL

  • Oracle's Procedural Language Extension to SQL
  • ANSI-SQL 표준 SQL에 절차 지향 언어의 기능을 추가한 SQL
  • ANSI-SQL + 자바같은 프로그래밍 언어의 기능 = PL/SQL

 

★  ANSI-SQL

  • 비절차 지향 언어
  • 순서가 없고 문장간의 행동이 서로 독립적이다.
  • 문장 단위 구조 

 

★ 프로시저

  • 메소드, 함수 등...
  • 순서가 있는 명령어의 집합(ANSI-SQL + PL/SQL)의 집합
  • 1. 익명 프로시저
    • - 1회용 코드 작성용
  • 2. 실명 프로시저
    • 저장(데이터베이스) > DB object
    • 재사용 가능
    • 계정간 공유 가능
  • PL/SQL 프로시저 블럭 구조
    • 4개의 키워드(블럭)으로 구성
              a. declare
              b. begin
              c. exception
              d. end 
    • a. declare
              - 선언부
              - 프로시저 내에서 사용할 변수, 객체 등을 선언하는 영역
              - 생략 가능 
              
    •  b. begin
              - 실행부, 구현부
              - begin ~ end
              - begin(구현부 시작) ~ end(구현부 끝)
              - 생략 불가능
              - 핵심 파트
              - 구현 코드 > ANSI-SQL + PL/SQL
              
    • c. exception
              - 예외처리부
              - catch 역할
              - 예외 처리 코드를 작성
              - 생략 가능
              
    • d. end
              - begin 블럭의 종료 역할
              - 생략 불가능
  • 양식
declare
        변수 선언
        객체 선언
    begin 
        구현할 코드(SQL)
    exception
        예외처리 코드
end;
  • 변수 선언하기
    • 변수명 자료형 [not null] [default 값];
    • 주로 질의(select)의 결과값을 저장하는 용도
    • 일반적인 데이터를 저장하는 용도
  • 대입 연산자
        - ANSI-SQL
            ex) update table set column = 값;
        - PL/SQL 
            ex) 변수 := 값; 
  • PL/SQL 시작
set serveroutput on;
set serverout on;
  • PL/SQL 종료
set serveroutput off;
set serverout off;

 

■ 사용 ex)

  • 메소드 : 선언(저장) > 호출
  • 익명프로시저 : 호출
begin
    -- 자바의 System.out.println(); 과 같음
    dbms_output.put_line(100);
    dbms_output.put_line('홍길동');
end;

declare
    num number;
    name varchar2(30);
    today date;
begin
    num := 10;
    dbms_output.put_line(num);
    
    name := '홍길동';
    dbms_output.put_line(name);
    
    today := sysdate;
    dbms_output.put_line(today);
end;

 

■ select into 절 사용 ex)

  • PL/SQL의 변수에 ANSI-SQL의 결과값을 저장하는 구문
  • into 주의점
    • 1. 컬럼의 개수와 변수의 개수의 동일!!
    • 2. 값을 동일 하게 넣지 않으면 , 해당 에러 발생 : PL/SQL: ORA-00947: not enough values
    • 3. 컬럼 갯수를 동일하게 넣지 않으면, 해당 에러 발생 : PL/SQL: ORA-00913: too many values
    • 4. 컬럼의 순서와 변수의 순서가 일치!!
    • 5. 컬럼과 변수의 자료형이 일치!!
declare

    vname varchar2(30);
    buseo varchar2(30);

begin
	-- vname := select name from tblInsa where num = 1001;
    
    -- PLS-00428: an INTO clause is expected in this SELECT statement
    -- ***** PL/SQL 블럭안에서는 ANSI-SQL의 select문을 사용할 수 없다. > Select into 사용 
    -- ***** PL/SQL 블럭안에서는 select문을 제외한 ANSI-SQL은 그대로 사용 가능하다.(Insert,Update,delete)
    
    -- 대입 연산자 역할 
    -- select 컬럼 into 변수 
    select name into vname from tblInsa where num = 1001;
    dbms_output.put_line(vname);
    
    --      컬럼         변수
    select buseo into buseo from tblInsa where num = 1001;
    dbms_output.put_line(buseo);
    
end;
  • ex2) 회사 > 프로젝트 > 직원 중
create table tblTeam (
    num number primary key,
    name varchar2(15) not null,
    buseo varchar2(15) not null,
    jikwi varchar2(15) not null
);

-- 개발부 + 부장
-- 1. ANSI-SQL
-- 2. PL/SQL

-- 1.1 노가다 > 비추천 
select * from tblInsa where buseo = '개발부' and jikwi = '부장';
insert into tblTeam values (1003, '이순애', '개발부', '부장');

-- 1.2 서브쿼리
insert into tblTeam values ((select num from tblInsa where buseo = '개발부' and jikwi = '부장'), 
                                  (select name from tblInsa where buseo = '개발부' and jikwi = '부장'), 
                                  '개발부', '부장');
-- 2. PL/SQL 사용
declare
    vnum number;
    vname varchar2(15);
    vbuseo varchar2(15);
    vjikwi varchar2(15);
begin
    
    -- ***** Select의 결과는 반드시 PL/SQL에 넣어야 한다. > select into 사용
    select num into vnum from tblInsa where buseo = '개발부' and jikwi = '부장';
    select name into vname from tblInsa where buseo = '개발부' and jikwi = '부장';
    select buseo into vbuseo from tblInsa where buseo = '개발부' and jikwi = '부장';
    select jikwi into vjikwi from tblInsa where buseo = '개발부' and jikwi = '부장';
    
    -- vnum, vname, vbuseo, vjikwi 확보
    insert into tblTeam values (vnum, vname, vbuseo, vjikwi);
    
end;

 

■ 타입 참조 ex)

  • 변수를 선언할 때 같이 사용
  • 1. %type
            - 컬럼 1개 참조 
            - 사용하는 테이블의 특정 컬럼의 스키마를 알아내서 변수에 적용
            - 복사되는 정보
                a. 자료형
                b. 길이
  • 2. %rowtype
            - 레코드 전체 참조(모든 컬럼 참조)
            - 와일드 카드의 성질
  • 1. %type ex)
declare
    vname tblInsa.name%type;
    vbuseo tblInsa.buseo%type;
    vjikwi tblInsa.jikwi%type;
begin
    select name, buseo, jikwi into vname, vbuseo, vjikwi from tblInsa where num = 1002;
    
    dbms_output.put_line(vname);
    dbms_output.put_line(vbuseo);
    dbms_output.put_line(vjikwi);
end;

select * from tblTeam;

-- 특정 직원에게 보너스 지급 > 내역 저장
-- 보너스 = basicpay * 1.5

create table tblBonus (
    seq number primary key,
    num number(5) not null references tblInsa(num),
    bonus number not null
);

create sequence seqBonus;

-- 1.
select * from tblInsa where buseo ='총무부' and jikwi = '부장';
insert into tblBonus values (seqBonus.nextVal, 1046, 2650000*1.5);

-- 2.
insert into tblBonus values (seqBonus.nextVal, 
                                    (select num from tblInsa where buseo ='총무부' and jikwi = '부장'), 
                                    (select basicpay from tblInsa where buseo ='총무부' and jikwi = '부장') * 1.5);

select * from tblBonus;

-- 3.
declare
    vnum        tblInsa.num%type;
    vbasicpay   tblInsa.basicpay%type;
begin
    select num, basicpay into vnum, vbasicpay from tblInsa where buseo ='총무부' and jikwi = '부장';
    
    insert into tblBonus values (seqBonus.nextval, vnum, vbasicpay * 1.5);
    

    
end;

select * from tblBonus;
  • 2. %rowtype
  • ex)
declare 
    vnum        tblInsa.num%type;
    vname       tblInsa.name%type;
    vbuseo      tblInsa.buseo%type;
    vjikwi         tblInsa.jikwi%type;
    vssn          tblInsa.ssn%type;
    vcity          tblInsa.city%type;
    vbasicpay    tblInsa.basicpay%type;
    vsudang      tblInsa.sudang%type;
    vibsadate     tblInsa.ibsadate%type;
    vtel            tblInsa.tel%type;

begin
    select num, name, buseo, jikwi, ssn, city, basicpay, sudang, ibsadate, tel
            into vnum, vname, vbuseo, vjikwi, vssn, vcity, vbasicpay, vsudang, vibsadate, vtel
        from tblInsa where name = '홍길동';
end;

-- 좋은 예
declare 
    vrow tblInsa%rowtype; --총 10개의 컬럼 참조
    vrow2 tblInsa%rowtype; --총 10개의 컬럼 참조
begin
    
    -- ex) 덜 좋은 예
    select 
        num, name, ssn, ibsadate, city, tel, buseo, jikwi, basicpay, sudang
        into vrow
    from tblInsa where name = '이순신';
    
    -- ex) 가장 좋은 예
    select 
        * into vrow2
    from tblInsa where name = '이순애';
    
    --dbms_output.put_line(vrow);
    dbms_output.put_line(vrow.name);
    dbms_output.put_line(vrow2.name);
    
end;
  • '하하하' > 성전환 > tblWomen 이동
    • 1. tblMen > select > 정보
    • 2. tblWomen > insert(1번) > 복사
    • 3. tblMen > delete
  • ex)
declare
    vrow tblMen%rowtype;
begin
    --1.
    select * into vrow from tblMen where name = '하하하';
    
    --2. 
    insert into tblWomen values(vrow.name, vrow.age, vrow.height, vrow.weight, vrow.couple);
    
    --3.
    delete from tblMen where name = '하하하';
    
end;

select * from tblMen;
select * from tblWomen;

 

■ 제어문

  • 1. 조건문
  • if 문 ex)
declare
    vnum number := 10;
begin
    
    if (vnum > 0) then 
        dbms_output.put_line('양수');
    end if;
    
end;

declare
    vnum number := -10;
begin
    
    if (vnum > 0) then 
        dbms_output.put_line('양수');
    elsif vnum < 0 then
        dbms_output.put_line('음수');
    else
        --dbms_output.put_line('양수 아님');
        null; -- 빈블럭 만들 때 사용
    end if;
    
end;

-- 특정 직원 선택 > 보너스 지급 > 간부(basicpay * 1.5), 대리,사원(baiscpay * 2)
declare
    vnum        tblInsa.num%type;
    vbasicpay   tblInsa.basicpay%type;
    vjikwi        tblInsa.jikwi%type;
    vbonus      number;
begin
    --1.
    select num, basicpay, jikwi into vnum, vbasicpay, vjikwi from tblInsa where name = '이순신';
    
    --2.
    if vjikwi = '부장' or vjikwi = '과장' then
        vbonus := vbasicpay * 1.5;
    elsif vjikwi in ('대리','사원') then
        vbonus := vbasicpay * 2;
    end if;
    
    --3.
    insert into tblBonus values (seqBonus.nextVal, vnum, vbonus);
    
end;
  • if문 ex2)
declare
    vcontinent tblCountry.continent%type;
    vresult varchar2(30);
begin
    select continent into vcontinent from tblCountry where name = '대한민국';

    if vcontinent = 'AS' then
        vresult := '아시아';
    elsif vcontinent = 'EU' then
        vresult := '유럽';
    elsif vcontinent = 'AF' then
        vresult := '아프리카';
    else
        vresult := '기타';
end if;
    
    dbms_output.put_line(vresult);
  • case문 ex1)
case
        when vcontinent = 'AS' then vresult := '아시아';
        when vcontinent = 'EU' then vresult := '유럽';
        when vcontinent = 'AF' then vresult := '아프리카';
        else vresult := '기타';
end case;
    
    dbms_output.put_line(vresult);
    
case vcontinent
        when 'AS' then vresult := '아시아';
        when 'EU' then vresult := '유럽';
        when 'AF' then vresult := '아프리카';
        else vresult := '기타';
end case;

 

■ 반복문

  • 1. loop 문
    • 단순 반복
  • 2. for loop
    • 횟수 반복
    • loop 기반
  • 3. while loop
    • 조건 반복
    • loop 기반
  • 1. loop 문 ex)
loop
        -- 실행문;
        dbms_output.put_line(to_char(sysdate, 'hh24:mi:ss'));
        dbms_output.put_line(vnum);
        
        vnum := vnum+1;
        
        exit when vnum > 10; -- 조건 만족 > loop 탈출
        
    end loop;

end;
  • 1. loop 문 ex2) 더미데이터 생성
-- 더미 데이터 추가 x 1000 건
create table tblLoop (
    seq number primary key,
    data varchar2(30) not null
);

create sequence seqLoop;

insert into tblLoop values (seqLoop.nextVal, '데이터1');
insert into tblLoop values (seqLoop.nextVal, '데이터2');
insert into tblLoop values (seqLoop.nextVal, '데이터3');

declare
    vnum number := 4;
begin
    
    loop
        insert into tblLoop values (seqLoop.nextVal, '데이터' || vnum);
        vnum := vnum +1;
        
        exit when vnum > 1000;
        
    end loop;
    
end;

select * from tblLoop;
select count(*) from tblLoop;
  • 2. for loop ex)
begin
    
    for i in 1..10 loop
        
        dbms_output.put_line(i);
        
    end loop;

end;
  • 2. for loop ex2) 구구단 만들기
create table tblGugudan (
    dan number,
    num number,
    result number not null,
    
    constraint tblgugudan_dan_num_pk primary key(dan,num)
);

begin
    for dan in 2..9 loop
        for num in 1..9 loop
            insert into tblGugudan (dan, num, result) values (dan, num, dan*num);
        end loop;
    end loop;

end;

select * from tblGugudan;
  • 3. while loop ex)
declare
    vnum number := 1;
begin
    while vnum <= 10 loop
    
        dbms_output.put_line(vnum);
        vnum := vnum +1;
    
    end loop;
end;

 

■ cursor + loop

  • 결과셋의 레코드가 N개일때 사용한다.
  • 사용양식
사용양식
    
    declare
        변수 선언;
        커서 선언;
    begin
        
        커서 열기;
            loop
                커서 사용 > 데이터 접근 > 조작        
            end loop;
        커서 닫기;
        
    end;
  • ex)
declare
    cursor vcursor 
    is 
    select name from tblInsa;
    vname tblInsa.name%type;
begin
    open vcursor; -- select문 실행 > 결과셋에 커서 연결(참조) > 탐색 > 자바의 Iterator
  • ex2) 주로 사용하는 cursor 문
declare
    cursor vcursor is select name from tblInsa;
    vname tblInsa.name%type;
begin
    open vcursor; 
        
        loop
            fetch vcursor into vname;
            exit when vcursor%notfound; 
            dbms_output.put_line(vname);
        end loop;
        
    close vcursor;
    
end;

 

728x90
저작자표시 비영리 변경금지 (새창열림)

'데이터베이스' 카테고리의 다른 글

DATABASE STEP 33 - STORED FUNCTION  (0) 2023.03.29
DATABASE STEP 32 - PROCEDURE  (0) 2023.03.28
DATABASE SEMI PROJECT - MOVIE RANK DATA  (0) 2023.03.24
DATABASE STEP 30 - Modeling  (0) 2023.03.23
DATABASE STEP 29 - Transaction  (0) 2023.03.23
'데이터베이스' 카테고리의 다른 글
  • DATABASE STEP 33 - STORED FUNCTION
  • DATABASE STEP 32 - PROCEDURE
  • DATABASE SEMI PROJECT - MOVIE RANK DATA
  • DATABASE STEP 30 - Modeling
IT의 큰손
IT의 큰손
IT계의 큰손이 되고 싶은 개린이의 Log 일지
Developer Story HouseIT계의 큰손이 되고 싶은 개린이의 Log 일지
IT의 큰손
Developer Story House
IT의 큰손
전체
오늘
어제
  • 분류 전체보기 (457)
    • 정보처리기사 필기 (18)
    • 정보처리기사 실기 (12)
    • 정보처리기사 통합 QUIZ (12)
    • 빅데이터 (11)
    • 안드로이드 (11)
    • 웹페이지 (108)
    • 자바 (49)
    • SQLD (3)
    • 백준 알고리즘 (76)
    • 데이터베이스 (41)
    • 깃허브 (2)
    • Library (14)
    • Server (31)
    • 크롤링&스크래핑 (3)
    • Spring (23)
    • Vue.js (13)
    • React (27)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • Developer Stroy House

인기 글

태그

  • 정보처리기사필기
  • IT자격증공부
  • 개발자
  • 데이터베이스
  • 프론트엔드
  • it
  • 정보처리기사
  • java
  • ajax
  • 백준
  • DB
  • 웹개발자
  • 알고리즘
  • 개발블로그
  • React
  • 웹개발
  • 정보보안전문가
  • css
  • 코딩테스트
  • jsp
  • JavaScript
  • html
  • DBA
  • IT개발자
  • jquery
  • 앱개발자
  • 웹페이지
  • IT자격증
  • 백엔드
  • 자바

최근 댓글

최근 글

Designed By hELLO
IT의 큰손
DATABASE STEP 31 - PL/SQL
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.