Московский государственный университет имени М.В.Ломоносова
Опубликован: 10.10.2005 | Доступ: свободный | Студентов: 8465 / 635 | Оценка: 3.85 / 3.50 | Длительность: 22:03:00
Лекция 7:

Средства манипулирования данными

Представления, над которыми возможны операции обновления

В разделе "Общие синтаксические правила построения скалярных выражений" лекции 13 было введено понятие представления ( VIEW ). Кратко повторим, что представление - это сохраняемое в каталоге базы данных выражение запросов, обладающее собственным именем и, возможно, собственными именами столбцов. Для удобства повторим синтаксические правила определения представления:

create_view ::= CREATE [ RECURSIVE ] VIEW table_name
      [ column_name_comma_list ]
   AS query_expression
   [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

В операциях выборки к любому представлению можно адресоваться таким же образом, как и к любой базовой таблице. Естественно, возникает вопрос: а можно ли использовать имена представлений и в операциях обновления базы данных и если такая возможность допускается, то как это следует понимать?

Напомним, что в соответствии с семантикой языка SQL при выполнении запроса, в разделе FROM которого прямо или косвенно присутствует имя представления, прежде всего, производится материализация представления, т.е. вычисляется результат соответствующего выражения запросов, сохраняется во временной базовой таблице, и далее запрос выполняется по отношению к этой базовой таблице. Хотя в реализациях SQL обычно стремятся избегать материализации представлений, любая реализация обязана обеспечить такое выполнение запроса над представлением, которое было бы эквивалентно выполнению запроса с явной материализацией представления.

Если допустить выполнение над представлениями операций обновления (сразу заметим, что, вообще говоря, в языке SQL это всегда разрешалось), то в этом случае семантика материализации явно не подходит. На первое место выходит требование, чтобы операция обновления над представлением однозначно отображалась в одну или несколько операций обновления над теми постоянно хранимыми базовыми таблицами, над которыми прямо или косвенно определено данное представление.

Представления, допускающие применение операций обновления, в стандарте SQL/92

Поскольку базовым элементом выражения запросов является спецификация запроса, прежде всего нужно понять, какой класс спецификаций запросов является допускающим операции обновления (термин updatable - обновляемый, используемый в стандарте SQL, кажется не слишком удачным в русском варианте). В стандарте SQL/92 спецификация запроса считалась допускающей операции обновления в том и только в том случае, когда выполнялись следующие условия:

  • в разделе SELECT спецификации запроса отсутствует ключевое слово DISTINCT (т.е. не требуется удаление строк-дубликатов из результата запроса);
  • все элементы списка выборки раздела SELECT являются именами столбцов, и ни одно имя столбца не встречается в этом списке более одного раза;
  • в разделе FROM присутствует только одна ссылка на таблицу, и она указывает либо на базовую таблицу, либо на порождаемую таблицу, допускающую операции обновления;
  • прямые или косвенные ссылки на базовую таблицу, прямо или косвенно идентифицируемую ссылкой на таблицу в разделе FROM, не встречаются в разделе FROM ни одного подзапроса, участвующего в разделе WHERE спецификации запроса;
  • в спецификации запроса отсутствуют разделы GROUP BY и HAVING.

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

SELECT EMP_SAL
   FROM (SELECT EMP_SAL, DEPT_NO
         FROM EMP
         WHERE EMP_NAME = (SELECT EMP_NAME
                           FROM EMP
                           WHERE EMP_NO = 4425))
   WHERE DEPT_NO <> 630;
Пример 17.9.

Эту спецификацию можно упростить до эквивалентной формулировки3Обратите внимание, что формально эта формулировка не отвечает требованиям SQL/92 для спецификаций запросов, допускающих применение операций обновления. Но в действительности здесь вложенный подзапрос вычисляется в единственное значение при отсутствии какой-либо корреляции с внешним вхождением таблицы EMP .:

SELECT EMP_SAL
   FROM EMP
   WHERE EMP_NAME = (SELECT EMP_NAME
                     FROM EMP
                     WHERE EMP_NO = 4425 )
                        AND DEPT_NO <> 630;

Предположим, что с данной спецификацией запроса связано представление с именем EMPSAL. Тогда операция

UPDATE EMPSAL SET EMP_SAL = EMP_SAL - 1000.00;

эквивалентна операции

UPDATE EMP SET EMP_SAL = EMP_SAL - 1000.00
   WHERE EMP_NAME = (SELECT EMP_NAME
                     FROM EMP
                     WHERE EMP_NO = 4425 )
                        AND DEPT_NO <> 630;

Операция

DELETE FROM EMPSAL WHERE EMP_SAL > 20000.00;

эквивалентна операции

DELETE EMPSAL
   WHERE EMP_SAL > 20000.00 AND
         EMP_NAME = (SELECT EMP_NAME
                     FROM EMP
                     WHERE EMP_NO = 4425 )
                        AND DEPT_NO <> 630;

Операция вставки над представлением EMPSAL

INSERT INTO EMPSAL 25000.00;

трактуется как

INSERT INTO EMP
   ROW (DEFAULT, DEFAULT, DEFAULT, 25000.00, DEFAULT, DEFAULT);

Понятно, что такая операция будет отвергнута системой, потому что для столбца EMP_NO таблицы EMP значения по умолчанию не определены (это первичный ключ таблицы, значения которого должны явно задаваться в любой операции вставки).

С другой стороны, условия допустимости операций обновления, специфицированные в SQL/92, не являются необходимыми. Например, над представлением EMPMNG, определенным над спецификацией запроса ("выбрать данные о служащих, являющихся руководителями отделов").

SELECT *
   FROM EMP
   WHERE EXISTS (SELECT *
                 FROM DEPT
                 WHERE DEPT_MNG = EMP_NO);

можно было бы совершенно корректно выполнять операции обновления (с некоторыми оговорками насчет операции вставки; см. ниже в этом разделе).

Алексей Ковтун
Алексей Ковтун

При попытке исполнения запроса:

CREATE DOMAIN EMP_NO AS INTEGER

    CHECK (VALUE BETWEEN 1 AND 10000);

Выдается ошибка: Неизвестный тип объекта "DOMAIN" в интсрукции CREATE, DROP или ALTER. 

Используется SQL Server MS SQL 2008R2

Александра Каева
Александра Каева