Представления в SQL
Представление — это виртуальная таблица, определение которой хранится в базе данных. Но в отличие от таблиц представления не содержат никаких данных. Вместо этого они обеспечивают способ хранения в базе данных часто используемых сложных запросов.
Представление можно использовать в операторе SELECT
для доступа к данным так же, как и обычную таблицу.
Представления также используются в качестве механизма безопасности, то есть позволяют пользователям получать доступ к данным через представление, но не дают им прямой доступ ко всем базовым таблицам.
Синтаксис
Представления создаются при помощи выражения CREATE VIEW
.
CREATE VIEW название_представления AS выражение_SELECT;
Чтобы понять принцип действия этого выражения, давайте обратимся к таблицам employees и departments.
Таблица employees |
Таблица departments |
+--------+--------------+------------+---------+ | emp_id | emp_name | hire_date | dept_id | +--------+--------------+------------+---------+ | 1 | Ethan Hunt | 2001-05-01 | 4 | | 2 | Tony Montana | 2002-07-15 | 1 | | 3 | Sarah Connor | 2005-10-18 | 5 | | 4 | Rick Deckard | 2007-01-03 | 3 | | 5 | Martin Blank | 2008-06-24 | NULL | +--------+--------------+------------+---------+ |
+---------+------------------+ | dept_id | dept_name | +---------+------------------+ | 1 | Administration | | 2 | Customer Service | | 3 | Finance | | 4 | Human Resources | | 5 | Sales | +---------+------------------+ |
Предположим, что вы хотите получить идентификатор и имя сотрудников вместе с названием их отдела. Для этого можно выполнить объединение LEFT JOIN
, как показано ниже:
SELECT t1.emp_id, t1.emp_name, t2.dept_name
FROM employees AS t1 LEFT JOIN departments AS t2
ON t1.dept_id = t2.dept_id;
После выполнения этого запроса вы получите следующий результат:
+--------+--------------+-----------------+ | emp_id | emp_name | dept_name | +--------+--------------+-----------------+ | 1 | Ethan Hunt | Human Resources | | 2 | Tony Montana | Administration | | 3 | Sarah Connor | Sales | | 4 | Rick Deckard | Finance | | 5 | Martin Blank | NULL | +--------+--------------+-----------------+
Проблема в том, что каждый раз для доступа к этой записи вам придется набирать весь запрос заново. Если нужно выполнять такие операции довольно часто, это неудобно.
В такой ситуации можно создать представление для облегчения доступа к результатам запроса, как показано ниже:
CREATE VIEW emp_dept_view AS
SELECT t1.emp_id, t1.emp_name, t2.dept_name
FROM employees AS t1 LEFT JOIN departments AS t2
ON t1.dept_id = t2.dept_id;
Теперь можно получить доступ к тем же записям через представление emp_dept_view
:
SELECT * FROM emp_dept_view;
Обратите внимание, сколько времени можно сэкономить с помощью представлений.
Примечание. Представление всегда показывает актуальные данные. При каждом запросе к представлению механизм базы данных выполняет SQL-запрос, связанный с представлением, и воссоздает данные.
Примечание. В MySQL можно указать
ORDER BY
в определении представления. А в SQL Sever так не получится, если в select-списке нет предложенияTOP
.
Замена существующего представления
В MySQL, если вы хотите обновить или заменить существующее представление, есть два варианта:
- удалить это представление и создать новое,
- использовать выражение
OR REPLACE
в оператореCREATE VIEW
, как показано ниже:
CREATE OR REPLACE VIEW название_представления AS выражение_SELECT;
Примечание. Когда в операторе
CREATE VIEW
используется операторOR REPLACE
, он создает новое представление — при условии, что оно не существует. В противном случае он просто заменяет существующее представление.
Следующий оператор SQL заменит или изменит определение существующего представления emp_dept_view
, добавив в него новый столбец salary
.
CREATE OR REPLACE VIEW emp_dept_view AS
SELECT t1.emp_id, t1.emp_name, t1.salary, t2.dept_name
FROM employees AS t1 LEFT JOIN departments AS t2
ON t1.dept_id = t2.dept_id;
После обновления представления, если вы выполните следующий оператор:
SELECT * FROM emp_dept_view ORDER BY emp_id;
вы увидите еще один столбец зарплаты в выводе, как показано ниже:
+--------+--------------+--------+-----------------+ | emp_id | emp_name | salary | dept_name | +--------+--------------+--------+-----------------+ | 1 | Ethan Hunt | 5000 | Human Resources | | 2 | Tony Montana | 6500 | Administration | | 3 | Sarah Connor | 8000 | Sales | | 4 | Rick Deckard | 7200 | Finance | | 5 | Martin Blank | 5600 | NULL | +--------+--------------+--------+-----------------+
Обновление данных через представление
Теоретически помимо SELECT
для представлений можно использовать INSERT
, UPDATE
и DELETE
. Однако не все представления являются обновляемыми, т.е. способными изменять данные базовой исходной таблицы. Существуют некоторые ограничения на возможность обновления.
Как правило, представление не является обновляемым, если оно содержит что-либо из перечисленного ниже:
-
Выражения
DISTINCT
,GROUP BY
илиHAVING
. -
Агрегатные функции, такие как
AVG()
,COUNT()
,SUM()
,MIN()
,MAX()
и так далее. -
Операторы
UNION
,UNION ALL
,CROSSJOIN
,EXCEPT
илиINTERSECT
. -
Подзапрос в выражении
WHERE
, который ссылается на таблицу в выраженииFROM
.
Если представление удовлетворяет этим условиям, вы можете изменить исходную таблицу с помощью этого представления.
Следующий оператор обновит зарплату сотрудника с emp_id
равным 1.
UPDATE emp_dept_view SET salary = '6000'
WHERE emp_id = 1;
Примечание. Представление должно содержать все столбцы базовой таблицы, которые не имеют значения по умолчанию, чтобы в него можно было вставить новые значения. Аналогично для возможности обновления каждый обновляемый столбец в представлении должен соответствовать обновляемому столбцу в исходной таблице.
Удаление представления
Если вам больше не нужно представление, вы можете использовать оператор DROP VIEW
, чтобы удалить его из базы данных, как показано ниже:
DROP VIEW имя_представления;
Следующая команда удалит представление emp_dept_view
из базы данных:
DROP VIEW emp_dept_view;