Дейт К. Д27 Руководство по реляционной субд db2/ Пер с англ и предисл. М. Р. Когаловского

Вид материалаРуководство
Глава 8 представления 8.1. введение
8.2. Определение представления
8.3. Операции выборки
8.4. Операции обновления
В системе DB2 могут обновляться только представления-подмножества строк и столбцов.
Случай а).
Случай б).
Случай в).
Случай г).
Случай д).
Случай е).
8.5. Логическая независимость данных
8.6. Преимущества представлений
Ответы к некоторым упражнениям
Подобный материал:
1   ...   5   6   7   8   9   10   11   12   ...   34

ГЛАВА 8

ПРЕДСТАВЛЕНИЯ




8.1. ВВЕДЕНИЕ



Напомним из главы 1, что представление—это виртуальная таблица, т. е. таблица, которая сама по себе не существует, но для пользователя выглядит таким образом, как будто она существует. В противоположность этому базовая таблица — это реальная таблица в том смысле, что для каждой строки такой таблицы в действительности имеется некоторый хранимый двойник этой строки в физической памяти (см. главу 13). Представления не поддерживаются их собственными физически отдельными различимыми хранимыми данными. Вместо этого в каталоге (фактически в таблице каталога SYSVIEWS) хранится их определение в терминах других таблиц. Ниже приводится пример представления:

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

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

FROM S

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

Когда исполняется это предложение CREATE VIEW (создать представление), подзапрос, следующий за AS, являющийся фактически определением данного представления, не исполняется. Вместо этого он просто сохраняется в каталоге. Но для пользователя дело обстоит теперь таким образом, как будто бы в базе данных в действительности существует таблица, называемая ХОРОШИЕ_ПОСТАВЩИКИ, строки и столбцы которой показаны в необведенной пунктиром части рис. 8.1. ХОРОШИЕ_ПОСТАВЩИКИ представляет собой фактически «окно» в реальную таблицу S. Более того, это окно является динамическим: изменения в S будут автоматически и немедленно видны через это окно при условии, конечно, что эти изменения относятся к необведенной пунктиром части таблицы S. Подобным же образом изменения, внесенные в ХОРОШИЕ_ПОСТАВЩИКИ, будут автоматически и немедленно осуществлены и в реальной таблице S (см. ниже раздел 8.4).

Далее, в зависимости от искушенности пользователя и, возможно, также от рассматриваемого приложения, пользователь может или не может реализовать ХОРОШИЕ_ПОСТАВЩИКИ действительно как представление. Некоторые пользователи могут быть осведомлены об этом факте, а также о том, что имеется лежащая в основе этого представления реальная таблица S; другие могут искренне полагать, что ХОРОШИЕ_ПОСТАВЩИКИ — это сама «реальная» таблица. В любом случае нет никакой разницы Смысл заключается в том, что пользователь может производить операции над представлением ХОРОШИЕ_ПОСТАВЩИКИ точно так же, как если бы это была реальная таблица, за некоторыми исключениями, которые будут обсуждаться позже. Ниже приведен пример операции выборки данных (предложение SELECT) применительно к представлению ХОРОШИЕ_ПОСТАВЩИКИ:

SELECT *

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

WHERE ГОРОД = 'Лондон';



ХОРОШИЕ_

ПОСТАВЩИКИ

НОМЕР_

ПОСТАВЩИКА

ФАМИЛИЯ

СОСТОЯНИЕ

ГОРОД




S1

Смит

20

Лондон




S2

Джонс

10

Париж




S3

Влеик

30

Париж




S4

Кларк

20

Лондон




S5

Адамс

30

Атенс


Рис. 8.1. ХОРОШИЕ_ПОСТАВЩИКИ как представление базовой таблицы S (необведенная пунктиром часть)

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

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

FROM S

WHERE ГОРОД = 'Лондон'

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

