# 30강. 뷰 작성과 삭제
뷰는 테이블과 같은 부류의 데이터베이스 객체 중 하나이다. 여기에서는 뷰를 정의하고, 작성 및 삭제하는 방법에 대해서 알아본다.

**`뷰의 작성 및 삭제`**
```
CREATE VIEW 뷰명 AS SELECT명령
DROP VIEW 뷰명
```

- 앞장에서 서브쿼리에 대해서 배웠는데, 서브쿼리는 `FROM` 구에서도 기술할 수 있었다.
- 여기서 `FROM` 구에 기술된 서브쿼리에 이름을 붙이고 데이터베이스 객체화하여 쓰기 쉽게 한 것을 뷰라고 한다.

---

## 1. 뷰
- 데이터베이스 객체란 테이블이나 인덱스 등 데이터베이스 안에 정의하는 모든 것을 말한다.
- 뷰 역시 데이터베이스 객체 중 하나이다. 반면 `SELECT` 명령은 객체가 아니다.
- `SELECT` 명령에 이름을 지정할 수도 없고 데이터베이스에 등록되지도 않기 때문이다.
- 이처럼 본래 데이터베이스 객체로 등록할 수 없는 `SELECT` 명령을, 객체로서 이름을 붙여 관리할 수 있도록 한 것이 뷰이다.
- `SELECT` 명령은 실행했을 때 테이블에 저장된 데이터를 결괏값으로 반환한다.
- 따라서 뷰를 참조하면 그에 정의된 `SELECT` 명령의 실행결과를 테이블처럼 사용할 수 있다.

##### 뷰는 SELECT 명령을 기록하는 데이터베이스 객체다!

- `FROM` 구에는 서브쿼리를 사용할 수 있었다. 예를 들면 다음과 같은 `SELECT` 명령이다.

`SELECT * FROM (SELECT * FROM sample54) sq;`

- 앞의 예에서 서브쿼리 부분을 `뷰 객체`로 만들면 다음과 같은 `SELECT` 명령이 된다.

`SELECT * FROM sample_view_67;`

- sample_view_67은 뷰의 이름이다. 뷰를 정의할 때는 이름과 `SELECT` 명령을 지정한다.
- 뷰를 만든 후에는 `SELECT` 명령에서 뷰의 이름을 지정하면 참조할 수 있다.
- 앞선 예제에서는 서브쿼리 부분이 단순한 `SELECT` 명령으로 되어 있지만, 실제 업무에서는 `WHERE` 구로 조건을 지정하거나 `GROUP BY` 구로 집계하는 등 좀 더 복잡한 명령으로 이루어지는 경우가 많다.
- 이런 경우 서브쿼리 부분을 뷰로 대체하여 `SELECT` 명령을 간략하게 표현할 수 있다.
- 또한 뷰를 사용함으로써 복잡한 `SELECT` 명령을 데이터베이스에 등록해 두었다가 나중에 간단히 실행할 수도 있다.
- 즉, 자주 사용하거나 복잡한 `SELECT` 명령을 뷰로 만들어 편리하게 사용할 수 있는 것이다.

##### 뷰를 작성하는 것으로 복잡한 SELECT 명령을 간략하게 표현할 수 있다!

### 가상 테이블
- 뷰는 테이블처럼 취급할 수 있지만 '실체가 존재하지 않는다'라는 의미로 `가상 테이블`이라 불리기도 한다.
- `SELECT` 명령으로 이루어지는 뷰는 테이블처럼 데이터를 쓰거나 지울 수 있는 저장공간을 가지지 않는다.
- 이 때문에 테이블처럼 취급할 수 있다고는 해도 `SELECT 명령에서만 사용`하는 것을 권장한다.
- `INSERT`나 `UPDATE`, `DELETE` 명령에서도 조건이 맞으면 가능하지만 사용에 주의할 필요가 있다.

---

## 2. 뷰 작성과 삭제
- 뷰는 데이터베이스 객체이기 때문에 `DDL`로 작성하거나 삭제한다.
- 작성할 때는 `CREATE VIEW`를, 삭제할 때는 `DROP VIEW`를 사용한다.

### 뷰의 작성

**`CREATE VIEW`**
```
CREATE VIEW 뷰명 AS SELECT 명령
```

- `CREATE VIEW` 다음에 뷰의 이름을 지정하고, `AS`로 `SELECT` 명령을 지정한다.
- `CREATE VIEW`의 `AS` 키워드는 별명을 붙일 때 사용하는 `AS`와는 달리 생략할 수 없다.

**`뷰 작성하기`**
```
CREATE VIEW sample_view_67 AS SELECT * FROM sample54;

SELECT * FROM sample_view_67;
```

- `CREATE VIEW`로 뷰를 작성한 뒤 `SELECT` 명령의 `FROM` 구에 지정해 사용할 수 있다.
- 뷰는 필요에 따라 열을 지정할 수도 있는데, 이 경우에는 이름 뒤에 괄호로 묶어 열을 나열한다.

**`CREATE VIEW에서 열 지정하기`**
```
CREATE VIEW 뷰명 (열명1, 열명2, ...) AS SELECT 명령
```

