Представления
Представление (view) — именованный SQL-запрос, сохраненный в базу данных. Представление не хранит данные, а читает их из другой таблицы каждый раз, когда к нему обращаются. По сути, при чтении из представления определяющий его запрос используется как подзапрос в выражении FROM. Представления позволяют сохранять часто используемые или сложные запросы и использовать их в запросах SELECT как обычные таблицы.
Параметризованное представление (parameterized view) — представление с параметрами в условии фильтрации определяющего его запроса, значения которых должны передаваться при каждом обращении к представлению. Параметризованные представления могут быть удобны, когда нужно многократно использовать сложные аналитические запросы с переменными условиями фильтрации.
ADQM/ClickHouse также поддерживает материализованные представления (materialized view), которые в отличие от обычных представлений физически хранят данные (агрегатные состояния данных другой таблицы) и обновляются автоматически при вставке новых данных в исходную таблицу — подробнее в статье Материализованные представления.
| Тип представления | Хранение данных | Параметры | Производительность запросов | Обновление представления |
|---|---|---|---|---|
Представление |
Нет |
Нет |
Не меняется (запрос выполняется каждый раз при обращении к представлению) |
При каждом обращении к представлению |
Параметризованное представление |
Нет |
Да |
Не меняется (запрос выполняется при каждом обращении к представлению) |
При каждом обращении к представлению |
Материализованное представление |
Да |
Нет |
Повышается (быстрое чтение за счет предварительной агрегации данных) |
При вставке данных в исходную таблицу |
Создайте таблицу sales и заполните ее тестовыми данными о продажах:
CREATE TABLE sales (
sale_id UInt32,
product_name String,
sale_amount Decimal(10,2),
customer_name String,
sale_date Date
)
ENGINE = MergeTree()
ORDER BY sale_id;
INSERT INTO sales VALUES
(1, 'Smartphone_2', 700.00, 'Mary Burton', '2026-04-15'),
(2, 'Smartphone_1', 750.00, 'Robert Gray', '2026-04-17'),
(3, 'Monitor', 200.00, 'Linda Black', '2026-04-17'),
(4, 'Laptop', 1000.00, 'Paul Brown', '2026-04-17'),
(5, 'Monitor', 200.00, 'Mark Armstrong', '2026-04-18'),
(6, 'Keyboard', 75.50, 'David Green', '2026-04-18'),
(7, 'Keyboard', 75.50, 'Daniel Gray', '2026-05-01'),
(8, 'Laptop', 1000.00, 'Robert Gray', '2026-05-02'),
(9, 'Mouse', 25.50, 'Joseph Lewis', '2026-05-02'),
(10, 'Smartphone_2', 700.00, 'Paul Brown', '2026-05-03');
┌─sale_id─┬─product_name─┬─sale_amount─┬─customer_name──┬──sale_date─┐
1. │ 1 │ Smartphone_2 │ 700 │ Mary Burton │ 2026-04-15 │
2. │ 2 │ Smartphone_1 │ 750 │ Robert Gray │ 2026-04-17 │
3. │ 3 │ Monitor │ 200 │ Linda Black │ 2026-04-17 │
4. │ 4 │ Laptop │ 1000 │ Paul Brown │ 2026-04-17 │
5. │ 5 │ Monitor │ 200 │ Mark Armstrong │ 2026-04-18 │
6. │ 6 │ Keyboard │ 75.5 │ David Green │ 2026-04-18 │
7. │ 7 │ Keyboard │ 75.5 │ Daniel Gray │ 2026-05-01 │
8. │ 8 │ Laptop │ 1000 │ Robert Gray │ 2026-05-02 │
9. │ 9 │ Mouse │ 25.5 │ Joseph Lewis │ 2026-05-02 │
10. │ 10 │ Smartphone_2 │ 700 │ Paul Brown │ 2026-05-03 │
└─────────┴──────────────┴─────────────┴────────────────┴────────────┘
Создание представлений
Создание представления
Чтобы создать представление, используйте запрос CREATE VIEW. Синтаксис в общем виде:
CREATE VIEW [IF NOT EXISTS] [<db_name>.]<view_name> [ON CLUSTER <cluster_name>]
[DEFINER = { '<user_name>' | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }]
AS SELECT ...
[COMMENT 'comment'];
где DEFINER и SQL SECURITY — параметры для управления доступом к данным (см. описание ниже).
|
ПРИМЕЧАНИЕ
Табличная функция |
Пример
Создайте представление, которое получает данные о продажах в мае:
CREATE VIEW sales_may AS
SELECT * FROM sales
WHERE toMonth(sale_date) = 5;
Запросы к представлению можно выполнять как к обычной таблице с помощью SELECT:
SELECT * FROM sales_may;
┌─sale_id─┬─product_name─┬─sale_amount─┬─customer_name─┬──sale_date─┐ 1. │ 7 │ Keyboard │ 75.5 │ Daniel Gray │ 2026-05-01 │ 2. │ 8 │ Laptop │ 1000 │ Robert Gray │ 2026-05-02 │ 3. │ 9 │ Mouse │ 25.5 │ Joseph Lewis │ 2026-05-02 │ 4. │ 10 │ Smartphone_2 │ 700 │ Paul Brown │ 2026-05-03 │ └─────────┴──────────────┴─────────────┴───────────────┴────────────┘
Создание параметризованного представления
Параметризованное представление создается как обычное представление, но в условии WHERE указываются параметры в виде {<param_name>:<param_type>}, например:
CREATE VIEW [IF NOT EXISTS] [<db_name>.]<view_name> [ON CLUSTER <cluster_name>]
[DEFINER = { '<user_name>' | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }]
AS SELECT ...
WHERE <column_name1> = {<param_name1>:<data_type1>} AND <column_name2> != {<param_name2>:<data_type2>} ...
[COMMENT 'comment'];
где <param_name1>, <param_name2> — имена параметров; <data_type1>, <data_type2> — типы данных параметров.
Значения параметров необходимо передавать при каждом обращении к представлению в следующем формате:
SELECT <list_of_columns> FROM <view_name>(<param_name1>=<value1>, <param_name2>=<value2>, ...);
Таким образом, параметризованное представление вызывается как табличная функция — имя представления используется как имя функции, а значения параметров передаются в виде ее именованных аргументов.
Пример
Создайте параметризованное представление, которое получает данные о продажах указанного продукта за указанные месяц:
CREATE VIEW sales_product_by_month AS
SELECT * FROM sales
WHERE product_name = {product:String} AND toMonth(sale_date) = {month:UInt8};
При обращении к представлению необходимо передавать имя продукта и номер месяца как значения параметров product и month соответственно:
SELECT * FROM sales_product_by_month(product='Monitor', month=4);
┌─sale_id─┬─product_name─┬─sale_amount─┬─customer_name──┬──sale_date─┐ 1. │ 3 │ Monitor │ 200 │ Linda Black │ 2026-04-17 │ 2. │ 5 │ Monitor │ 200 │ Mark Armstrong │ 2026-04-18 │ └─────────┴──────────────┴─────────────┴────────────────┴────────────┘
SQL SECURITY и DEFINER
Параметры SQL SECURITY и DEFINER, которые можно указывать при создании представлений, позволяют гибко настраивать доступ к данным. Например, можно скрыть от пользователей исходные таблицы (данные из которых читают представления), предоставив им при этом доступ к агрегированным или отфильтрованным данным через представления.
| Параметр | Описание | Возможные значения |
|---|---|---|
SQL SECURITY |
Указывает, права какого пользователя будут использоваться при выполнении запроса, определяющего представление |
|
DEFINER |
Указывает, права какого пользователя будут использоваться при выполнении запроса представления, если установлено Чтобы установить значение параметра, у создающего представление пользователя должна быть привилегия |
|
Независимо от того, как настроены параметры разграничения доступа, для чтения данных из представления пользователю требуется разрешение SELECT ON <view_name>.
Пример
Предположим, доступ ко всем данным таблицы sales может иметь только администратор (пользователь admin, который создал эту таблицу), а другие пользователи могут получать данные о продажах без имен покупателей. Чтобы реализовать этот сценарий, выполните следующие шаги:
-
Создайте нового пользователя:
CREATE USER john IDENTIFIED WITH sha256_password BY 'qwerty'; -
От имени администратора создайте представление, которое читает все данные о продажах из таблицы
salesкроме имен покупателей:CREATE VIEW sales_without_customers DEFINER = admin SQL SECURITY DEFINER AS SELECT sale_id, product_name, sale_amount, sale_date FROM sales; -
Выдайте пользователю
johnдоступ к этому представлению:GRANT SELECT ON sales_without_customers TO john; -
Обратитесь к представлению от имени пользователя
john:SELECT * FROM sales_without_customers;Пользователю
johnбудут доступны данные о продажах без информации о покупателях через представлениеsales_without_customers:┌─sale_id─┬─product_name─┬─sale_amount─┬──sale_date─┐ 1. │ 1 │ Smartphone_2 │ 700 │ 2026-04-15 │ 2. │ 2 │ Smartphone_1 │ 750 │ 2026-04-17 │ 3. │ 3 │ Monitor │ 200 │ 2026-04-17 │ 4. │ 4 │ Laptop │ 1000 │ 2026-04-17 │ 5. │ 5 │ Monitor │ 200 │ 2026-04-18 │ 6. │ 6 │ Keyboard │ 75.5 │ 2026-04-18 │ 7. │ 7 │ Keyboard │ 75.5 │ 2026-05-01 │ 8. │ 8 │ Laptop │ 1000 │ 2026-05-02 │ 9. │ 9 │ Mouse │ 25.5 │ 2026-05-02 │ 10. │ 10 │ Smartphone_2 │ 700 │ 2026-05-03 │ └─────────┴──────────────┴─────────────┴────────────┘При этом у пользователя
johnнет прямого доступа к таблицеsales. Если попытаться прочитать данные из таблицыsalesот его имени, будет выведено сообщение:Exception: Received from localhost:9000. DB::Exception: john: Not enough privileges. To execute this query, it's necessary to have the grant SELECT(sale_id, product_name, sale_amount, customer_name, sale_date) ON default.sales. (ACCESS_DENIED)
Изменение представлений
Изменение запроса представления
Если необходимо изменить запрос, который определяет представление, используйте команду CREATE OR REPLACE VIEW:
CREATE OR REPLACE VIEW [<db_name>.]<view_name> AS SELECT ...
Если представление с таким именем существует, оно обновится в соответствии с новым определением его внутреннего запроса. Если представление не существует, то оно будет создано.
Изменение SQL SECURITY и DEFINER
Чтобы изменить настройки SQL SECURITY и DEFINER для существующего представления, используйте команду ALTER TABLE:
ALTER TABLE <view_name> MODIFY SQL SECURITY { DEFINER | INVOKER } [DEFINER = { '<user_name>' | CURRENT_USER }];
Получение информации о представлениях
Получить информацию о представлениях в базе данных ADQM/ClickHouse можно несколькими способами.
-
Посмотреть все таблицы и представления (см. столбец
engine— для реализации представлений используется табличный движокView):SHOW FULL TABLES;┌─name────────────────────┬─engine────┐ 1. │ sales │ MergeTree │ 2. │ sales_may │ View │ 3. │ sales_product_by_month │ View │ 4. │ sales_without_customers │ View │ └─────────────────────────┴───────────┘
-
Получить детальную информацию о представлениях можно из системной таблицы system.tables. Например, могут быть полезны столбцы:
-
as_select— запрос, определяющий представление; -
parameterized_view_parameters— параметры параметризованного представления; -
definer— пользователь, с правами которого выполняется запрос представления.
SELECT name, as_select, parameterized_view_parameters, definer FROM system.tables WHERE engine = 'View' AND database = '<database_name>';\GRow 1: ────── name: sales_may as_select: SELECT * FROM default.sales WHERE toMonth(sale_date) = 5 parameterized_view_parameters: [] definer: Row 2: ────── name: sales_product_by_month as_select: SELECT * FROM default.sales WHERE (product_name = {product:String}) AND (toMonth(sale_date) = {month:UInt8}) parameterized_view_parameters: [('product','String'),('month','UInt8')] definer: Row 3: ────── name: sales_without_customers as_select: SELECT sale_id, product_name, sale_amount, sale_date FROM default.sales parameterized_view_parameters: [] definer: admin -
-
Посмотреть запрос
CREATE VIEW, с помощью которого было создано конкретное представление:SHOW CREATE VIEW <view_name>;Пример вывода на экран для представления
sales_without_customers:┌─statement───────────────────────────────────┐ 1. │ CREATE VIEW default.sales_without_customers │ │ ( │ │ `sale_id` UInt32, │ │ `product_name` String, │ │ `sale_amount` Decimal(10, 2), │ │ `sale_date` Date │ │ ) │ │ DEFINER = admin SQL SECURITY DEFINER │ │ AS SELECT │ │ sale_id, │ │ product_name, │ │ sale_amount, │ │ sale_date │ │ FROM default.sales │ └─────────────────────────────────────────────┘
-
Информацию о представлениях можно также посмотреть в таблице
VIEWSсистемной базы данныхINFORMATION_SCHEMA:SELECT table_name, view_definition FROM information_schema.views WHERE table_schema = '<your_database_name>';┌─table_name──────────────┬─view_definition──────────────────────────────────────────────────────────────────────────────────────────────┐ 1. │ sales_may │ SELECT * FROM default.sales WHERE toMonth(sale_date) = 5 │ 2. │ sales_product_by_month │ SELECT * FROM default.sales WHERE (product_name = {product:String}) AND (toMonth(sale_date) = {month:UInt8}) │ 3. │ sales_without_customers │ SELECT sale_id, product_name, sale_amount, sale_date FROM default.sales │ └─────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Отключение и подключение представлений
Представление можно отключить с помощью запроса DETACH VIEW:
DETACH VIEW [IF EXISTS] [<db_name.]<view_name> [ON CLUSTER <cluster_name>] [PERMANENTLY];
При выполнении этого запроса представление становится "невидимым" для сервера (перестает быть доступным для запросов), но его метаданные не удаляются. Если отключение не было перманентным (ключевое слово PERMANENTLY не использовалось в запросе), при следующем запуске сервер прочитает метаданные и снова будет "видеть" представление. Если представление было отключено перманентно, то сервер не подключит его обратно автоматически.
Независимо от того, каким способом представление было отключено, его можно подключить обратно с помощью запроса ATTACH TABLE:
ATTACH TABLE [IF NOT EXISTS] [<db_name.]<view_name> [ON CLUSTER <cluster_name>];