CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]

[DEFINER = {user | CURRENT_USER}]

[SQL SECURITY {DEFINER | INVOKER}]

VIEW view_name [(column_list)]

AS select_statement

[WITH [CASCADED | LOCAL] CHECK OPTION]

Эта инструкция создает новый view или заменяет существующий, если дано предложение OR REPLACE. Инструкция SELECT select_statement обеспечивает определение view. Инструкция может выбирать из основных таблиц или других views.

Эта инструкция требует привилегии CREATE VIEW для view и некоторой привилегии для каждого столбца, выбранного инструкцией SELECT. Для столбцов, используемых в другом месте в инструкции SELECT, Вы должны иметь привилегию SELECT. Если присутствует предложение OR REPLACE, Вы должны также иметь привилегию DROP для view.

Каждый view принадлежит базе данных. По умолчанию, новый view создан в заданной по умолчанию базе данных. Чтобы явно создавать view в указанной базе данных, определите его имя как db_name.view_name.

mysql> CREATE VIEW test.v AS SELECT * FROM t;

Основные таблицы и views совместно используют то же самое пространство имен внутри базы данных, так что база данных не может содержать основную таблицу и view, которые имеют то же самое имя.

Views должны иметь уникальные имена столбца без дубликатов, точно так же, как основные таблицы. По умолчанию, имена столбцов, найденных инструкцией SELECT используются для имени столбца view. Чтобы определять явные имена для столбцов view, может быть задано факультативное предложение column_list как список разделяемых запятой идентификаторов. Число имен в column_list должно быть таким же, как число столбцов, найденных командой SELECT.

Столбцы, найденные инструкцией SELECT, могут быть простыми ссылками к столбцам таблицы. Они также могут быть выражениями, которые используют функции, постоянные значения, операторы и т.д.

Неквалифицированная таблица или имя view в операторе SELECT интерпретируется относительно заданной по умолчанию базы данных. view может обратиться к таблицам или view в других базах данных, квалифицируя имя таблицы или view с соответствующим именем базы данных.

view может быть создан из многих видов инструкций SELECT. Он может обратиться к основным таблицам или другим view. Это может использовать объединения, UNION и подзапросы. SELECT не обязан обращаться к каким-либо таблицам. Следующий пример определяет view, который выбирает два столбца из другой таблицы, также как выражение, вычисленное из данных этих столбцов:

mysql> CREATE TABLE t (qty INT, price INT);

mysql> INSERT INTO t VALUES(3, 50);

mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;

mysql> SELECT * FROM v;

+------+-------+-------+

| qty | price | value |

+------+-------+-------+

| 3 | 50 | 150 |

+------+-------+-------+

Определение view подчиненно следующим ограничениям:

Инструкция SELECT не может содержать подзапрос в предложении FROM.

Инструкция SELECT не может обратиться к переменным пользователя или системы.

Инструкция SELECT не может обратиться к подготовленным операторным параметрам.

Внутри сохраненной подпрограммы, определение не может обратиться к стандартным параметрам или локальным переменным.

Любая таблица или view, упоминаемый в определении, должны существовать. Однако, после того, как view был создан, можно удалить таблицу или view, к которому определение обращается. В этом случае, использование view приводит к ошибке. Чтобы проверить определение view для выявления проблем этого вида, используйте инструкцию CHECK TABLE.

Определение не может обратиться к таблице типа TEMPORARY, и Вы не можете создавать TEMPORARY view.

Таблицы, поименованные в определении view, должны уже существовать.

Вы не можете связывать триггер с view.

ORDER BY позволяется в определении view, но это игнорируется, если Вы выбираете из view, используя инструкцию, которая имеет собственный ORDER BY.

Для других параметров или предложений в определении, которые добавлены к параметрам или предложениям инструкции, которая ссылается на view, эффект не определен. Например, если определение view включает предложение LIMIT, и Вы выбираете из view, применяя инструкцию, которая имеет собственное предложение LIMIT, не определено, которое ограничение применяется. Тот же самый принцип применяется к параметрам типа ALL, DISTINCT или SQL_SMALL_RESULT, которые следуют за ключевым словом SELECT, к предложениям типа INTO, FOR UPDATE, LOCK IN SHARE MODE и PROCEDURE.

Если Вы создаете view, а затем меняете среду, обрабатывающую запрос, меняя переменные системы, которые могут воздействовать на результаты, получаемые из view:

mysql> CREATE VIEW v AS SELECT CHARSET(CHAR(65)), COLLATION(CHAR(65));

Query OK, 0 rows affected (0.00 sec)

mysql> SET NAMES 'latin1';

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM v;

+-------------------+---------------------+

| CHARSET(CHAR(65)) | COLLATION(CHAR(65)) |

+-------------------+---------------------+

| latin1 | latin1_swedish_ci |

+-------------------+---------------------+

1 row in set (0.00 sec)

mysql> SET NAMES 'utf8';

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM v;

+-------------------+---------------------+

| CHARSET(CHAR(65)) | COLLATION(CHAR(65)) |

+-------------------+---------------------+

| utf8 | utf8_general_ci |

+-------------------+---------------------+

1 row in set (0.00 sec)

Предложения DEFINER и SQL SECURITY определяют контекст защиты, который нужно использовать при проверке привилегий доступа при вызове view. Они были добавлены в MySQL 5.0.13, но реально работают с MySQL 5.0.16.

CURRENT_USER также известен как CURRENT_USER().

Внутри сохраненной подпрограммы, которая определена с характеристикой SQL SECURITY DEFINER, CURRENT_USER возвращает создателя подпрограммы. Это также воздействует на view, определенный внутри такой подпрограммы, если определение view содержит значение DEFINER для CURRENT_USER.

Заданное по умолчанию значение DEFINER: пользователь, который выполняет инструкцию CREATE VIEW (поскольку DEFINER = CURRENT_USER). Если задано значение user, это должно быть логином MySQL в формате 'user_name'@'host_name' (тот же самый формат, используется в инструкции GRANT). Требуются значения user_name и host_name.

Если Вы определяете предложение DEFINER, Вы не можете устанавливать значение к любому пользователю, если не имеете привилегии SUPER. Эти правила определяют допустимые значения пользователя для предложения DEFINER:

Если Вы не имеете привилегии SUPER, единственное допустимое значение user: Ваш собственный логин, определенный буквально или используя CURRENT_USER. Вы не можете устанавливать DEFINER к некоторому другому логину.

Если Вы имеете привилегию SUPER, Вы можете определять любой синтаксически допустимый логин. Если он фактически не существует, будет сгенерировано предупреждение.

Характеристика SQL SECURITY определяет, который логин MySQL использовать при проверке привилегий доступа для view. Допустимые значения: DEFINER и INVOKER. Они указывают, что view должен быть выполним пользователем, который определил или вызвал его, соответственно. Заданное по умолчанию значение для SQL SECURITY: DEFINER.

Начиная с MySQL 5.0.16 (когда были введены в строй DEFINER и SQL SECURITY), привилегии view проверяются следующим образом:

При определении view создатель view должен иметь привилегии, необходимые, чтобы использовать объекты верхнего уровня, к которым обращается view. Например, если определение view обращается к сохраненной функции, могут быть проверены только привилегии, необходимые чтобы вызвать функцию. Привилегии, требуемые, когда функция выполняется, могут быть проверены только, когда это выполняется: для различных вызовов функции, могут приниматься различные пути выполнения внутри функции.

Во время выполнения view, привилегии для объектов, к которым обращается view, проверены относительно привилегий создателя или исполнителя view, в зависимости от того, является ли характеристика SQL SECURITY равной DEFINER или INVOKER.

Если выполнение view вызывает выполнение сохраненной функции, инструкции прверки привилегии, выполненные внутри функции, зависят от того, определена ли функция с характеристикой SQL SECURITY, равной DEFINER или INVOKER. Если характеристика защиты DEFINER, функция выполняется с привилегиями создателя. Если характеристика INVOKER, функция выполняется с привилегиями, определенными в соответствии с характеристикой SQL SECURITY для view.

До MySQL 5.0.16 привилегии, требуемые для объектов, используемых в view, проверялись при создании view.

Пример: view мог бы зависеть от сохраненной функции, и та функция могла бы вызывать другие сохраненные подпрограммы. Например, следующий view вызывает сохраненную функцию f():

CREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);

Предположим, что f() содержит инструкцию типа этого:

IF name IS NULL then CALL p1();

ELSE CALL p2();

END IF;

