뷰는 가상 테이블이며, 실제 데이터를 저장하지 않고, SELECT 쿼리 결과를 저장한 것처럼 사용할 수 있는 객체이다. 마치 테이블처럼 사용할 수 있지만, 내부적으로는 정의된 SQL 쿼리가 실행되어
결과가 표시된다.
MySQL 기준이다.
-- 테이블
CREATE TABLE employees
(
id INT PRIMARY KEY,
name VARCHAR(100),
department VARCHAR(100),
salary INT
);
INSERT INTO employees
VALUES (1, 'kim', 'HR', 5000),
(2, 'lee', 'Engineering', 8000),
(3, 'park', 'Engineering', 7500);
-- 뷰 생성
CREATE VIEW engineering_employees AS
SELECT id, name, salary
FROM employees
WHERE department = 'Engineering';
-- 뷰에서 데이터 조회
SELECT *
FROM engineering_employees;
| id | name | salary |
|---|---|---|
| 2 | lee | 8000 |
| 3 | park | 7500 |
-- 뷰 목록 보기
SHOW FULL TABLES WHERE Table_type = 'VIEW';
-- 뷰 정의 확인
SHOW CREATE VIEW engineering_employees;
CREATE OR REPLACE VIEW engineering_employees AS
SELECT id, name, department, salary
FROM employees
WHERE department = 'Engineering';
DROP VIEW engineering_employees;
뷰가 단일 테이블 기반이고 집계나 조인 없이 단순한 SELECT라면 데이터를 수정할 수도 있다.
UPDATE engineering_employees
SET salary = 8500
WHERE name = 'lee';
이 경우 실제 employees테이블의 lee의 급여가 변경된다.
다음과 같은 조건을 만족하면 뷰를 통해 수정할 수 있다.
SUM(), AVG() 같은 집계 함수가 없어야 한다.GROUP BY, HAVING BY가 없다: 그룹화를 하면 안 된다.SELECT id, salary * 1.1 AS bonus처럼 추가적인 계산이 있으면 안 된다.NOT NULL 컬럼 포함: NOT NULL인 컬럼들이 모두 뷰에 포함되어 있어야 한다.-- 수정 가능한 뷰 (위의 예시)
CREATE VIEW engineering_employees AS
SELECT id, name, salary
FROM employees
WHERE department = 'Engineering';
다음과 같은 경우는 MySQL이 수정 방법을 결정할 수 없기 때문에 뷰를 통한 변경이 금지된다.
-- 집계를 포함한다.
CREATE VIEW avg_salary_by_dept AS
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
-- 계산된 컬럼이 있는 뷰
CREATE VIEW salary_with_tax AS
SELECT id, name, salary, salary * 0.9 AS after_tax_salary
FROM employees;
-- DISTINCT가 포함된 뷰
CREATE VIEW distinct_departments AS
SELECT DISTINCT department
FROM employees;
-- LIMIT이 포함된 뷰
CREATE VIEW top_3_highest_paid AS
SELECT *
FROM employees
ORDER BY salary DESC
LIMIT 3;
-- 서브퀴리가 포함된 뷰
CREATE VIEW high_salary_employees AS
SELECT id, name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- 뷰에 포함되지 않은 NOT NULL 컬럼이 있는 경우
CREATE VIEW employee_names AS
SELECT name -- id가 빠짐
FROM employees;
UPDATE나 INSERT를 하려면 NOT NULL컬럼이 모두 포함되어 있어야 한다.뷰에 맞지 않는 데이터는 넣거나 바꿀 수 없게 한다.
WITH CHECK OPTION은 뷰를 통해 데이터를 수정할 때, 뷰에서 정의한 조건을 유지하도록 강제하는 옵션이다.
뷰는 실제 테이블의 일부만 보여줄 수 있다. 예를 들어 특정 부서만 보여주는 뷰가 있다고 할 때, 그 뷰를 통해 다른 부서로 옮기는 업데이트가 가능해지면 논리적 일관성이 깨질 수 있기 때문이다.
이러한 문제를 방지하기 위해 WITH CHECK OPTION
테이블 스키마와 뷰는 위와 동일하다.
UPDATE engineering_employees
SET department = 'HR'
WHERE name = 'lee';
lee는 더이상 엔지니어링 부서가 아니기에 뷰에서 사라진다.CREATE OR REPLACE VIEW engineering_employees AS
SELECT *
FROM employees
WHERE department = 'Engineering'
WITH CHECK OPTION; -- WITH CHECK OPTION 사용
이렇게 WITH CHECK OPTION을 붙이면 조건에 맞는 수정만 가능해진다.
-- 수정 가능
UPDATE engineering_employees
SET salary = 9000
WHERE name = 'park';
-- OK
-- 수정 불가능
UPDATE engineering_employees
SET department = 'HR'
WHERE name = 'lee';
정리하면 아래와 같다.
| 항목 | 설명 |
|---|---|
WITH CHECK OPTION 없음 | 뷰 조건과 관계없이 수정 가능 |
WITH CHECK OPTION 있음 | 뷰 조건을 벗어나는 수정은 금지됨 |
| 목적 | 뷰를 통한 데이터 무결성 보장 |
뷰는 권한 통제를 할 때도 사용할 수 있다.
-- 원본 테이블은 관리자만 접근 가능
GRANT SELECT ON engineering_employees TO 'readonly_user'@'%';
-- employees 테이블에 대한 권한은 안 줌
이렇게 하면 뷰만 접근 가능한 사용자를 만들 수 있다.
뷰는 항상 최신 데이터를 반영하지만 성능 이슈가 발생할 수 있다.