РУКОВОДСТВО ПО РЕЛЯЦИОННОЙ СУБД DB2

         

ОПЕРАЦИИ ОБНОВЛЕНИЯ


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

Теперь мы в состоянии высказать более сильное утверждение. Рассмотрим сначала два представления ХОРОШИЕ_ПОСТАВЩИКИ и ПАРЫ_ГОРОДОВ, определенные ранее в этой главе. Для удобства повторим здесь их определения:

CREATE VIEW

ХОРОШИЕ_

ПОСТАВЩИКИ

CREATE VIEW

ПАРЫ_ГОРОДОВ (ГОРОД_ПОСТАВЩИКА,



ГОРОД_ДЕТАЛИ)

AS SELECT

НОМЕР_ПОСТАВЩИКА, СОСТОЯНИЕ, ГОРОД

AS SELECT

ГОРОД_ПОСТАВЩИКА, ГОРОД_ДЕТАЛИ

FROM

S

FROM

S, SP, Р

WHERE

СОСТОЯНИЕ >15;

WHERE

S НОМЕР_ПОСТАВЩИКА=SP. НОМЕР_ПОСТАВЩИКА

AND

SP. НОМЕР_ДЕТАЛИ = Р. НОМЕР_ДЕТАЛИ);

Из этих двух представлений ХОРОШИЕ_ПОСТАВЩИКИ обновляемо, а ПАРЫ_ГОРОДОВ нет. Поучительно рассмотреть, почему это так. В случае представления ХОРОШИЕ_ПОСТАВЩИКИ можно:

а) вставить (операция

INSERT) новую строку в представление, например строку ('S6', 40, 'Рим'), фактически вставляя соответствующую строку ('S6', NULL, 40, 'Рим') в лежащую в основе базовую таблицу;

б) удалить (операция

DELETE) существующую строку из представления, например строку ('S1', 20, 'Лондон'), фактически удаляя соответствующую строку ('S1', 'Смит', 20, 'Лондон') из лежащей в основе базовой таблицы;

в) обновить (операция

UPDATE) какое-либо поле в существующей строке представления, например изменить город (Лондон) для поставщика S1 на Рим, фактически осуществляя то же самое изменение в соответствующем поле лежащей в основе базовой таблицы.

Будем называть такое представление, как ХОРОШИЕ_ПОСТАВЩИКИ, которое продуцируется из единственной базовой таблицы путем простого исключения некоторых строк и некоторых столбцов этой базовой таблицы, представлением-подмножеством строк и столбцов.

Такие представления по своей природе обновляемы, как показывает обсуждение предшествующего примера.

Рассмотрим теперь представление ПАРЫ_ГОРОДОВ, которое, конечно, не является представлением-подмножеством строк и столбцов. Как было показано ранее, одна из строк этого представления —('Лондон', 'Лондон'). Предположим, что некоторый пользователь имел бы возможность заменить эту строку, например, на ('Рим', 'Осло'). Что означало бы такое обновление? По-видимому, некоторый поставщик — но мы не знаем, какой именно, поскольку мы отбросили эту информацию при конструировании представления — переместился из Лондона в Рим. Подобным же образом местом хранения некоторой детали — но мы не знаем, какой именно, поскольку мы опять-таки исключили эту информацию, когда конструировалось представление,— был Лондон, а стал город Осло. Поскольку неизвестно, какой поставщик и какая деталь затрагиваются, нет способа, позволяющего спуститься к лежащим в основе базовым таблицам и сделать там соответствующие изменения. Иными словами, первоначальное UPDATE является внутренне неподдерживаемой операцией. Можно привести аналогичные аргументы для того, чтобы показать, что INSERT и DELETE — также внутренне неподдерживаемые операции над этим представлением.


Мы видели, таким образом, что некоторые представления по своей природе обновляемы, в то время как другие таковыми не являются. Обратите здесь внимание на слова «по своей природе». Дело заключается не просто в том, что некоторая система не способна поддерживать определенные обновления, в то время как другие системы могут это делать. Никакая система не может непротиворечивым образом поддерживать без дополнительной помощи обновления для такого представления, как ПАРЫ_ГОРОДОВ. «Без дополнительной помощи» означает здесь «без помощи какого-либо человека — пользователя». Вследствие этого факта можно классифицировать представления в соответствии с приведенной на рис. 8.2 диаграммой Венна.