Это новое предложение может быть теперь скомпилировано, т. е. связано, и обычным образом исполнено. Преобразование, о котором говорилось выше, фактически делается путем слияния изданного пользователем предложения SELECT с предложением SELECT, которое было сохранено в каталоге при определении данного представления. Из каталога система знает, что FROM ХОРОШИЕ_ПОСТАВЩИКИ в действительности означает FROM S. Она знает также, что любая выборка из ХОРОШИЕ_ПОСТАВЩИКИ должна быть далее уточнена условием WHERE СОСТОЯНИЕ>15. Наконец, она знает также, что «SELECT *» для ХОРОШИЕ_ПОСТАВЩИКИ в действительности означает SELECT НОМЕР_ПОСТАВЩИКА, СОСТОЯНИЕ, ГОРОД (из таблицы S). Следовательно, система способна транслировать первоначальное предложение SELECT, относящееся к виртуальной таблице ХОРОШИЕ_ПОСТАВЩИКИ, в эквивалентное предложение SELECT, оперирующее с реальной таблицей S,— эквивалентное в том смысле, что результат исполнения этого SELECT для реальной таблицы S такой же, как если бы в действительности имелась базовая таблица, называемая ХОРОШИЕ_ПОСТАВЩИКИ, и первоначальное предложение SELECT выполнялось бы по отношению к ней.

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

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

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

WHERE ГОРОД ='Париж';

будет преобразована генератором планов прикладных задач в следующую:

UPDATE S

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

WHERE ГОРОД = 'Париж'

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

Аналогично интерпретируются операции INSERT и DELETE.

8.2. ОПРЕДЕЛЕНИЕ ПРЕДСТАВЛЕНИЯ



Общий синтаксис предложения CREATE VIEW (создать представление):

CREATE VIEW имя—представления

[(имя—столбца[ , имя—столбца] . . .)]

AS подзапрос

[WITH CHECK OPTION];

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

1. CREATE VIEW КРАСНЫЕ_ДЕТАЛИ (НОМЕР—ДЕТАЛИ,

НАЗВАНИЕ, ВЕС, ГОРОД)

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

FROM P

WHERE ЦВЕТ = 'Красный';

Действие этого оператора заключается в том, чтобы создать новое представление, названное xyz.КРАСНЫЕ_ДЕТАЛИ, где xyz — известное системе имя пользователя, издавшего предложение CREATE VIEW. Пользователь xyz может называть это представление просто КРАСНЫЕ_ДЕТАЛИ. Другие же пользователи должны называть его xyz.КРАСНЫЕ_ДЕТАЛИ. С другой стороны, они могут, конечно, ввести для него синоним, как указывалось в главе 7. В этом представлении четыре столбца — НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС и ГОРОД, соответствующих четырем столбцам НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС и ГОРОД лежащей в основе базовой таблицы Р. Если имена столбцов явно не специфицированы в предложении CREATE VIEW, то представление очевидным образом наследует имена столбцов его источника. В приведенном примере наследуемыми именами были бы НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС и ГОРОД. Имена столбцов должны быть специфицированы явно для всех столбцов представления, если: а) какой-либо столбец этого представления продуцируется с помощью стандартной функции, арифметического выражения или константы (и не имеет, следовательно, имени, которое он мог бы наследовать) или б) два или более столбцов имели бы в противном случае одно и то же имя. Каждый из этих двух случаев иллюстрируется в следующих двух примерах.

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

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

FROM SP

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

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

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

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

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

FROM S, SP, P

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

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

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

Смысл этого представления в том, что пара имен городов (х,у) будет входить в данное представление, если поставщик с местоположением в городе х поставляет какую-либо деталь, хранимую в городе у. Например, поставщик S1 поставляет деталь Р1. При этом поставщик S1 находится в Лондоне и деталь Р1 хранится тоже в Лондоне. И поэтому пара (Лондон, Лондон) входит в данное представление. Обратите внимание, что в определении этого представления используется соединение и, таким образом, оно является примером представления, продуцируемого из нескольких положенных в основу таблиц. Примечание. Мы могли бы при желании включить в определение этого представления спецификацию DISTINCT. Сравните с примером 4.3.5 в главе 4.

4. CREATE VIEW ЛОНДОНСКИЕ_КРАСНЫЕ_ДЕТАЛИ

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

FROM КРАСНЫЕ_ДЕТАЛИ

WHERE ГОРОД = 'Лондон';

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

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

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

FROM S

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

WITH CHECK OPTION;

