view



1. 뷰는 테이블에서 사용자가 얻기를 원하는 데이터들만을 정확하고 편하게 가져오기 위하여

사전에 원하는 컬럼들만을 모아서 만들어 놓은 가상의 테이블



2. 형식

CREATE OR REPLACE VIEW 뷰이름

AS

SELECT 구문;


서브쿼리로 예를 들면,

SELECT * FROM (서브쿼리 구문);

서브쿼리 구문이 복잡하더라도 결국은 단순한 쿼리문으로 표현할 수 있다.

서브쿼리는 객체로서 등록하지는 못한다.


뷰로 예를 들면,

CREATE OR REPLACE VIEW 뷰이름

AS

서브쿼리 구문;

서브쿼리는 복잡하더라도 결국은 단순한 뷰 구문(SELECT * FROM 뷰이름)으로 표현할 수 있다.

뷰는 객체로서 등록하지는 못한다.



-- 제약조건 확인용 뷰 생성

-- 원본SELECT 쿼리

SELECT uc.owner                         --소유자

, uc.constraint_name            --제약명

, uc.table_name AS table_name   --테이블명

, uc.constraint_type            --제약조건 종류(P, R, U, C)

, uc.search_condition           --CHECK 제약 조건식

, ucc.column_name               --지정된 컬럼

, (SELECT table_name 

FROM user_constraints 

WHERE constraint_name=uc.r_constraint_name) 

AS r_table_name --참조하는 테이블

, (SELECT column_name 

FROM user_constraints 

WHERE constraint_name=uc.r_constraint_name) 

AS r_conlumn_name --참조하는 컬럼

FROM user_constraints uc, user_cons_columns ucc

WHERE uc.constraint_name = ucc.constraint_name

AND uc.table_name='테이블명'; -- 외부로 부터 받는 인자는 지우고 추후 추가 where 절을 통해 개별지정.


--뷰생성

CREATE OR REPLACE VIEW constraint_check

AS

SELECT uc.owner                         --소유자

, uc.constraint_name            --제약명

, uc.table_name AS table_name   --테이블명

, uc.constraint_type            --제약조건 종류(P, R, U, C)

, uc.search_condition           --CHECK 제약 조건식

, ucc.column_name               --지정된 컬럼

, (SELECT table_name 

FROM user_constraints 

WHERE constraint_name=uc.r_constraint_name) 

AS r_table_name --참조하는 테이블

, (SELECT column_name 

FROM user_constraints 

WHERE constraint_name=uc.r_constraint_name) 

AS r_conlumn_name --참조하는 컬럼

FROM user_constraints uc, user_cons_columns ucc

WHERE uc.constraint_name = ucc.constraint_name;


--뷰 실행

select * from constraint_check

where table_name = 테이블명;



--뷰의 구조 확인

DESC 뷰이름;


--뷰의 소스 확인


SELECT view_name, text

from user_views

where view_name = '뷰 이름';



문제) insa 테이블에서 아래의 결과를 얻는 뷰 작성.

이름, 부서, 출신도, 기본급, 수당, 기본급+수당(총급여), 세금, 실수령액 출력

세금 계산 -> 총급여가 250만원 이상이면 2% 200만원이상이면 1%, 나머지는 0%

실수령액 계산 -> 총급여 - 세금








인라인 뷰


1. 쿼리문에서 from절에 서브쿼리를 사용하여 생성한 임시 뷰이다.

인라인 뷰는 객체로서 저장되지 않는다.


2. 형식

SELECT 컬럼리스트

FROM (서브쿼리);


UPDATE (서브쿼리)

SET 컬럼 = 신규자료, ...

WHERE 조건식;


DELETE (서브쿼리)

WHERE 조건식;



--employees 테이블에서 입사일(hire_date)가 빠른 순으로 5순위까지만 출력


SELECT *

FROM (SELECT first_name, last_name, RANK() OVER(order by hire_date asc) as rank

FROM EMPLOYEES)

where rank <= 5;




--employees 테이블에서 jobs.job_title이 'Shipping Clerk'인 직원의 employees.salary를 10% 인상.