- 뷰의 열 지정을 생략한 경우에는 `SELECT` 명령의 `SELECT` 구에서 지정하는 열 정보가 수집되어 자동적으로 뷰의 열로 지정된다.
- 반대로 열을 지정한 경우에는 `SELECT` 명령의 `SELECT` 구에 지정한 열보다 우선된다.
- 다만 `SELECT` 명령의 `SELECT` 구와 같은 수의 열을 일일이 지정해야 하므로 `SELECT` 명령의 모든 열을 사용할 경우에는 열을 지정하지 않는 편이 낫다.
- 또한 열 이외에는 정의할 수 없으며, 테이블의 열을 정의할 때처럼 자료형이나 제약도 지정할 수 없다.

**`열을 지정해서 뷰 작성하기`**
```
CREATE VIEW sample_view_672(n, v, v2) AS SELECT no, a, a*2 FROM sample54;

SELECT * FROM sample_view_672 WHERE n = 1;
```

### 뷰 삭제
- 뷰를 삭제할 경우에는 `DROP VIEW`를 사용한다.
- 일단 뷰를 삭제하면 더 이상 뷰를 참조하여 사용할 수 없다.

**`DROP VIEW`**
```
DROP VIEW 뷰명
```

**`뷰 삭제하기`**
```
DROP VIEW sample_view_672;
```

---

## 3. 뷰의 약점
- 뷰는 데이터베이스 객체로서 저장장치에 저장된다.
- 하지만 테이블과 달리 대량의 저장공간을 필요로 하지 않는다.
- 데이터베이스에 저장되는 것은 `SELECT` 명령뿐이기 때문이다.
- 다만 저장공간을 소비하지 않는 대신 CPU 자원을 사용한다.
- `SELECT` 명령은 데이터베이스의 테이블에서 행을 검색해 클라이언트로 반환하는 명령이다.
- 검색뿐만 아니라 `ORDER BY`로 정렬하거나 `GROUP BY`로 집계할 수 있다.
- 이러한 처리는 계산능력을 필요로 하기 때문에 컴퓨터의 CPU를 사용한다.
- 뷰를 참조하면 뷰에 등록되어 있는 `SELECT` 명령이 실행된다.
- 실행 결과는 일시적으로 보존되며, 뷰를 참조할 때마다 `SELECT` 명령이 실행된다.

### 머티리얼라이즈드 뷰(Materialized View)
- 뷰에도 약점은 있다. 뷰의 근원이 되는 테이블에 보관하는 데이터양이 많은 경우, 집계처리를 할 때도 뷰가 사용된다면 처리속도가 많이 떨어질 수밖에 없다.
- 뷰를 중첩해서 사용하는 경우에도 처리 속도가 떨어지기 쉽다.
- 이 같은 상황을 회피하기 위해 사용할 수 잇는 것이 `머티리얼라이즈드 뷰`이다.
- 일반적으로 뷰는 데이터를 일시적으로 저장했다가 쿼리가 실행 종료될 때 함께 삭제된다. 그에 비해 머티리얼라이즈드 뷰는 데이터를 일시적으로 저장해 사용하는 것이 아니라 테이블처럼 저장장치에 저장해두고 사용한다.
- 머티리얼라이즈드 뷰는 처음 참조되었을 때 데이터를 저장해둔다.
- 이후 다시 참조할 때 이전에 저장해 두었던 데이터를 그대로 사용한다.
- 일반적인 뷰처럼 매번 `SELECT` 명령을 실행할 필요가 없다.
- 다만 뷰에 지정된 테이블의 데이터가 변경된 경우에는 `SELECT` 명령을 재실행하여 데이터를 다시 저장한다.
- 이처럼 변경 유무를 확인하여 재실행하는 것은 `RDBMS`가 자동으로 실행한다.
- 뷰에 지정된 테이블의 데이터가 자주 변경되지 않는 경우라면 머티리얼라이즈드 뷰를 사용하여 뷰의 약점을 어느 정도 보완할 수 있다.
- 다만, 한 가지 아쉬운 점이 있다면 `MySQL`에서는 머티리얼라이즈드 뷰를 사용할 수 없다.
- 지금으로서는 `Oracle`과 `DB2`에서만 사용할 수 있는 데이터베이스 객체이다.

### 함수 테이블
- 뷰는 또 하나의 약점을 갖는다. 뷰를 구성하는 `SELECT` 명령은 단독으로도 실행할 수 있어야 한다.
- 상관 서브쿼리에서 언급한 것처럼, 부모 쿼리와 어떤 식으로든 연관된 서브쿼리의 경우에는 뷰의 `SELECT` 명령으로 사용할 수 없다.
- 대신 이 같은 뷰의 약점을 `함수 테이블`을 사용하여 회피할 수 있다.
- `함수 테이블`은 테이블을 결괏값으로 반환해주는 사용자정의 함수이다.
- 함수에는 인수를 지정할 수 있기 때문에 인수의 값에 따라 `WHERE` 조건을 붙여 결괏값을 바꿀 수 있다. 그에 따라 상관 서브쿼리처럼 동작할 수 있다.

---