Привилегии, требуемые для выполнения инструкций внутри f(), должны быть проверены, когда f() выполняется. Это могло бы означать, что привилегии необходимы для p1() или p2(), в зависимости от пути выполнения внутри f(). Те привилегии должны быть проверены во время выполнения, а пользователь, который должен обладать привилегиями, определен значениями SQL SECURITY функции f() и view v.

DEFINER и предложение SQL SECURITY для views представляют собой расширения к стандарту SQL. В обычном SQL views обработаны, используя правила для SQL SECURITY INVOKER.

Если Вы вызываете view, который был создан до MySQL 5.0.13, это обрабатывается, как если бы это было создано с предложением SQL SECURITY DEFINER и со значением DEFINER, равным Вашему логину. Однако, потому что фактический definer неизвестен, MySQL выдает предупреждение. Чтобы обойти предупреждение, достаточно вновь создать view, так чтобы определение view включило предложение DEFINER.

Факультативное предложение ALGORITHM задает расширение MySQL для стандартного SQL. ALGORITHM берет три значения: MERGE, TEMPTABLE или UNDEFINED. Заданный по умолчанию UNDEFINED, если никакое предложение ALGORITHM не присутствует. Алгоритм воздействует на то, как MySQL обрабатывает view.

Для MERGE текст инструкции, которая обращается к view, и определение view объединены так, что части определения view заменяют соответствующие части инструкции.

Для TEMPTABLE результаты из просмотра view помещаются во временную таблицу, которая затем используется, чтобы выполнить инструкцию.

Для UNDEFINED MySQL выбирает, который алгоритм использовать. Это предпочитает MERGE варианту TEMPTABLE, если возможно, поскольку MERGE обычно более эффективен и потому, что view не может быть обновляемым, если временная таблица используется.

Причина выбирать TEMPTABLE явно: блокировки на основных таблицах могут быть сняты после того, как временная таблица была создана, но прежде, чем это используется, чтобы закончить обрабатывать инструкцию. Это могло бы привести к более быстрому снятию блокировки, чем алгоритм MERGE так, чтобы другая клиентура, которая использует view, не была блокирована очень долго.

Алгоритм view может быть UNDEFINED по трем причинам:

Никакое предложение ALGORITHM не присутствует в инструкции CREATE VIEW.

Инструкция CREATE VIEW имеет явное предложение ALGORITHM = UNDEFINED.

ALGORITHM = MERGE определен для view, который может быть обработан только с временной таблицей. В этом случае MySQL генерирует предупреждение и устанавливает алгоритм к UNDEFINED (не к TEMPTABLE!).

Как упомянуто ранее, MERGE обработан, объединяя соответствующие части определения view в инструкцию, которая обращается к view. Следующие примеры кратко иллюстрируют, как работает алгоритм MERGE. Примеры принимают, что имеется view v_merge, который имеет это определение:

CREATE ALGORITHM = MERGE VIEW v_merge (vc1, vc2) AS

SELECT c1, c2 FROM t WHERE c3 > 100;

Пример 1: Предположим, что мы выдаем эту инструкцию:

SELECT * FROM v_merge;

MySQL обрабатывает инструкцию следующим образом:

v_merge становится t.

* становится vc1, vc2, которые соответствуют c1, c2.

Предложение WHERE из view добавляется.

Возникающая в результате инструкция, которая будет выполнена:

SELECT c1, c2 FROM t WHERE c3 > 100;

Пример 2: Предположим, что мы выдаем эту инструкцию:

SELECT * FROM v_merge WHERE vc1 < 100;

Эта инструкция обработана аналогично предыдущей за исключением того, что vc1 < 100 становится c1 <100 и предложение WHERE из view добавлено к предложению WHERE инструкции, используя связку AND (круглые скобки добавлены, чтобы удостовериться, что части предложения выполнены с правильным старшинством). Возникающая в результате инструкция, которая будет выполнена:

SELECT c1, c2 FROM t WHERE (c3 > 100) AND (c1 < 100);

Действительно, инструкция, которая будет выполнена, имеет предложение WHERE этой формы:

WHERE (select WHERE) AND (view WHERE)

Алгоритм MERGE требует взаимно однозначной связи между строками в view и строках в основной таблице. Если эта связь не действует, временная таблица должна использоваться вместо этого. Недостаток взаимно однозначной связи происходит, если view содержит любую из этих конструкций:

Агрегатные функции (SUM(), MIN(), MAX(), COUNT() и им подобные)

DISTINCT

GROUP BY

HAVING

UNION или UNION ALL