Фраза «WITH CHECK OPTION» (с проверкой) указывает, что для операций UPDATE и INSERT над этим представлением должна осуществляться проверка, которая обеспечивает удовлетворение определяющего представление предиката обновленной или вставляемой строкой (в данном примере СОСТОЯНИЕ>15). Вариант CHECK более подробно описан в разделе 8.4.

Предложение DROP VIEW имеет следующий синтаксис:

DROP VIEW имя — представления;

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

Пример рассматриваемого предложения:

DROP VIEW КРАСНЫЕ_ДЕТАЛИ;

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

Предложения ALTER VIEW (изменить представление) в языке SQL нет. Предложение ALTER TABLE, которое добавляет новый столбец к базовой таблице, не оказывает влияния на любые существующие представления.

8.3. ОПЕРАЦИИ ВЫБОРКИ



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

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

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

FROM SP

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

Это представление — «статистическая сводка» из раздела 8.2, пример 2.

Предпринятый запрос:

SELECT *

FROM PQ

WHERE ОБЩЕЕ_КОЛИЧЕСТВО > 500;

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

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

FROM SP

WHERE SUM (КОЛИЧЕСТВО) > 500

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

Такое предложение SELECT недопустимо. Не разрешается, чтобы в предикате во фразе WHERE использовалась стандартная функция, например SUM. Первоначальный запрос следовало бы на самом деле преобразовать в нечто подобное следующему:

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

FROM SP

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

HAVING SUM (КОЛИЧЕСТВО) > 500;

Однако система DB2 не умеет выполнять такое преобразование.

Ниже приводится другой пример, в котором рассматриваемое преобразование снова не работает. В этом примере опять используется представление — статистическая сводка PQ. Предпринимаемый запрос:

SELECT AVG (ОБЩЕЕ_КОЛИЧЕСТВО)

FROM PQ;

«Преобразованная» форма:

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

FROM SP

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

И снова это недопустимое предложение. В языке SQL не разрешается использовать вложенные таким образом стандартные функции.

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

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



В главе 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.

8.5. ЛОГИЧЕСКАЯ НЕЗАВИСИМОСТЬ ДАННЫХ



Мы еще не объяснили на самом деле, для чего нужны представления. Одна из задач, которую они позволяют решать — обеспечение того, что принято называть логической независимостью данных. Понятие физической независимости данных было введено в главе 2. Говорят, что система, подобная DB2, обеспечивает физическую независимость данных, поскольку пользователи и программы пользователей не зависят от физической структуры хранимой базы данных. Система обеспечивает логическую независимость данных, если пользователи и программы пользователей независимы также от логической структуры базы данных. Имеется два аспекта такой независимости — рост и реструктуризация.


Рост

Когда база данных растет в связи с включением новых видов информации, должно также соответственно расти ее определение.

Примечание. Вопрос о росте базы данных обсуждается здесь только для полноты. Он важен, но не имеет какого-либо отношения к самим по себе представлениям. Существуют два возможных типа роста, которые могут иметь место:

1. Расширение существующей базовой таблицы для включения в нее нового поля в соответствии с добавлением новой информации относительно некоторого существующего типа объектов, например добавление поля СКИДКА к базовой таблице поставщиков.

2. Включение новой базовой таблицы в соответствии с добавлением нового типа объектов, например при добавлении информации об изделиях в базу данных поставщиков и деталей.

Ни один из этих двух видов изменений не должен вообще оказывать какого-либо влияния на существующих пользователей, если только они не использовали предложения «SELECT *» или INSERT, в которых опущены списки имен полей. Как уже указывалось ранее в этой книге, смысл этих предложений может изменяться, если для них потребуется повторно произвести связывание, а рассматриваемая таблица была изменена (операция ALTER) в данном промежутке времени.


Реструктуризация

Иногда может стать необходимой реструктуризация базы данных. Хотя при этом общее информационное содержание остается тем же самым, размещение информации в этой базе данных изменяется, т. е. некоторым образом изменяется размещение полей в таблицах. Прежде чем продолжить обсуждение, отметим, что такая реструктуризация вообще нежелательна. Однако иногда она неизбежна. Например, может оказаться необходимым «вертикально» расщепить таблицу так, чтобы часто требующиеся столбцы могли храниться на более быстром устройстве, а реже требующиеся столбцы—на более медленном устройстве. Рассмотрим этот случай более подробно. Предположим для примера, что необходимо по некоторой причине — точная причина не является здесь важной — заменить базовую таблицу S следующими двумя базовыми таблицами:

SX (НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, ГОРОД)

SY (НОМЕР-ПОСТАВЩИКА, СОСТОЯНИЕ)

Примечание. Эта операция замены, между прочим, не совсем тривиальна. Один из способов ее осуществления состоит в следующей последовательности операций языка SQL:

CREATE TABLE SX

(НОМЕР_ПОСТАВЩИКА CHAR (5) NOT NULL,

ФАМИЛИЯ CHAR (20),

ГОРОД CHAR (15));

CREATE TABLE SY

(НОМЕР_ПОСТАВЩИКА CHAR (5) NOT NULL,

СОСТОЯНИЕ SMALLINT);

CREATE UNIQUE

CREATE UNIQUE INDEX XSX ON SX (НОМЕР_ПОСТАВЩИКА);

CREATE UNIQUE I NDEX XSY ON SY (НОМЕР_ПОСТАВЩИКА);

INSERT INTO SX (НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, ГОРОД)

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

FROM S;

INSERT INTO SY (НОМЕР_ПОСТАВЩИКА, СОСТОЯНИЕ)

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

FROM S;

DROP TABLE S;

Важный факт, который обнаруживается в данном примере, заключается в том, что старая таблица S представляет собой соединение двух новых таблиц SX и SY по номерам поставщиков. В таблице S, например, была строка ('S1', 'Смит', 20, 'Лондон'). В таблице SX мы имеем теперь строку ('S1', 'Смит', 'Лондон'), а в SY—строку ('S1', 20). Соединение их дает, как и ранее, строку ('S1', 'Смит', 20, 'Лондон'). Поэтому создадим представление, которое является в точности этим соединением, и назовем его S:

CREATE VIEW S (НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, СОСТОЯНИЕ,

ГОРОД)

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

SY СОСТОЯНИЕ, SX ГОРОД

FROM SX,SY

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

SY.HOMEP_ПОСТАВЩИКА;

Каждая программа, которая ранее обращалась к базовой таблице S, теперь будет вместо этого обращаться к представлению S. Операции SELECT будут продолжать работать в точности как и ранее, хотя они потребуют дополнительного анализа во время процесса связывания и дополнительных накладных расходов на стадии исполнения. Однако операции обновления больше не будут работать, поскольку система DB2, как уже пояснялось в разделе 8.4, не будет допускать обновлений представления, определяемого как соединение. Иными словами, выполняющий операции обновления пользователь не обладает иммунитетом к этому типу изменений. Он должен вручную внести некоторые изменения, касающиеся предложений обновления, а затем произвести их прекомпиляцию и повторное связывание.

Таким образом показано, что система DB2 не обеспечивает полной защиты от изменений в логической структуре базы данных. И в этом в первую очередь причина того, что проведение таких изменений вряд ли является хорошей идеей. Но дела могут быть не настолько плохими, как кажется, даже если требуются ручные изменения. Во-первых, легко обнаружить, какие программы должны быть изменены в связи с любыми такими изменениями. Эта информация может быть получена из каталога. Во-вторых, легко найти такие предложения, которые необходимо изменить в этой программе. Все они совершенно отдельны от всего другого и начинаются с префикса EXEC SQL. В-третьих, SQL — язык очень высокого уровня. Поэтому число подлежащих изменениям предложений обычно невелико, и смысл этих предложений можно легко уяснить. В результате необходимые изменения делаются, как правило, легко. Это не похоже на предложения обновления в языках сравнительно низкого уровня, таких, как PL/1 или КОБОЛ, где смысл данного предложения в большой степени зависит от динамической логики управления—от программы к предложению в запросе. Поэтому, хотя и справедливо, что должны быть сделаны некоторые поправки вручную, требуемый объем работ на практике не будет настолько большим.

