2011년 7월 28일 목요일

[Oracle. 12]PL/SQL (Procedural Language / Structured Query Language)

PL/SQL ( Procedural Language / Structured Query Language )
선언적인 SQL 언어와는 달리 SQL을 절차적인 방식에 의해 사용하도록 설계된 언어이다.
1. PL/SQL
DECLARE (선언)
BEGIN (실행)
EXCEPTION (예외 처리)
END;
 - DECLARE (선언) : 실행문에 사용될 변수나 커서, 사용자 정의 예외 등을 정의한다.
 - BEGIN (실행) : 질의문(SELECT)  DML문 그리고 조건이나 제어문을 사용할 수 있다.
 - EXCEPTION (예외처리) : 실행시 발생 가능한 예외를 정의한다.
1) PL/SQL 실행 절차
1. 개발 환경에서 작성
2. COMPILE                 
3. Debugging -> 1 -> 2 -> 3
4. 실행
2. Stored Procedure
SQL의 경우 Shared Pool에 같은 실행 계획이 있는지 확인하고 있다면, 해당 실행 계획을 실행한다. 따라서 수행한 SQL문을 가능한 Shared Pool에 두고 사용한다면 좋은 성능을 기대할 수 있다.
반면 Stored Procedure의 경우 한번 생성이 되면 데이터베이스 서버에 저장이 된다. 그리고 이후 다시 사용할 때에는 이미 Compile 과정을 거쳤기 때문에 실행만으로 결과를 얻을 수 있다.
, 다시 Compile을 하지 않고, 클라이언트 서버간 전송되는 크기가 상대적으로 복잡하고 긴SQL문 보다 작다. 이는 Network 전송량을 줄일 수 있는 장점이 있다.
1) Stored Procedure 작성
예문 ) 사원번호를 입력받아 해당 직무의 최소/최대 급여를 얻고, 급여의 분포에 따라 최대 급여에서 최소 급여의 차가 5,000 이하일 때는 LOW, 5,000 ~ 10,000 일때는 MIDDLE 10,000을 초과할 때는 HIGH로 표시한다.
1-1) 실행문의 주된 내용은 SQL이기 때문에 먼저 질의문을 통해 위 결과를 확인할 수 있는 SQL문을 작성한다.
SQL> SELECT employee_id, last_name, job_title, min_salary, max_salary
     FROM employees e JOIN jobs j
     ON e.job_id = j.job_id
     AND employee_id = 205;
1-2) 여기에 최소/최대 급여의 차이에 따른 등급을 나타내기 위해 CASE문을 SQL문에 적용할 수 있다.
SQL> SELECT employee_id, last_name, job_title, min_salary, max_salary,
     CASE WHEN max_salary – min_salary < 5000 THEN ‘low’
             WHEN max_salary – min_salary < 10000 THEN ‘middle’
     ELSE ‘high’
     END CASE
     FROM employees e JOIN jobs j
     ON e.job_id = j.job_id
     AND employee_id = 205;
1-3) 실행 결과를 확인 하였다면 Stored Procedure를 작성하여 보자. Parameter Variable로 사원번호를 입력받아 BEGIN ~ END에 위질의문을 넣고 로컬 변수를 선언하여 결과를 처리한다.
SQL> CREATE OR REPLACE PROCEDURE rank_Salaryofjob
(p_empid    employees.employee_id%TYPE := 0)
      IS
            l_last_name    employees.last_name%TYPE := NULL;
            l_min_salary    jobs.min_salary%TYPE := 0;
            l_max_salary    jobs.max_salary%TYPE := 0;
            l_rank         VARCHAR2(10);
      BEGIN
SELECT employee_id, last_name, job_title, min_salary, max_salary,
                  CASE WHEN max_salary – min_salary < 5000 THEN ‘low’
                     WHEN max_salary – min_salary < 10000 THEN ‘middle’
                  ELSE ‘high’
           END CASE
             FROM employees e JOIN jobs j
             ON e.job_id = j.job_id
   AND employee_id = 205;
   DBMS_OUTPUT.PUT_LINE(l_last_name||’ ‘||l_min_salary||’ ‘||l_max_salary||’ ‘||l_rank);
     END rank_salaryofjob;