update employees

set salary = salary * 1.1

where job_id = (select job_id

from jobs

where job_title = 'Shipping Clerk');



update (select first_name, last_name, job_title, salary

from employees e, jobs j

where e.job_id = j.job_id) e

set esalary = e.salary * 1.1

where e.job_title = 'Shipping Clerk';



--employees 테이블에서 jobs.job_title이 'Shipping Clerk'인 직원 삭제.


delete (select first_name, last_name, job_title, salary

from employees e, jobs j

where e.job_id = j.job_id) e

where e.job_title = 'Shipping Clerk'



문제) employees 테이블에서 employees.salary를 각 부서 이름별(department_name)로 다른 인상율 적용합니다. 인라인뷰 이용.


Finance -> 10%

Executive -> 15%

Accounting -> 20%

나머지 부서 -> 5%


update(select e.first_name, e.last_name, d.department_name, e.salary

from employees e, departments d) t

set t.salary = case when t.department_name='Finance' then t.salary * 1.1

   when t.department_name='Executive' then t.salary * 1.15

   when t.department_name='Accounting' then t.salary * 1.2

   else t.salary * 1.05 end







PL/SQL (Procedural Language extension to SQL)


1. PL/SQL 은 프로그래밍 언어의 특성을 가지는 SQL의 확장.


2. PL/SQL은 블록 구조로 되어 있으며 선언부, 실행부, 예외처리부로 구성됨


3. 형식

DECLARE

-- 선언문

BEGIN

-- 실행문


[EXCEPTION

-- 예외처리문]


END;



4. PL/SQL 은 변수, 연산자(대입문), 제어문(조건문, 반복문) 등을 지원한다.


--메세지 출력

SET SERVEROUTPUT ON;

DECLARE

BEGIN

DBMS_OUTPUT.PUT_LINE('Hello, Oracle World!');

END;



--변수 선언 및 초기값 대입

SET SERVEROUTPUT ON;

DECLARE

str VARCHAR2(100) := 'Hello, Oracle World!';

BEGIN

DBMS_OUTPUT.PUT_LINE(str);

END;



--산술연산

SET SERVEROUTPUT ON;

DECLARE

n1 NUMBER := 10;

n2 NUMBER := 20;

BEGIN

DBMS_OUTPUT.PUT_LINE('n1 = ' || n1);

DBMS_OUTPUT.PUT_LINE('n2 = ' || n2);

DBMS_OUTPUT.PUT_LINE('n1 + n2 = ' || (n1 + n2));

DBMS_OUTPUT.PUT_LINE('n1 * n2 = ' || (n1 * n2));

END;



--IF문

형식

IF(조건식) THEN 실행문;

elsif 조건식 then 실행문;3


else 실행문

END IF;



형식2

IF(조건식) THEN

실행문;

ELSE

실행문;

END IF;



형식3

IF(조건식) THEN

실행문;

ELSIF(조건식2) THEN

실행문;

[ELSIF(조건식n THEN)

실행문;]

ELSE

실행문;

END IF;




SET SERVEROUTPUT ON;

DECLARE

grade NUMBER := 100;

BEGIN

if(grade >= 90 and grade <= 100)  then

DBMS_OUTPUT.PUT_LINE('A등급');

else

DBMS_OUTPUT.PUT_LINE('B등급');

end if;

END;




SET SERVEROUTPUT ON;

DECLARE

grade NUMBER := 100;

BEGIN

if(grade >= 90 and grade <= 100)  then

DBMS_OUTPUT.PUT_LINE('A등급');

elsif (grade >= 80 and grade <= 90) then

DBMS_OUTPUT.PUT_LINE('B등급');

elsif (grade >= 70 and grade <= 80) then

DBMS_OUTPUT.PUT_LINE('C등급');

elsif (grade >= 60 and grade <= 70) then

DBMS_OUTPUT.PUT_LINE('D등급');

else

DBMS_OUTPUT.PUT_LINE('F등급');

end if;

END;




-- CASE ~ END CASE 구문

CASE 변수

