SQL-представления — секрет чистой схемы. Рассказали, как одним view заменить гору JOIN, скрыть лишние поля и ускорить разработку на VPS.
Введение
Представления (views) в SQL — это виртуальные таблицы, то есть результат выполнения заранее заданного запроса, сохранённый в базе под отдельным именем. При обращении к представлению сервер базы данных каждый раз выполняет его внутренний SQL-запрос и возвращает актуальные данные. Никакие новые сведения физически не хранятся, представление лишь собирает информацию из существующих таблиц на лету.
В материале рассказали, как работают представления на практике и чем они могут быть полезны, особенно если у вас собственный VPS или выделенный сервер. На своём сервере такие инструменты особенно полезны, ведь вы полностью управляете СУБД и можете настроить дополнительные views под нужды приложений.
Преимущества и особенности представлений
Зачем нужны представления, если можно просто выполнять SQL-запросы напрямую? Дело в том, что представление значительно упрощает работу с данными. Оно выглядит для пользователя как обычная таблица, хотя на самом деле является лишь логическим слоем поверх информации.
Если запрос к базе объединяет несколько таблиц или содержит сложные условия, его можно сохранить как представление. Вместо того чтобы каждый раз писать длинный JOIN или подзапрос, вы обращаетесь к представлению одним коротким запросом SELECT. Это экономит время и снижает вероятность ошибок. Например, в крупных интернет-магазинах часто приходится объединять данные о клиентах и их заказах. Вместо того чтобы каждый раз вручную соединять таблицы Customers и Orders, можно один раз создать представление orders_info и потом запрашивать его как обычную таблицу.
Представления помогают показывать пользователю или приложению только необходимую информацию. Можно создать урезанную версию таблицы, включив в представление лишь некоторые столбцы или строки, и выдать доступ только к нему. Так конфиденциальные данные останутся скрытыми. Например, банк может подготовить представление с информацией по счетам клиентов (без личных данных) и дать доступ к нему операторам кол-центра. Сотрудники будут видеть только предусмотренные поля.
Представление служит единым источником определённых данных для разных частей приложения. Если логика отбора меняется, достаточно поправить запрос представления, и все обращения к нему сразу начнут выдавать новый результат. Это проще, чем переписывать десятки SQL-запросов по всему проекту. Команда view позволяет дать понятное имя сложной выборке. Вместо длинного запроса с множеством условий вы оперируете лаконичным именем, а код становится чище.
Учтите, что представление само по себе не ускоряет выполнение запросов — при обращении к нему СУБД всё равно прогоняет исходный SELECT. Вы выигрываете в удобстве, но не во времени. Существуют и материализованные представления, которые сохраняют результат, но классические views всегда формируются на лету и показывают актуальное состояние базовых таблиц.
Создание представления
Чтобы создать новое представление, используйте команду CREATE VIEW: задайте имя и укажите запрос, результат которого будет возвращаться. Например, создайте простое представление для выборки клиентов из таблицы Customers, которые проживают в России:
CREATE VIEW ru_customers AS
SELECT customer_id, first_name, last_name, status
FROM Customers
WHERE country = 'Russia';
Представление ru_customers создано с запросом к таблице Customers. Чтобы получить всех клиентов из России, выполните запрос SELECT * FROM ru_customers — база подставит сохранённое условие и вернёт тот же результат, что и при прямом обращении к Customers с фильтром. Представление особенно выручает, когда необходимо объединять данные из нескольких таблиц: сложность соединения (JOIN) скрывается за простым именем. Допустим, в базе интернет-магазина есть две таблицы — Customers (покупатели) и Orders (заказы). Вместо того чтобы каждый раз писать запрос с JOIN, достаточно один раз создать представление, сразу содержащее нужные связи:
CREATE VIEW orders_info AS
SELECT Customers.first_name, Customers.last_name, Orders.order_id,
Orders.amount
FROM Customers
JOIN Orders ON Orders.customer_id = Customers.customer_id;
В результате получается виртуальная таблица со столбцами из обеих исходных таблиц. Один запрос к orders_info вернёт список всех заказов с именами покупателей. Это гораздо удобнее, чем каждый раз вручную составлять длинный объединённый запрос.
Изменение представления
Определение представления изменяется при необходимости. Например, решено, что orders_info должен включать дату заказа. В MySQL и других системах для этого служит команда CREATE OR REPLACE VIEW. Она создаёт новое представление, если его ещё не было, или обновляет запрос для существующего. Добавьте в orders_info поле даты заказа:
CREATE OR REPLACE VIEW orders_info AS
SELECT Customers.first_name, Customers.last_name, Orders.order_id, Orders.amount,
Orders.order_date
FROM Customers
JOIN Orders ON Orders.customer_id = Customers.customer_id;
Определение orders_info обновлено: теперь представление включает столбец order_date. Все последующие запросы к orders_info сразу вернут и дату заказа наряду с остальными колонками. Помните: CREATE OR REPLACE полностью перезаписывает запрос представления, поэтому важно указать корректный SQL, иначе есть риск испортить объект.
Удаление представления
Когда представление перестаёт быть нужным, удалите его, чтобы схема базы не разрасталась лишними объектами. Сделать это поможет команда DROP VIEW. Например:
DROP VIEW ru_customers;
Команда уничтожает виртуальную таблицу ru_customers, сохранив все данные в таблице Customers — удаляется только сохранённый запрос. После выполнения DROP VIEW СУБД моментально забывает о представлении, поэтому обращения к нему начнут возвращать ошибку relation does not exist.
Перед удалением убедитесь, что представление не используется в отчётах, триггерах или коде приложения, иначе встроенные запросы потеряют опору. Если зависимостей много, сначала пересмотрите функции и процедуры или временно замените представление заглушкой. Дополнительно проверьте права доступа: при удалении объекта СУБД автоматически сбрасывает связанные GRANT-разрешения, так что после повторного создания представления придётся заново выдавать права нужным пользователям. Такой подход помогает держать базу в чистоте и упрощает сопровождение, особенно когда база живёт на собственном VPS и порядок в схеме полностью зависит от действий администратора.
Обновление данных через представление
Использовать представление можно не только для чтения, но и для изменения данных. Да, некоторые представления обновляемы — выполняйте INSERT, UPDATE или DELETE, ссылаясь на представление, и СУБД внесёт изменения в базовую таблицу. Это работает при соблюдении условий: представление построено на одной таблице и не содержит сложных элементов вроде агрегатных функций, DISTINCT, GROUP BY, подзапросов или соединений. Все обязательные столбцы базовой таблицы (NOT NULL без значения по умолчанию) должны входить в представление.
Если условия выполнены, меняйте данные через view без сложностей. Допустим, есть представление ru_customers, основанное на таблице Customers. Измените статус клиента так:
UPDATE ru_customers
SET status = 'VIP'
WHERE customer_id = 123;
Запрос найдёт в ru_customers запись с customer_id = 123 и присвоит ей статус 'VIP', обновив соответствующую строку в Customers. Аналогично, DELETE FROM ru_customers WHERE ... удалит строку из Customers, а INSERT INTO ru_customers (...) VALUES (...) добавит новую запись при соблюдении ограничений целостности.
Используйте опцию WITH CHECK OPTION при создании представления с условием WHERE, чтобы база блокировала изменения, нарушающие фильтр. Например, в ru_customers с условием country = 'Russia' опция WITH CHECK OPTION запретит изменение поля country через это представление на любое другое значение.
Ограничение доступа с помощью представлений
Используйте представление для ограничения доступа. Допустим, в базе есть таблица Employees с информацией о сотрудниках, например, отдел и оклад. Чтобы скрыть зарплаты, создайте представление без этого столбца:
CREATE VIEW dept_staff AS
SELECT id, name, department
FROM Employees;
Затем выдайте конкретному пользователю доступ только к dept_staff, не открывая прямой доступ к Employees. Воспользуйтесь командой GRANT:
GRANT SELECT ON mydatabase.dept_staff TO 'boss_user'@'localhost';
Пользователь boss_user сможет выбирать данные через представление, но не из таблицы Employees — зарплаты останутся скрытыми, будет виден лишь список сотрудников и их отделов.
Заключение
SQL-представления превращают базу данных в гибкий конструктор: лишние столбцы скрываются, громоздкие JOIN-ы заменяются лаконичным SELECT, а схема остаётся аккуратной. Создание, обновление и удаление представлений выполняется без лишних усилий, поэтому управление данными становится более прозрачным. Эксперименты с представлениями поддерживают чистоту кода и помогают каждой выборке отрабатывать точно так, как задумано.
Читайте в блоге:
- Защита веб-приложения от SQL-инъекций
- Как сделать бекап PostgreSQL на удалённое хранилище
- Как объединить таблицы в SQL для отчётов и анализа