3. CURSOR
질의 수행 결과 반환되는 여러 행을 처리할 수 있도록 명시적 커서를 이용하고 있다. oracle에서 커서란 질의의 결과 얻어진 여러 행이 저장된 메모리 상의 위치를 나타낸다. , PL/SQL에 내장된 일종의 포인트이며, 결과 SET의 행들을 하나씩 얻어 오는 작업에 이용된다.
1) 문법
DECLARE
 -- 커서의 선언
 CURSOR 커서이름 IS SELECT 구문;
BEGIN
 -- 커서 열기
 OPEN 커서이름;
 -- 커서로부터 데이터 읽기
 FETCH 커서이름 INTO 로컬변수;
 -- 커서 닫기
 CLOSE 커서이름;
END;
2) 예문
SQL> CREATE OR REPLACE PROCEDURE info_Hiredate (p_year   IN CHAR := 0)
      IS
         l_emp    employees%ROWTYPE;
         -- 커서의 선언
         -- CURSOR cursor_name IS SELECT statement;
         CURSOR emp_cur IS
            SELECT employee_id, last_name, salary
               FROM employees
               WHERE TO_CHAR(hire_date, ‘YYYY’) = p_year;
      BEGIN
             -- 커서 열기
             -- OPEN cursor_name;
             OPEN emp_cur;
             -- 커서로부터 데이터 일기
             -- FETCH cursor_name INTO local variables;
             LOOP
                FETCH emp_cur INTO l_emp.employee_id, l_emp.last_name, l_emp.salary;
                EXIT WHEN emp_cur%NOTFOUND;
               
                DBMS_OUTPUT.PUT_LINE(l_emp.employee_id || ‘ ‘ || l_emp.last_name || ‘ ‘ || l_emp.salary);
             END LOOP;      
             --커서 닫기
             --CLOSE cursor_name;
             CLOSE emp_cur;
      END info_Hiredate;
3) CURSOR 속성
- %FOUND : PL/SQL 코드가 마지막으로 얻은 커서의 결과 SET에 레코드가 있다면 참
- %NOTFOUND : %FOUND 연산자와 반대의 의미
- %ROWCOUNT : 커서에서 얻은 레코드의 수를 반환
- %ISOPEN : 커서가 열렸고, 아직 닫히지 않은 상태라면 참
4. EXCEPTION
1) 문법
DECLARE
-- 예외선언
-- 예외 이름 EXCEPTION;
BEGIN
-- 예외 발생
-- RAISE 예외 이름;
EXCEPTION
-- 예외 처리
-- WHEN 예외 이름 THEN
--                 구문;
END;
2) Oracle에서 제공하는 예외
 - NO_DATA_FOUND : SELECT INTO 구문 실행 후 반환되는 행이 없는 경우
 - TOO_MANY_ROWS : SELECT INTO 구문이 하나 이상의 행을 반환하는 경우
 - VALUE_ERROR : 데이터의 변환 과정에서 오류나 선언된 변수가 데이터의 저장하기에 크기가 작은 경우
 - NOT_LOGED_ON : Oracle에 접속하지 않은 채 데이터베이스를 Call하는 경우
 - INVALID_CURSOR : Cursor의 동작이 부적절한 경우
 - CURSOR_ALREADY_OPEN : 이미 열려있는 Cursor가 열려고 하는 경우
 - DUP_VAL_ON_INDEX : Unique Index가 설정된 칼럼에 중복된 값을 입력하는 경우
*** 참조 문헌 : 10g로 시작하는 오라클 SQL & PL/SQL - 7장 SQL의 한계를 넘어 PL/SQL

2011년 7월 20일 수요일

[Oracle.11]Database Object - View