WHEN 값1 THEN 실행문;

WHEN 값2 THEN 실행문;

...

ELSE 실행문;

END CASE;



문제) 점수를 분석해서 A등급에서 F등급까지 출력하는 PL/SQL 작성. CASE ~ END CASE 구문 이용.


SET SERVEROUTPUT ON;

DECLARE

grade NUMBER := 100;

BEGIN

CASE trunc(grade/10)

WHEN 10 THEN DBMS_OUTPUT.PUT_LINE('A등급');

WHEN 9 THEN DBMS_OUTPUT.PUT_LINE('A등급');

WHEN 8 THEN DBMS_OUTPUT.PUT_LINE('B등급');

WHEN 7 THEN DBMS_OUTPUT.PUT_LINE('C등급');

WHEN 6 THEN DBMS_OUTPUT.PUT_LINE('D등급');

ELSE DBMS_OUTPUT.PUT_LINE('F등급');

END CASE;

END;




-- WHILE ~ END LOOP 구문

형식1

WHILE 조건식 LOOP -- 조건이 참이면 반복실행

실행문;

END LOOP;



형식2 (무한실행)

LOOP

EXIT WHEN 조건식; -- 조건이 참이면 블럭탈출

실행문;

END LOOP;


-- 1부터 10까지 출력.


SET SERVEROUTPUT ON;

DECLARE

n NUMBER; 

BEGIN

n := 0;

while n < 10 loop

n := n + 1;

DBMS_OUTPUT.PUT_LINE(n);

end loop;

END;




SET SERVEROUTPUT ON;

DECLARE

n NUMBER;

BEGIN

n := 0;

loop

exit when n = 11;

n := n + 1;

DBMS_OUTOUT.PUT_LINE(n);

end loop;

END;




-- FOR ~ END LOOP 문

FOR 변수 IN 시작수..끝수 LOOP

실행문;

END LOOP;



-- 1부터 10까지 출력.


SET SERVEROUTPUT ON;

DECLARE

n NUMBER;

BEGIN

FOR n IN 1..10 LOOP -- 이 FOR문에서 n 즉 변수는 별도의 선언이 없어도 자동선언되므로, DECLARE 에서 별도로 선언하지 않아도 됨.

DBMS_OUTPUT.PUT_LINE(n);

END LOOP;

END;




문제) 구구단 출력을 WHILE, LOOP, FOR 반복문으로 출력. 5단으로 한정.


while 문사용 ) --


SET SERVEROUTPUT ON;

DECLARE

n NUMBER := 5;

m NUMBER := 1;

BEGIN

WHILE(m <= 9) LOOP

DBMS_OUTPUT.PUT_LINE(n || '*' || m ||' = ' || (n*m));

m := m + 1;

END LOOP;

END;




LOOP 문 사용 )--


SET SERVEROUTPUT ON;

DECLARE

n NUMBER := 5;

m NUMBER := 1;

BEGIN

LOOP

EXIT WHEN m = 9;

DBMS_OUTPUT.PUT_LINE(n || '*' || m ||' = ' || (n*m));

m := m+1;

END LOOP;

END;




FOR 문 사용 )--


SET SERVEROUTPUT ON;

DECLARE

n NUMBER := 5;

BEGIN

for m in 1..9 loop

DBMS_OUTPUT.PUT_LINE(n || '*' || m ||' = ' || (n*m));

end loop;

END;








PL/SQL 외부 입력 처리


1. ACCEPT 변수 PROMPT '메시지'


2. 외부 변수에서 받은 데이터를 내부 변수에 전달할 때는 &외부변수명 형태로 연결.


ACCEPT n1 PROMPT '숫자1?';

ACCEPT n2 PROMPT '숫자2?';

SET SERVEROUTPUT ON;

DECLARE

num1 NUMBER := &n1;

num2 NUMBER := &n2;

BEGIN

DBMS_OUTPUT.PUT_LINE('n1 = ' || n1);

DBMS_OUTPUT.PUT_LINE('n2 = ' || n2);