Вернемся на минутку к примеру с таблицами SX и SY. Фактически представление S, определенное как соединение SX и SY, это хороший пример представления — соединения, которое теоретически обновляемо. Если предположить, что всегда существует взаимно однозначное соответствие между SX и SY таким образом, что любой поставщик, указанный в SX, должен быть указан также в SY, и наоборот, то воздействие на представление S всех возможных операций обновления понятным образом определяется в терминах SX и SY. (Упражнение. Согласны ли Вы с этим утверждением?) Таким образом, данный пример иллюстрирует, не только почему способность обновлять представления — соединения была бы полезной системной возможностью, но и случай, где такое обновление, по-видимому, является осуществимым.

8.6. ПРЕИМУЩЕСТВА ПРЕДСТАВЛЕНИЙ



Завершим эту главу краткой сводкой преимуществ представлений.

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

— Они дают возможность различным пользователям по-разному видеть одни и те же данные, возможно, даже в одно и то же время. Это соображение, очевидно, имеет важное значение, когда имеется много различных категорий пользователей и все они взаимодействуют с единой интегрированной базой данных.

— Упрощается пользовательское восприятие. Очевидно, что механизм представлений дает возможность пользователям сосредоточить внимание именно на тех данных, которые представляют для них интерес, и игнорировать остальные данные. Вместе с тем не настолько очевидно, что по крайней мере в отношении поиска данных этот механизм может также значительно упростить пользовательские операции манипулирования данными. В частности, поскольку для пользователя может быть предусмотрено представление, в котором все лежащие в его основе таблицы соединены вместе, необходимость явных операций для перехода от одной таблицы к другой может быть значительно уменьшена. В качестве примера рассмотрим представление ПАРЫ_ГОРОДОВ и сопоставим предложение SELECT, необходимое для нахождения городов, где хранятся поставляемые из Лондона детали, и использующее это представление, с предложением SELECT, требующимся для получения того же результата непосредственно из базовых таблиц. В действительности, сложный процесс выборки был перенесен здесь из сферы манипулирования данными в сферу определения данных. (На самом деле различия между этими двумя сферами в реляционных языках, подобных SQL, далеко не ясны.)

— Для скрытых данных автоматически обеспечивается секретность. «Скрытые данные» обозначает здесь данные, невидимые через некоторое заданное представление. Ясно, что такие данные защищены от доступа через это конкретное представление. Таким образом, принуждение пользователя осуществлять доступ к базе данных через представления является простым, но эффективным механизмом для управления санкционированием доступа. Этот аспект представлений более подробно обсуждается в следующей главе.

УПРАЖНЕНИЯ



8.1. Определите отношение SP из базы данных поставщиков и деталей как представление отношения SPJ из базы данных поставщиков, деталей и изделий.

8.2. Создайте для базы данных поставщиков, деталей и изделий представление. состоящее из всех изделий (включающее только поля номера изделия и города), которые поставляются поставщиком S1 и используют деталь Р1.

8.3. Является ли Ваше решение упражнения 8 2 обновляемым представлением?

а) Если да, то можно ли для него специфицировать вариант CHECKS

б) Если нет, найдите обновляемую версию представления и повторите это упражнение.

8.4. Создайте представление, состоящее из номеров поставщиков и номеров деталей, для таких поставщиков и деталей, которые не «соразмещены».

8.5. Создайте представление, состоящее из записей поставщиков, только для тех поставщиков, которые находятся в Лондоне

8.6. При условии, что задано определение представления:

CREATE VIEW СВОДКА (НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ,

МАКС_КОЛИЧЕСТВО, МИН_КОЛИЧЕСТВО,

СРЕДНЕЕ_КОЛИЧЕСТВО)

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

(КОЛИЧЕСТВО), MIN (КОЛИЧЕСТВО),

AVG (КОЛИЧЕСТВО)

FROM SPJ

GROUP BY НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ

HAVING SUM (КОЛИЧЕСТВО) > 50;

установите, какие из следующих операций корректны и приведите для них полученный в результате трансляции эквивалент.

а) SELECT *

FROM СВОДКА;

б) SELECT *

FROM СВОДКА

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

в) SELECT

FROM СВОДКА

WHERE МАКС_КОЛИЧЕСТВО > 250;

г) SELECT МАКС_КОЛИЧЕСТВО - МИН_КОЛИЧЕСТВО,

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

FROM СВОДКА

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

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

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

FROM СВОДКА

GROUP BY НОМЕР_ПОСТАВЩИКА;