На основе этой диаграммы заметим для строгости, что все представления-подмножества строк и столбцов (например, ХОРОШИЕ_ПОСТАВЩИКИ) теоретически обновляемы, но что не все теоретически обновляемые представления — это представления-подмножества строк и столбцов. Иными словами, существуют некоторые представления, которые теоретически обновляемы, но не являются представлениями-подмножествами строк и столбцов.

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

В системе DB2 могут обновляться только представления-подмножества строк и столбцов.

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



Рис. 8.2. Классификация представлений

Тот факт, что не все представления обновляемы, часто выражается так: «нельзя обновить соединение». Однако это утверждение не только не дает точной характеристики ситуации, но и не отражает в действительности существа проблемы. Существуют некоторые представления, которые не являются соединениями, но не обновляемы. Кроме того, существуют некоторые представления, которые являются соединениями, но (теоретически) обновляемы, хотя они и не обновляемы в системе DB2. Но, без сомнения, соединение представляет собой «интересный случай» в том смысле, что было бы очень удобно иметь возможность обновлять представление, в определении которого используется соединение. Из предыдущего обсуждения должно быть ясно, что такие представления действительно могут быть обновляемыми в какой-либо будущей системе. Но здесь мы имеем дело лишь с тем, что в настоящее время допускается в системе DB2. Постараемся теперь уяснить, что это такое.



В системе DB2 представление, допускающее обновление, должно быть производным от единственной базовой таблицы. Более того:

а) Если поле данного представления продуцируется из арифметического выражения или константы, то над этим полем не допускаются операции INSERT и UPDATE. Однако операции DELETE допускаются.

б) Если какое-либо поле представления продуцируется из стандартной функции, то данное представление необновляемо.

в) Если в определении представления используется фраза GROUP BY, то данное представление необновляемо.

г) Если в определении представления используется спецификация DISTINCT, то данное представление необновляемо.

д) Если определение представления включает вложенный подзапрос и во фразе FROM подзапроса указывается базовая таблица, над которой определяется данное представление, то это представление необновляемо.

е) Если во фразе FROM в определении представления указано несколько таблиц, то это представление необновляемо. Кроме того, конечно, если данное представление определено над необновляемым представлением, то оно само также необновляемо.

Убедимся в разумности этих ограничений. Рассмотрим поочередно каждый из случаев а)—е). Для каждого из них будет приведен пример представления, иллюстрирующий соответствующее ограничение.

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

CREATE               VIEW  ВЕС_В_ГРАММАХ (НОМЕР_ДЕТАЛИ, ВЕС)

AS                   SELECT НОМЕР_ДЕТАЛИ, ВЕС * 454

FROM              P;

Если предположить, что таблица Р имеет вид, показанный на рис. 1.3 (глава 1), то через это представление видимо следующее множество строк:

ВЕС_В_ГРАММАХ

НОМЕР_ДЕТАЛИ

ВЕС

Р1

Р2

РЗ

Р4

Р5

Р6

5448

7718

7718

6356

5448

8626

Должно быть ясно, что ВЕС_В_ГРАММАХ не может поддерживать операции INSERT, а также операции UPDATE над полем ВЕС. Каждая из этих операций потребовала бы, чтобы система была способна преобразовывать вес в граммах обратно в фунты без каких-либо инструкций относительно того, как выполнять такое преобразование. С другой стороны, операции DELETE могут быть поддержаны, например, таким образом, что удаление строки для детали Р1 из данного представления может осуществляться путем удаления строки для детали Р1 из лежащей в основе базовой таблицы. Могут быть поддержаны также операции UPDATE над полем НОМЕР_ДЕТАЛИ. Такие операции требуют просто соответствующих операций UPDATE над полем НОМЕР_ДЕТАЛИ этой базовой таблицы. Аналогичные соображения относятся к представлению, включающему поле, которое продуцируется из константы, а не из арифметического выражения.



Случай б). Поле представления, продуцируемое с помощью стандартной функции.

CREATE   VIEW              TQ (ОБЩЕЕ_КОЛИЧЕСТВО)

AS       SELECT           SUM (КОЛИЧЕСТВО)

FROM              SP;

В нашем случае имеем:

TQ

ОБЩЕЕ_КОЛИЧЕСТВО

3100

Вероятно, очевидно, что никакие операции UPDATE, INSERT, DELETE не имеют какого-либо смысла для этого представления.

Случай в).

Представление, в определении которого используется фраза GROUP BY.