Database Object
데이터베이스는 테이블뿐만 아니라 데이터를 저장하고 이를 활용하는 다양한 Object 를 제공하고 있다.
3. View
여러 테이블을 JOIN하여 질의할 때, JOIN하는 테이블의 수가 늘어나면 질의문의 길고 복잡해 진다. 이러한 질의문이 반복해서 쓰인다면 매번 질의문을 작성하는 것도 불편하지만, 유지보수에도 많은 어려움이 있을 것이다.
이렇게 자주 사용되는 질의문은 스크립트로 만들어 두거나, STORED PROCEDURE를 사용해서 데이터베이스 서버에 저장하고 필요할 때만 호출하여 사용하는 방법이 있다.
또 하나의 방법으로 작성된 질의문을 VIEW의 형태로 데이터베이스에 저장하는 방법을 생각해 볼 수 있다. 위 처럼 긴 질의문을 VIEW로 정의하여 사용한다면 소스 코드에서 사용되는 질의문은 간결해 지며, 자연적으로 코드의 양도 줄어들어 유지보수가 편리한 장점이 있다.
- 테이블을 관리, 참조하기 위한 가상의 테이블 이다.
 - DATA를 물리적이 아닌 논리적으로 갖는 집합. 절대로 물리적인 공간을 사용하지 않는다.
 - VIEW를 생성하면 SQL문장과 함께 Dictionary에 저장된다.
 - VIEW를 조회하면 Dictionary에 저장되어 있는 해당 view SQL문장을 이용하여 근간이 되는 테이블을 ACCESS한다.
1) VEW 생성
CREATE [OR REPLACE] VIEW 뷰이름 AS 쿼리;
OR REPLACE는 뷰이름이 존재하면 지금의 질의에 대한 정의로 대체하라는 의미이다. 뷰의 내용을 변경할 때 사용된다.
2) VIEW 조회
VIEW 조회 역시 일반 테이블을 조회 하듯이 조회 하면 된다. ( 가상테이블 )
3) VIEW 삭제
DROP VIEW 뷰이름;
4) VIEW 사용 목적
- 검색조건의 단순화, JOIN문장의 단순화 등 여러번 조회 하거나 유지보수를 위하여 VIEW를 만들어 사용한다.
- 미리 튜닝된 SQL문으로 VIEW를 생성하여 수행속도를 향상 시킬 수 있다.
- 보안관리를 위하여 VIEW를 생성하여 접근 권한 및 테이블의 일부 칼럼을 숨기고 보여줄 수 있다.
5) Inline View
SQL > SELECT employee_id, last_name, hire_date
      FROM (SELECT * FROM employees ORDER BY hire_date)
      WHERE ROWNUM < 11;
위와 같이 Inline View View의 결과를 전체 질의에서 사용할 수 있도록 해준다. 따라서 매번 별도의 View를 생성하지 않아도 된다.
4. Sequence
Sequence는 연속적으로 어떤 값을 부여하는 것을 의미한다. 예를 들어 회원 테이블에 가입한 신규 회원을 식별하는 식별자로써 회원번호에 일련번호를 할당할 수 있다. 이때 회원번호에Sequence를 적용할 수 있다.
Sequence가 없더라고 중복되지 않고 연속된 일련번호를 부여할 수는 있따.
SQL > SELECT MAX(회원번호) FROM 회원;
이라는 질의 문을 통해 최대 번호를 얻은 다음 증가시키는 연산을 해주면 된다.
하지만 위의 경우 읽어야 하는 회원의 수가 많을 수록 시스템에 부하가 크게 발생할 수 있는 단점이 있다. 따라서 MAX() 함수의 사용시 발생하는 질의의 부하를 최소화할 수 있기 위해Sequence를 사용한다.
1) Sequence 만들기
CREATE SEQUENCE Sequence이름
[START WITH 숫자
INCREMENT BY 숫자] ;
2) Sequence 사용
INSERT INTO Table VALUES ( Sequence이름.NEXTVAL )
NEXTVAL이란 다음 값으로 지정된 값을 자동으로 증가 시킨다. 지정하지 않으면 시작 값 및 증가 값은 1을 가진다.
*** 참조 문헌 : 10g로 시작하는 오라클 SQL & PL/SQL - 6장 데이터를 담을 그릇을 만들자

언제 부터 였던가 생각해보니 아르바이트 겸 외부 컨설팅을 의뢰 받고 맥북 프로를 처음 써봤을 때 부터 였던 것 같다. 지금은 거의 대부분의 작업을 맥으로 작업을 하다 보니 윈도우에서만 실행되는 일부 프로그램들 때문과 회사 내부 ERP프로그램이 윈도우 ...