CREATE VIEW
Эта страница переведена при помощи нейросети GigaChat.
CREATE VIEW
– создание нового представления.
Синтаксис
CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW name [ ( column_name [, ...] ) ]
[ WITH ( view_option_name [= view_option_value] [, ... ] ) ]
AS query
[ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
Описание
CREATE VIEW
определяет представление на основе запроса. Представление не материализуется физически — вместо этого запрос выполняется каждый раз при обращении к представлению.
CREATE OR REPLACE VIEW
работает аналогично, но если представление с таким именем уже существует, оно заменяется. Новый запрос должен генерировать те же столбцы, что и существующее представление (то есть с теми же именами, в том же порядке и с теми же типами данных), но может добавлять дополнительные столбцы в конец списка. При этом сами вычисления для столбцов могут быть совершенно иными.
Если указано имя схемы (например, CREATE VIEW myschema.myview ...
), то представление создается в этой схеме. В противном случае оно создается в текущей схеме. Временные представления существуют в специальной схеме, поэтому имя схемы указывать нельзя при создании временного представления. Имя представления должно отличаться от имени любой другой сущности (таблицы, последовательности, индекса, представления, материализованного представления или внешней таблицы) в той же схеме.
Параметры
TEMPORARY
илиTEMP
- Создает представление как временное. Временные представления автоматически удаляются в конце текущей сессии. Существующие постоянные объекты с тем же именем не видны в текущей сессии, пока существует временное представление, если только к ним не обращаются с указанием схемы.
Если в определении представления упоминаются временные таблицы, представление также создается как временное (даже если
TEMPORARY
не указано).
RECURSIVE
- Создает рекурсивное представление. Синтаксис:
CREATE RECURSIVE VIEW [ schema . ] view_name (column_names) AS SELECT ...;
эквивалентен:
CREATE VIEW [ schema . ] view_name AS WITH RECURSIVE view_name (column_names) AS (SELECT ...) SELECT column_names FROM view_name;
Для рекурсивного представления необходимо указать список имен столбцов.
name
- Задает имя представления, при необходимости дополненное схемой, которое должно быть создано.
column_name
- Задает необязательный список имен для столбцов представления. Если не указан, имена столбцов выводятся из запроса.
WITH (view_option_name [= view_option_value] [, ... ])
- Задает дополнительные параметры представления. Поддерживаются следующие параметры:
check_option
(enum
) может принимать значенияlocal
илиcascaded
, эквивалентен использованиюWITH [ CASCADED | LOCAL ] CHECK OPTION
(смотрите ниже).security_barrier
(boolean
) используется, если представление предназначено для обеспечения построчной безопасности. Подробнее смотрите раздел «Правила и привилегии».security_invoker
(boolean
) – привилегии для доступа к базовым объектам проверяются относительно пользователя, выполняющего запрос, а не владельца представления. Подробности — в примечаниях.
Все эти параметры можно изменить с помощью команды ALTER VIEW.
WITH [ CASCADED | LOCAL ] CHECK OPTION
- Управляет поведением автоматически обновляемых представлений. Если указано, команды
INSERT
,UPDATE
иMERGE
будут проверять, удовлетворяют ли новые строки условиям, определенным в представлении (то есть являются ли они видимыми через представление). Если нет — операция будет отклонена. БезCHECK OPTION
можно вставить или изменить строки, которые не видны через представление. Поддерживаются следующие варианты:LOCAL
: Новые строки проверяются только по условиям, определенным в текущем представлении. Условия базовых представлений не проверяются (если только они тоже не используютCHECK OPTION
).CASCADED
: Новые строки проверяются по условиям текущего представления и всех базовых представлений. Если указаноCHECK OPTION
, но не заданоLOCAL
илиCASCADED
, по умолчанию используетсяCASCADED
.CHECK OPTION
не может использоваться с представлениямиRECURSIVE
.Также стоит учитывать, что
CHECK OPTION
поддерживается только для автоматически обновляемых представлений, в которых нет триггеровINSTEAD OF
или правилINSTEAD
. Если представление определено поверх базового представления с такими триггерами, можно использоватьLOCAL CHECK OPTION
для проверки условий на верхнем уровне, но условия нижнего уровня не будут проверяться.CASCADED CHECK OPTION
не применяется к представлениям с такими триггерами, и всеCHECK OPTION
, определенные в таких представлениях, игнорируются. Если представление или его базовые объекты содержат правилоINSTEAD
, переписывающее командуINSERT
илиUPDATE
, то всеCHECK OPTION
также будут проигнорированы в переписанном запросе, включая те, что определены в автоматически обновляемых представлениях поверх этих объектов. КомандаMERGE
не поддерживается, если для представления или любого из его базовых отношений определены правила.
Примечания
Для удаления представлений используйте команду DROP VIEW.
Будьте внимательны при определении имен и типов столбцов в представлении. Например:
CREATE VIEW vista AS SELECT 'Hello World';
— это плохая практика, так как имя столбца по умолчанию будет ?column?
, а тип данных — text
, что может быть не тем, что хотелось. Лучше оформить строковый литерал так:
CREATE VIEW vista AS SELECT text 'Hello World' AS hello;
По умолчанию доступ к базовым объектам, используемым в представлении, определяется правами владельца представления. Это поведение можно использовать для организации защищенного, но ограниченного доступа к таблицам. Однако не все представления надежны с точки зрения защиты от подмены — подробности смотрите в разделе «Правила и привилегии».
Если для представления установлено свойство security_invoker = true
, доступ к базовым объектам будет определяться правами пользователя, выполняющего запрос, а не владельца представления. То есть пользователь такого представления должен иметь необходимые права не только на само представление, но и на все его базовые объекты.
Если среди базовых объектов встречаются представления с security_invoker
, они обрабатываются так, как будто обращение к ним идет напрямую. Таким образом, при любом использовании такого представления права доступа будут проверяться для текущего пользователя, даже если вызов идет из обычного представления.
Если базовые объекты представления используют политику безопасности на уровне строк, то по умолчанию применяется политика владельца представления. Однако если включен security_invoker
, то проверка выполняется по политике и правам вызывающего пользователя, как будто он обращается к базовым объектам напрямую.
Функции, вызываемые внутри представления, обрабатываются так же, как если бы они вызывались напрямую. Пользователь, использующий представление, должен иметь права на вызов всех функций, используемых внутри. Функции выполняются с привилегиями пользователя, выполняющего запрос, или владельца функции — в зависимости от того, определены ли они как SECURITY INVOKER
или SECURITY DEFINER
. Например, вызов CURRENT_USER
внутри представления всегда вернет имя пользователя, выполнившего запрос, а не владельца представления. Это не зависит от значения security_invoker
, и потому представление с security_invoker = false
не является эквивалентом функции с SECURITY DEFINER
. Эти концепции не следует путать.
Пользователь, создающий или заменяющий представление, должен иметь привилегию USAGE
на все схемы, упомянутые в запросе представления, чтобы иметь возможность находить объекты в этих схемах. Однако это разрешение требуется только на момент создания или замены представления. В дальнейшем, при использовании представления, пользователю нужно привилегию USAGE
только на схему, содержащую само представление — даже если оно использует security_invoker
.
При использовании CREATE OR REPLACE VIEW
изменяется только определяющий запрос SELECT
, параметры WITH (...)
и параметр CHECK OPTION
. Другие свойства, включая владельца, разрешения и правила, отличные от SELECT
, остаются неизменными. Для замены представления необходимо быть его владельцем (или состоять в роли владельце).
Обновляемые представления
Простые представления являются автоматически обновляемыми: система позволяет выполнять команды INSERT
, UPDATE
, DELETE
и MERGE
над представлением так же, как и над обычной таблицей. Представление считается автоматически обновляемым, если выполняются все следующие условия:
- В списке
FROM
представления должен быть ровно один элемент, и он должен быть таблицей или другим обновляемым представлением. - Определение представления не должно содержать на верхнем уровне выражений
WITH
,DISTINCT
,GROUP BY
,HAVING
,LIMIT
илиOFFSET
. - Определение представления не должно содержать на верхнем уровне операции объединения множеств:
UNION
,INTERSECT
илиEXCEPT
. - В списке выбираемых столбцов не должно быть агрегатных функций, оконных функций и функций, возвращающих множество строк.
Автоматически обновляемое представление может содержать как обновляемые, так и необновляемые столбцы. Столбец считается обновляемым, если он представляет собой простую ссылку на обновляемый столбец базовой таблицы. В противном случае столбец считается только для чтения, и при попытке выполнения INSERT
или UPDATE
, затрагивающих такой столбец, будет выдана ошибка.
Если представление является автоматически обновляемым, система преобразует любую команду INSERT
, UPDATE
, DELETE
и MERGE
, выполненную над представлением, в соответствующую команду над базовой таблицей. Также полностью поддерживаются операторы INSERT ... ON CONFLICT UPDATE
.
Если представление содержит условие WHERE
, оно ограничивает, какие строки базовой таблицы могут быть модифицированы через UPDATE
, DELETE
или MERGE
. Однако:
UPDATE
илиMERGE
могут изменить строку так, что она перестанет удовлетворять условиюWHERE
и больше не будет отображаться через представление.INSERT
иMERGE
могут добавить строки в базовую таблицу, которые не проходят условие WHERE, и значит не отображаются в представлении.ON CONFLICT UPDATE
также может модифицировать строки, невидимые через представление.
Чтобы запретить такие действия, можно использовать CHECK OPTION
— оно обеспечит, что команды INSERT
, UPDATE
и MERGE
не создают строк, невидимых через представление.
Если представление помечено параметром security_barrier
, то все его условия WHERE
(а также условия, использующие операторы с атрибутом LEAKPROOF
) будут всегда выполняться раньше, чем условия WHERE
, добавленные пользователем представления. Подробнее смотрите в разделе «Правила и привилегии». Из-за этого строки, которые не будут возвращены (так как не пройдут пользовательское условие), могут все же быть заблокированы. Для анализа этого поведения можно использовать EXPLAIN
, чтобы увидеть, какие условия применяются на уровне отношения (и не блокируют строки), а какие — нет.
Сложное представление, не удовлетворяющее этим условиям, по умолчанию является только для чтения: система не позволит выполнять над ним INSERT
, UPDATE
, DELETE
или MERGE
. Чтобы сделать такое представление обновляемым, можно создать триггеры типа INSTEAD OF
, которые будут перехватывать операции и преобразовывать их в действия над другими таблицами. Подробнее смотрите в описании CREATE TRIGGER. Еще один способ — использовать правила (CREATE RULE), но на практике триггеры проще и надежнее в использовании. Кроме того, команда MERGE
не поддерживается для отношений с правилами.
Также стоит учитывать следующее:
- Пользователь, выполняющий
INSERT
,UPDATE
илиDELETE
, должен иметь соответствующие права на представление. - По умолчанию, владелец представления должен иметь соответствующие привилегии на базовые таблицы, в то время как пользователь, выполняющий операцию, не обязан иметь какие-либо привилегии на базовые объекты (смотрите раздел «Правила и привилегии»).
- Однако если у представления установлен
security_invoker = true
, то права доступа к базовым таблицам должны быть у пользователя, выполняющего операцию, а не у владельца представления.
Примеры
Создание представления, содержащего все комедийные фильмы:
CREATE VIEW comedies AS
SELECT *
FROM films
WHERE kind = 'Comedy';
Эта команда создаст представление со столбцами, которые содержались в таблице film
в момент выполнения команды. Хотя при создании представления было указано *
, столбцы, добавляемые в таблицу позже, частью представления не будут.
Создание представления с указанием LOCAL CHECK OPTION
:
CREATE VIEW universal_comedies AS
SELECT *
FROM comedies
WHERE classification = 'U'
WITH LOCAL CHECK OPTION;
Эта команда создаст представление на базе представления comedies
, выдающее только комедии (kind = 'Comedy'
) универсальной возрастной категории classification = 'U'
. Любая попытка выполнить в представлении INSERT
или UPDATE
со строкой, не удовлетворяющей условию classification = 'U'
, будет отвергнута, но ограничение по полю kind
(тип фильма) проверяться не будет.
Создание представления с указанием CASCADED CHECK OPTION
:
CREATE VIEW pg_comedies AS
SELECT *
FROM comedies
WHERE classification = 'PG'
WITH CASCADED CHECK OPTION;
Это представление будет проверять, удовлетворяют ли новые строки обоим условиям: по столбцу kind
и по столбцу classification
.
Создание представления с изменяемыми и неизменяемыми столбцами:
CREATE VIEW comedies AS
SELECT f.*,
country_code_to_name(f.country_code) AS country,
(SELECT avg(r.rating)
FROM user_ratings r
WHERE r.film_id = f.id) AS avg_rating
FROM films f
WHERE f.kind = 'Comedy';
Это представление будет поддерживать операции INSERT
, UPDATE
и DELETE
. Изменяемыми будут все столбцы из таблицы films
, тогда как вычисляемые столбцы country
и avg_rating
будут доступны только для чтения.
Создание рекурсивного представления, содержащего числа от 1 до 100:
CREATE RECURSIVE VIEW public.nums_1_100 (n) AS
VALUES (1)
UNION ALL
SELECT n+1 FROM nums_1_100 WHERE n < 100;
Заметьте, что несмотря на то, что имя рекурсивного представления дополнено схемой в этой команде CREATE
, внутренняя ссылка представления на себя же схемой не дополняется. Это связано с тем, что имя неявно создаваемого CTE не может дополняться схемой.
Совместимость
CREATE OR REPLACE VIEW
— это расширение PostgreSQL. Концепция временного представления также является расширением. Выражение WITH ( ... )
, представления с ограничением безопасности и представления с вызовом от имени пользователя также являются расширениями PostgreSQL.