CREATE   VIEW P          Q (НОМЕР_ДЕТАЛИ, ОБЩЕЕ_КОЛИЧЕСТВО)

AS       SELECT           НОМЕР_ДЕТАЛИ, SUM (КОЛИЧЕСТВО)

FROM              SP

GROUP           BY НОМЕР_ДЕТАЛИ;

В данном случае имеем:

PQ

НОМЕР_ДЕТАЛИ

ОБЩЕЕ_КОЛИЧЕСТВО

Р1

Р2

РЗ

Р4

Р5

Р6

600

1000

400

500

500

100

Очевидно, что представление PQ не может поддерживать ни операций INSERT, ни операций UPDATE над полем ОБЩЕЕ_КОЛИЧЕСТВО. Операции DELETE и UPDATE над полем НОМЕР_ДЕТАЛИ можно было бы определить как удаление или обновление соответствующих строк в таблице SP. Например, операцию

DELETE

FROM       PQ

WHERE    НОМЕР_ДЕТАЛИ = 'Р1’;

можно было бы определить как переводимую в

DELETE

FROM       SP

WHERE    НОМЕР_ДЕТАЛИ = 'Р1’;

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

Случай г).

Представление, определенное со спецификацией DISTINCT:

CREATE               VIEW              CC

AS                   SELECT           DISTINCT ЦВЕТ, ГОРОД

FROM              P;

Имеем в этом случае (в скобках указаны соответствующие номера деталей):

CC

ЦВЕТ

ГОРОД

Красный

Зеленый

Голубой

Голубой

Лондон

Париж

Рим

Париж

(Р1, P4, P6)

(Р2)

(РЗ)

(Р5)

И снова должно быть ясно, что представление CC не может поддерживать операций INSERT. Такие операции над лежащей в основе таблицей Р требуют, чтобы пользователь специфицировал значение поля НОМЕР_ДЕТАЛИ, поскольку для него специфицировано NOT NULL. Как и в случае в), операции DELETE и UPDATE теоретически могут быть здесь определены (как удаления или обновления всех соответствующих строк в таблице Р), но замечания относительно этой возможности, высказанные для случая в), справедливы здесь, возможно, даже в большей степени.



Рассмотрим другой пример для случая г):

CREATE               VIEW              PC

AS                   SELECT           DISTINCT НОМЕР_ДЕТАЛИ, ЦВЕТ

FROM              P;

Имеем:

PC

НОМЕР_ДЕТАЛИ

ЦВЕТ

P1

Р2

РЗ

P4

Р5

P6

Красный

Зеленый

Голубой

Красный

Голубой

Красный

Это — пример представления, которое, очевидно, является теоретически обновляемым. Ясно, что все возможные операции INSERT, DELETE и UPDATE над этим представлением вполне определены. Фактически это представление является на самом деле представлением-подмножеством строк и столбцов. Однако система DB2 не осведомлена об этом факте. Другими словами, система DB2 не осведомлена о том, что спецификация DISTINCT является здесь фактически излишней. Вместо этого она просто предполагает, что присутствие DISTINCT означает возможность продуцирования любой заданной строки представления из множества строк базовой таблицы, как в предыдущем примере, и по этой причине не считает данное представление обновляемым.

Случай д).

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

CREATE   VIEW              ПОСТАВЩИК_НИЖЕ_СРЕДНЕГО

AS       SELECT          НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, СОСТОЯНИЕ,

ГОРОД

FROM              S

WHERE           СОСТОЯНИЕ <

(SELECT         AVG (СОСТОЯНИЕ)

FROM              S);

Операции UPDATE и DELETE над представлением ПОСТАВЩИК_НИЖЕ_СРЕДНЕГО незаконны, поскольку они нарушали бы ограничения, налагаемые на такие операции, указанные в разделе 6.5. Как и операции INSERT, они могли бы в принципе поддерживаться, но давали бы непредсказуемый результат.

Случай е).

Представление, определенное на множестве таблиц.

CREATE   VIEW              ПАРЫ_ГОРОДОВ (ГОРОД_ПОСТАВЩИКА,

ГОРОД_ДЕТАЛИ);

AS       SELECT           S. ГОРОД, P. ГОРОД

FROM              S. SP, P

WHERE           S. НОМЕР_ПОСТАВЩИКА = SP.HOMEP_ПОСТАВЩИКА

AND                SP.HOMEP_ДЕТАЛИ = Р.НОМЕР_ДЕТАЛИ;