DBMS_OUTPUT.PUT_LINE('n1 + n2 = ' || (n1 + n2));

END;



문제) 구구단 출력을 사용자가 원하는 단수로 출력. ACCEPT, FOR문 사용.

실행 예)

구구단 단수? 5

5 * 1 = 5

....

5 * 9 = 45



ACCEPT n1 PROMPT '구구단 단수?';

SET SERVEROUTPUT ON;

DECLARE

n NUMBER := &n1;

BEGIN

for m in 1..9 loop

DBMS_OUTPUT.PUT_LINE(n || '*' || m ||' = ' || (n*m));

end loop;

END;






FUNCTION (함수)


1. 내장함수, 사용자 정의 함수. 외부 데이터 입력시 단일 결과 리턴하는 PL/SQL 구문의 집합체.


2. 형식

CREATE OR REPLACE FUNCTION 함수이름

(

매개변수 리스트 --자료형 지정시 크기 지정 불가

)

RETURN 리턴자료형 --자료형 지정시 크기 지정 불가

IS

내부변수 리스트;

BEGIN

실행문;

RETURN 값;

END;


--주민번호 입력시 성별 출력하는 함수 작성.

--> fnGender('주민번호')


--사용자 정의 함수 작성

CREATE OR REPLACE FUNCTION fnGender

(

vssn VARCHAR2 --'123456-1234567', 1 또는 2만으로 구분한다고 가정

)

RETURN NVARCHAR2 --'남자', '여자'

IS

gender NVARCHAR2(2);

BEGIN

IF (SUBSTR(vssn, 8, 1) = '1') THEN

gender := '남자';

ELSE

gender := '여자';

END IF;

RETURN gender;

END;


--사용자 정의 함수 실행

SELECT fnGender('123456-1234567') AS fnGender FROM dual; --'남자'

SELECT fnGender('123456-2345678') AS fnGender FROM dual; --'여자'


SELECT num, name, ssn, fnGender(ssn) AS fnGender

  FROM insa;

  

SELECT fnGender(ssn), COUNT(*)

  FROM insa

  GROUP BY fnGender(ssn);



--주민번호(VARCHAR2) 입력시 생년월일(DATE, YYYY-MM-DD) 리턴하는 함수 작성

--> fnBirthDay('주민번호')

CREATE OR REPLACE FUNCTION fnBirthDay

(

vssn VARCHAR2

)

RETURN date

IS

birthday DATE;

BEGIN

birthday := TO_DATE(SUBSTR(vssn, 1, 6)); --YY/MM/DD

RETURN birthday;

END;



SELECT fnBirthDay('800101-1234567') AS fnBirthDay FROM dual;


SELECT TO_CHAR(fnBirthDay('800101-1234567'), 'YYYY-MM-DD') AS fnBirthDay FROM dual;


SELECT num, name, ssn, fnBirthDay(ssn) AS fnBirthDay FROM insa;



문제) 날짜 데이터를 입력 받아서 년도, 월, 일을 따로 출력하는 함수 작성.

반환 자료형은 NUMBER.

fnYear(날짜 데이터), fnMonth(날짜데이터), fnDay(날짜데이터)


--사용 예

SELECT num, name, ibsadate 

FROM insa

WHERE fnMonth(ibsadate) = 5;



--날짜 데이터에서 '년' 얻는 함수

CREATE OR REPLACE FUNCTION fnYear

(

vdate DATE

)

RETURN NUMBER

IS

BEGIN

RETURN TO_NUMBER(TO_CHAR(vdate, 'YYYY'));

END;


SELECT fnYear(SYSDATE) FROM dual;



--날짜 데이터에서 '월' 얻는 함수

CREATE OR REPLACE FUNCTION fnMonth

(

vdate DATE

)

RETURN NUMBER

IS

BEGIN

RETURN TO_NUMBER(TO_CHAR(vdate, 'MM'));

END;


SELECT fnMonth(SYSDATE) FROM dual;



--날짜 데이터에서 '일' 얻는 함수

CREATE OR REPLACE FUNCTION fnDay

(

vdate DATE

)

RETURN NUMBER

