뷰(View)
- 다른 테이블(기본 테이블, base table)로 유도된 가상의 테이블(virtual table)
- 생성된 뷰는 일반 테이블처럼 사용할 수 있음
- 기본 테이블은 데이터(레코드)가 실제 데이터베이스에 저장되지만 뷰의 경우에는 정의(definition)만 저장됨
- 데이터는 저장되지 않고 뷰가 사용될 때만 만들어지는 테이블
- 실제로는 뷰를 사용하는 SQL문에서 뷰 대신 뷰 정의에 해당하는 SQL문으로 대치됨
- 뷰를 기반으로 새로운 뷰를 정의할 수도 있음
뷰의 정의(View Definition)
create view <뷰 이름> [컬럼 이름 리스트]
as select 문
[with check option];
- select 문은 union 또는 order by를 포함할 수 없음
- 컬럼명을 지정하지 않으면 select 결과의 컬럼명과 동일
뷰의 확인(Oracle에서)
- all_catalog: 테이블, 뷰, 시퀀스 확인
- all_views: 뷰의 정의 확인
뷰의 삭제
drop view <뷰 이름> [restrict | cascade]
restrict의 경우에는 뷰가 다른 곳에서 사용되지 않을 때만 삭제됨
cascade의 경우에는 해당 뷰를 사용하여 유도된 뷰들도 같이 삭제됨
※ Oracle의 경우에는 restrict 기능이 없으며 cascade 옵션 대신 cascade constraints로 사용해야 하며 삭제되는 view와 관련된 제약조건들(constrraint)를 함께 삭제하라는 의미임
실습 - 뷰 정의
STUDENT 테이블에서 '컴퓨터'과에 속한 학생들만으로 구성된 뷰 CSTUDENT를 다음과 같이 정의하고, SELECT 명령을 사용하여 데이터를 확인하라. 또한 카탈로그 정보를 통해 View 정보를 확인하라.
create view CSTUDENT -- View(Virtual Table)
as select *
from STUDENT -- Base Table
where dept='컴퓨터';
select * from cstudent;
View는 base table에서 select 된 결과를 보여주는 것이지 별도의 새로운 테이블이 생성되는 것은 아니다.
테이블명 키워드명, 컬럼명은 대소문자를 가리지 않지만 데이터 값은 대소문자를 가린다.
예를 들어 데이터베이스 이름이 'DB123456789'라면 owner='db123456789'라고 썼을 때 에러가 발생한다.
실습 문제 - with check option의 기능
- 아래와 같은 SQL문을 이용하여 CSTUDENT_WITH_CHECK를 각각 정의한 다음
create view cstudent_with_check
as
select *
from student where dept='컴퓨터'
with check option;
- 다음 명령을 차례로 각각 실행한 다음 그 결과를 확인하고 결과에 차이가 나타나는 이유를 생각해 보라.
insert into cstudent_with_check values (600, '홍길동', 1, 'IT');
insert into cstudent values (600, '홍길동', 1, 'IT');
insert into cstudent_with_check values (600, '홍길동', 1, 'IT');
우선 첫 번째 명령을 실행하면 에러가 난다.
view 정의에 with check option을 추가하면 view에 레코드를 추가하거나 업데이트할 때 조건을 만족하는지 확인하기 때문이다.
insert into cstudent values (600, '홍길동', 1, 'IT');
그리고 두 번째 명령을 실행하면 에러가 나지는 않으나
cstudent의 정의와 맞지 않기 때문에 cstudent를 select 했을 때 출력되지 않는다.
대신 student 테이블에 레코드가 추가되었다.
애초에 cstudent는 테이블이 아닌 뷰이기 때문에 레코드를 출력하는 sql문일 뿐이다.
따라서 뷰에 레코드를 insert 하거나 update하는 것은 말이 안 되고 대신 베이스테이블이 변경된다.
실습 - 다양한 뷰의 정의
-- 학과 별로 학생수를 알려주는 View 정의
create view DEPTSIZE
as
select dept, count(*) as num
from student
group by dept;
-- 학생의 이름, 학년, 학과 정보를 모은 뷰
create view STUDENT_NAME
as
select sname, year, dept
from student;
-- 'A' 학점을 받은 학생의 학번, 이름, 과목번호를 보여주는 뷰
create view HONOR_STUDENT
as
select sno, sname, cno
from student natural join enrol
where grade='A';
실습 - 뷰를 이용해서 뷰를 생성
- CSTUDENT 뷰를 사용하여 CSTUDENT_SENIOR 뷰를 생성(유도)한다.
create view cstudent_senior
as
select *
from cstudent
where syear = 4;
실습 - Base Table에 데이터 추가
- 다음과 같이 Base Table인 STUDENT에 새로운 행을 추가하고 CSTUDENT와 CSTUDENT_SENIOR 뷰를 각각 select 해보라.
insert into student values (700, '이몽룡', 4, '컴퓨터');
insert into student values (800, '성춘향', 1, '컴퓨터');
베이스테이블이 변경되었으므로 뷰의 출력도 바뀌었다.
실습 - 뷰의 삭제
- 아래 SQL 문을 순서대로 실행하고 각 명령의 실행결과를 검토하라.
drop view cstudent;
select * from cstudent_senior;
create view CSTUDENT
as *
from STUDENT where dept='컴퓨터';
select * from cstudent_senior;
base table로 사용된 view가 삭제되었기 때문에 유도된 테이블인 cstuden_senior를 사용할 수 없게 되었다.
drop view cstudent restrict;
※ 오라클에서는 지원하지 않지만 이렇게 하면 해결된다.
그리고 다음 명령을 차례대로 실행하면 삭제하기 전과 같이 정상적으로 동작한다.
실습 - 뷰에 대한 변경
- 앞서 정의한 CSTUDENT 뷰와 DEPTSIZE 뷰에 대해 아래 SQL문을 실행하고, 결과를 검토하라.
student_name은 앞서 만든 뷰이다.
뷰는 자체적으로 테이블을 갖고 있는 것이 아니라 베이스 테이블의 데이터를 다루기 때문에 레코드를 insert 할 때 베이스 테이블의 형식에 맞춰야 한다.
update student_name set year=4 where dept='컴퓨터';
'컴퓨터'과 학생들의 학년이 4로 바뀌었다.
num은 view를 생성할 때 특정 열에 지어준 이름일 뿐, 베이스테이블에 존재하지 않기 때문에 변경할 수 없다.
정상적으로 실행이 되었고 결과를 검토해보면
student 테이블에는 sno=100인 레코드가 지워지지 않았고
enrol 테이블에만 sno=100인 레코드가 지워졌다.
아마 honor_student를 정의할 때 where절의 조건이 enrol에만 해당이 되기 때문이지 않을까?
∴ 뷰를 통해서 데이터를 변경하는 것은 상당히 모호함. 되는 경우도 있고 안 되는 경우도 있음.
뷰의 특징
- 뷰는 일반적으로는 변경이 불가능하지만 제한적으로 변경 가능한 뷰도 있음 (변경: 삽입, 삭제, 갱신)
- 뷰에 INSERT를 하려면 키가 포함되어 있어야 함(필요 조건)
- 뷰에 UPDATE 또는 DELETE를 하려면 기반테이블에서 갱신 또는 삭제 대상이 되는 행을 식별할 수 있어야 함
- 서로 다른 테이블들을 조인한 결과물 또는 통계 정보를 뷰로 정의한 경우에는 갱신이 불가능할 수 있음
뷰의 장단점
장점 | 단점 |
데이터 독립성을 제공한 한 방법 | 정의를 변경할 수 없음 |
뷰에 대한 접근 제어를 통해 보안성 제공 | 변경(삽입, 삭제, 갱신)에 제한이 있음 |
데이터의 관리가 용이 | |
사용자 별로 서로 다른 데이터를 보여줄 수 있음 |
create view cstudent
as
select *
from student
where dept='컴퓨터';
select * from cstudent;
select * from cstudent where year=4;
select * from (select *
from student
where dept='컴퓨터') where year=4;
update cstudent set year=2 where sno=300;
select * from student;
select * from all_catalog;
select * from all_catalog where owner='DB201811658';
select * from all_views where owner='DB201811658';
create view cstudent_with_check
as
select *
from student where dept='컴퓨터'
with check option;
select * from cstudent_with_check;
insert into cstudent values (600, '홍길동', 1, 'IT');
select * from cstudent;
select * from student;
select * from cstudent_with_check;
create view DEPTSIZE
as
select dept, count(*) as num
from student
group by dept;
select * from DEPTSIZE;
create view STUDENT_NAME
as
select sname, year, dept
from student;
select * from student_name;
create view honor_student
as
select sno, sname, cno
from student natural join enrol
where grade='A';
select * from honor_student;
create view cstudent_senior
as
select *
from cstudent
where year=4;
select * from cstudent_senior;
insert into student values (700, '이몽룡', 4, '컴퓨터');
insert into student values (800, '성춘향', 1, '컴퓨터');
select * from student;
select * from cstudent;
select * from cstudent_senior;
drop view cstudent;
select * from all_views where owner='DB201811658';
create view cstudent
as
select *
from student
where dept='컴퓨터';
select * from cstudent_senior;
select * from student_name;
insert into student_name values ('심청', 1, '전자');
update student_name set year=4 where dept='컴퓨터';
select * from student;
select * from deptsize;
update deptsize set num=10;
delete honor_student where sno=100;
select * from student;
select * from enrol;
'데이터베이스 Database' 카테고리의 다른 글
Chapter 6 SQL - 함수 Function (0) | 2020.10.26 |
---|---|
Chapter 6 SQL - 저장프로시저 Stored Procedure (0) | 2020.10.26 |
Chapter 5 관계 대수와 관계 해석 (0) | 2020.09.22 |
Chapter 4 관계 데이터베이스 (0) | 2020.09.18 |
Chapter 3 데이터베이스 시스템의 구성 (0) | 2020.09.17 |