Это представление необновляемо по тем причинам, которые уже были достаточно подробно обсуждены. Рассмотрим, однако, следующий пример:



CREATE               VIEW ПОСТАВЩИКИ_Р2

AS                   SELECT           DISTINCT S. *

FROM              S, SP

WHERE           S. НОМЕР_ПОСТАВЩИКА =

SP. НОМЕР_ПОСТАВЩИКА

AND                SP НОМЕР_ДЕТАЛИ = 'P2';

Это представление также необновляемо в системе DB2, даже несмотря на то, что оно является фактически представлением-подмножеством строк и столбцов. Здесь снова DB2 не имеет возможности распознать этот факт. В этом примере интересно отметить, что может быть определено семантически эквивалентное обновляемое представление, а именно:

CREATE   VIEW              ПОСТАВЩИКИ_Р2

AS       SELECT           S. *

FROM              S

WHERE           НОМЕР_ПОСТАВЩИКА IN'

(SELECT         НОМЕР_ПОСТАВЩИКА

FROM              SP

WHERE           НОМЕР_ДЕТАЛИ = 'P2');

В этом определении не нарушается правило «несколько таблиц во фразе FROM» (см. выше правило е).

Вернемся, наконец, снова к представлению ХОРОШИЕ_ПОСТАВЩИКИ с тем, чтобы обсудить ряд оставшихся вопросов. Напомним определение этого представления:

CREATE   VIEW              ХОРОШИЕ_ПОСТАВЩИКИ

AS       SELECT           НОМЕР_ПОСТАВЩИКА, СОСТОЯНИЕ, ГОРОД

FROM              S

WHERE           СОСТОЯНИЕ > 15;

Это представление является представлением-подмножеством строк и столбцов и, следовательно, обновляемо. Но нужно отметить следующее:

а) Успешно выполненная операция INSERT для представления ХОРОШИЕ_ПОСТАВЩИКИ должна будет сгенерировать неопределенное значение для опущенного поля ФАМИЛИЯ, как уже указывалось в начале этого раздела. Конечно, для поля ФАМИЛИЯ не должен был специфицироваться вариант NOT NULL (При создании таблицы S.— Примеч. пер.), если требуется выполнять операцию INSERT.

б) При значениях данных, приведенных на рис. 1.3, поставщик S2 не будет видимым через представление ХОРОШИЕ_ПОСТАВЩИКИ. Но это не означает, что пользователь может вставить (операция INSERT) в это представление запись с номером поставщика S2 или обновить (операция UPDATE) какую-либо другую запись таким образом, чтобы значение ее номера поставщика стало равным S2. Такая операция должна быть отвергнута точно так же, как если бы она осуществлялась непосредственно над таблицей S.



в) Рассмотрим, наконец, следующий пример с использованием операции UPDATE:

UPDATE ХОРОШИЕ_ПОСТАВЩИКИ

SET           СОСТОЯНИЕ = О

WHERE    НОМЕР_ПОСТАВЩИКА ='S1';

Должна ли быть принята эта операция UPDATE? Если да, то результатом ее выполнения будет удаление поставщика S1 из данного представления, поскольку запись этого поставщика не будет больше удовлетворять предикату, определяющему представление. Подобным же образом операция INSERT:

INSERT

INTO        ХОРОШИЕ_ПОСТАВЩИКИ (НОМЕР_ПОСТАВЩИКА,

СОСТОЯНИЕ, ГОРОД)

VALUE    ('S8', 7, 'Стокгольм');

если она будет принята, создаст запись нового поставщика, но эта запись немедленно исчезнет из представления. Для того чтобы иметь дело с такими ситуациями, предназначена спецификация CHECK, упоминаемая в разделе 8.2. Если в определении представления включается фраза

WITH       CHECK           OPTION,

то все операции INSERT и UPDATE над этим представлением будут подвергаться проверке, чтобы обеспечить действительное удовлетворение предиката, определяющего представление, вновь вставляемой или обновленной записью. Если предикат не удовлетворяется, данная операция будет отвергнута.

Вариант CHECK может быть специфицирован только если данное представление обновляемо и его определение не включает вложенных подзапросов. Если данное представление таково, что обновления (операция UPDATE) допустимы только над определенными полями, а вставка (операция INSERT) не допускается вообще, то вариант CHECK относится только к этим операциям UPDATE.


Содержание раздела