Обращается только к литеральным значениям (в этом случае не имеется никакой основной таблицы).

Некоторые views обновляемые. То есть Вы можете использовать их в инструкциях типа UPDATE, DELETE или INSERT, чтобы модифицировать содержание основной таблицы. Чтобы view был обновляемым, должна иметься взаимно однозначная связь между строками в view и строками в основной таблице. Имеются также некоторые другие конструкции, которые делают view не обновляемым. А именно: view не обновляемый, если он содержит любое из следующего:

Агрегатные функции (SUM(), MIN(), MAX(), COUNT() и им подобные)

DISTINCT

GROUP BY

HAVING

UNION или UNION ALL

Подзапросы в списке select

Join

Необновляемые view в FROM

Подзапросы в WHERE, ссылающиеся на таблицы в FROM

Обращается только к литеральным значениям (в этом случае не имеется никакой основной таблицы, чтобы модифицировать)

ALGORITHM = TEMPTABLE (использование временной таблицы всегда делает view не обновляемым)

Относительно вставляемости (обновляемости с инструкциями INSERT): обновляемый view является вставляемым, если он удовлетворяет этим дополнительным требованиям для столбцов view:

Не должно иметься никаких двойных имен столбца view.

view должен содержать все столбцы в основной таблице, которые не имеют значения по умолчанию.

Столбцы view должны быть простыми ссылками на столбец, но не полученными столбцами. Под полученными столбцами понимаются столбцы, которые получены из выражения. Вот примеры полученных столбцов:3.14159

col1 + 3

UPPER(col2)

col3 / col4

(подзапрос)

view, который имеет смесь простых ссылок столбца и полученных столбцов, не вставляемый, но он может быть обновляемым, если Вы модифицируете только те столбцы, которые не получены. Рассмотрите этот view:

CREATE VIEW v AS SELECT col1, 1 AS col2 FROM t;

Этот view не вставляемый, потому что col2 получен из выражения. Но это обновляемый view, если модификация не пробует менять col2. Эта модификация допустима:

UPDATE v SET col1 = 0;

А вот эта модификация уже не допустима, потому что она пытается модифицировать полученный столбец:

UPDATE v SET col2 = 0;

Для мультитабличного view иногда есть возможность обновляться, если это обрабатывается через алгоритм MERGE. Для этого view должен использовать внутреннее объединение (не внешнее объединение или UNION). Также, только одиночная таблица в определении view может модифицироваться, так что предложение SET должно называть только столбцы одной из таблиц в view. Views, которые используют UNION ALL отвергнуты даже при том, что они могли бы быть теоретически обновляемыми, потому что реализация использует временные таблицы, чтобы обработать их.

Для мультитабличного обновляемого view, INSERT может работать, если это вставляет в одиночную таблицу. DELETE не обеспечивается вообще.

Предложение WITH CHECK OPTION может быть дано для обновляемого view, чтобы предотвратить вставки или модификации в строки за исключением тех, для которых предложение WHERE в select_statement истинно.

В предложении WITH CHECK OPTION для обновляемого view ключевые слова LOCAL и CASCADED определяют контекст тестирования проверки, когда view определен в терминах другого view. Ключевое слово ограничивает LOCAL CHECK OPTION только определяемым view. CASCADED задает проверку для основных view, которые также будут оценены. Когда никакое ключевое слово не дано, значение по умолчанию: CASCADED. Рассмотрите определения для следующей таблицы и набора view:

mysql> CREATE TABLE t1 (a INT);

mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2

– > WITH CHECK OPTION;

mysql> CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0

– > WITH LOCAL CHECK OPTION;

mysql> CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0

– > WITH CASCADED CHECK OPTION;

Здесь view v2 и v3 определены в терминах другого view, а именно v1. v2 имеет опцию проверки LOCAL, так что вставки проверены только для v2. v3 имеет опцию проверки CASCADED, так что вставки проверены не только по собственной проверки, но и для таковых основных view. Следующие инструкции иллюстрируют эти различия:

mysql> INSERT INTO v2 VALUES (2);

Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO v3 VALUES (2);

ERROR 1369 (HY000): CHECK OPTION failed 'test.v3'

На обновляемость view можно воздействовать значением переменной системы updatable_views_with_limit. Команда CREATE VIEW была добавлена в MySQL 5.0.1. WITH CHECK OPTION было выполнено в MySQL 5.0.2.