IS

BEGIN

RETURN TO_NUMBER(TO_CHAR(vdate, 'DD'));

END;


SELECT fnDay(SYSDATE) FROM dual;



WRITTEN BY
빨강꼬마

,

◆ view ◆

- view
  실제로 존재하지 않는 가상의 테이블을 의미함.
  즉, A, B, C, D라는 컬럼을 가진 실제 테이블이 있고,
  이 테이블에서 select의 함수등을 통해 연산처리된 추가적인 컬럼(E)를 만들수 있다면
  출력된 결과를 가상의 테이블, 즉 view로 만들어 사용할 수 있게 한다.


EX)
  jikwon 이라는 테이블의 정보(총 6개의 column)

 

  select 함수를 이용하여 현재나이, 정년퇴직일자, 연봉을 추가로 출력한 결과값

  해당 결과값을 뷰(가상테이블)로 생성

  create or replace view [생성할뷰이름] as

  가상테이블로 만들어진 데이터 확인

 

  이렇게 만들어진 뷰를 대상으로 예를 들어 [정년퇴직일이 2040년 이후인 직원중 연봉이 3000이상인 직원을 검색하라] 라는 문제를 보다 쉽게 해결할 수 있음. 또한, 뷰는 테이블의 정보를 변경하지 않기 때문에 테이블의 정보를 기반으로 구성된 쿼리나 프로그램에는 전혀 영향을 끼치지 않음.

 - 뷰는 sys계정에서 create view 권한을 주어야 테이블 생성 권한을 주는 것처럼 뷰를 생성할 수 있음.
 - create view [생성될뷰이름] as select ~~~ 로도 뷰 생성이 가능하나, 뷰내용의 교체(replace)는
          replace 명령 단독으로 실행되지 않기 때문에, create or replace view 로 사용하는 것을 권장함.
 - 뷰는 테이블과의 구분이 시각적으로 어렵기 때문에 파일명에서 차이를 두는 습관을 기르도록 권장함.
   (ex: tbl_abc / view_abc 등)
 - 뷰는 생성시 alias를 지정해야 정상적으로 생성된다. 다만, 컬럼명에서 함수등이 사용되지 않아 원 컬럼명 그대로
   사용된 경우 alias 지정을 하지 않아도 생성이 가능하다.
 - alias 지정시 각 컬럼명 뒤에 as "~~~"식으로도 가능하나,
   create or replace view (컬럼1, 컬럼2, .....) 식으로 순차 맵핑시켜 생성도 가능하다.


- select * from user_views;
  생성되어 있는 뷰의 소스를 확인할 수 있다.

- drop view [뷰이름]
  생성한 뷰를 삭제한다.

- revoke [회수할 권한] from [사용자명];
  sys 계정 명령어로 권한을 다시 회수할 때 사용하는 명령

- betweeb [X] and [Y]
  X 부터 Y 까지의 데이터.
  예를들어 1번부터 100번까지의 데이터가 있는데, 이중 30~39까지의 데이터를 뽑고싶다면 다음과 같이 사용할 수 있다.
  between 30 and 39  혹은  trunc(현재나이, -1) = 30  혹은  숫자>=30 and 숫자 <=39

 

◆ inline view ◆

 - inline view
   인라인 뷰란, 실제 뷰를 생성하지 않고 SQL 쿼리문 안에서 선언하여 쿼리문 수행시 임시적으로 view를 만들어
   사용하는데 이것을 inline view 라 칭함.

ex)
    inline view 로 사용할 소스

 

    작성한 소스 select 앞과 소스 가장 마지막을 (소스내용)["inline view명";] 를 사용하여 선언한다.

 

    선언한 inline view는 선언한 inline view를 사용할 소스의 from 절에 위치하도록 한다.

 

 

선언한 inline view의 컬럼명은 ["inline view명".inline view컬럼명] 으로 사용한다.
- 선언된 inline view를 사용하여 작성한 쿼리문 역시 다시 inline view를 사용하여 묶을 수 있다.

 

 

 


WRITTEN BY
빨강꼬마

,