e) SELECT НОМЕР_ПОСТАВЩИКА, МАКС_КОЛИЧЕСТВО

FROM СВОДКА

GROUP BY НОМЕР_ПОСТАВЩИКА, МАКС_КОЛИЧЕСТВО;

ж) SELECT S.НОМЕР_ПОСТАВЩИКА, СВОДКА. СРЕДНЕЕ_КОЛИЧЕСТВО

FROM S,CBOДKA

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

з) UPDATE СВОДКА

SET НОМЕР_ПОСТАВЩИКА = 'S2'

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

и) UPDATE СВОДКА

SET МАКС_КОЛИЧЕСТВО = 1000

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

к)DELETE

FROM СВОДКА

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

8.7. Сформулируйте правила, касающиеся обновляемости представлений в системе DB2.

8.8. Сформулируйте правила, касающиеся спецификации CHECK.

8.9. Предположим, что база данных реструктуризуется таким образом, что таблицы А и В заменяются их естественным соединением С. В какой степени механизм представлений может скрыть эту реструктуризацию от существующих пользователей?

ОТВЕТЫ К НЕКОТОРЫМ УПРАЖНЕНИЯМ



8.1. Проблема здесь состоит в том, каким образом должно быть определено поле SP.КОЛИЧЕСТВО? Разумным представляется следующий ответ: для данной пары (НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ) SP.КОЛИЧЕСТВО должно быть суммой всех значений SPJ. КОЛИЧЕСТВО, взятых по всем значениям поля НОМЕР_ИЗДЕЛИЯ для рассматриваемой пары (НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ).

CREATE VIEW SP (НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ,

КОЛИЧЕСТВО)

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

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

FROM SPJ

GROUP BY НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ;

8.2. CREATE VIEW JC (НОМЕР_ИЗДЕЛИЯ, ГОРОД)

AS SELECT DISTINCT J. НОМЕР_ИЗДЕЛИЯ. J.ГОРОД

FROM J,SPJ

WHERE J.НОМЕР_ИЗДЕЛИЯ = SPJ. НОМЕР_ИЗДЕЛИЯ

AND (SP J. НОМЕР_ПОСТАВЩИКА = 'S1' OR

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

8.3. Определенное в ответе на упражнение 8.2 представление необновляемо, поскольку во фразе FROM в его определении указывается несколько таблиц. Поэтому:

б) Обновляемая версия:

CREATE VIEW JC (НОМЕР_ИЗДЕЛИЯ, ГОРОД)

AS SELECT J. НОМЕР_ИЗДЕЛИЯ, J.ГОPOД

FROM J. НОМЕР_ИЗДЕЛИЯ IN

(SELECT НОМЕР_ИЗДЕЛИЯ

FROM SPJ

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

AND J. НОМЕР_ИЗДЕЛИЯ IN

(SELECT НОМЕР_ИЗДЕЛИЯ

FROM SPJ

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

Теперь повторите упражнение.

а) Нет.


8.4. CREATE VIEW НЕ_СОРАЗМЕЩЕННЫЕ

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

FROM S, Р

WHERE S. ГОРОД  = Р. ГОРОД;

8.5. CREATE VIEW ЛОНДОНСКИЕ_ПОСТАВЩИКИ

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

FROM S

WHERE ГОРОД = 'Лондон';

В представлении опущен столбец ГОРОД, поскольку известно, что его значение для каждой видимой через это представление строки должно быть 'Лондон'. Заметим, однако, что это опущение означает, что любая вставляемая (с помощью операции INSERT) через это представление запись будет немедленно исчезать, поскольку ее поле ГОРОД значение будет принимать неопределенное значение.

8.6 Корректны только операции а), б) и г). В частности, отметим, что операция ж) некорректна, так как представление, определение которого включает фразу GROUP BY, не может соединяться с другими таблицами. Приведем эквивалент, полученный в результате трансляции, только для случая г):

SELECT MAX (КОЛИЧЕСТВО) - MI N (КОЛИЧЕСТВО),

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

FROM SPJ

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

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

GROUP BY НОМЕР_ПОСТАВЩИКА, НОМЕР_ДЕТАЛИ

HAVING SUM (КОЛИЧЕСТВО) > 50;