Московский государственный университет имени М.В.Ломоносова
Опубликован: 10.10.2005 | Доступ: свободный | Студентов: 8107 / 488 | Оценка: 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

Александра Каева
Александра Каева
Данил Икусов
Данил Икусов
Россия, Новосибирск, Новосибирский Государственный Университет, 2005
Николай Робук
Николай Робук
Россия, Дубна