Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Базы Данных - Сибилев, 2007

.pdf
Скачиваний:
290
Добавлен:
11.05.2015
Размер:
1.93 Mб
Скачать

241

После обработки этого оператора определения объектов появятся в системном каталоге. Они будут зарегистрированы как объекты схемы

SUPPLY, и автор определения получит все привилегии на работу с ними. В

дальнейшем он может добавить в схему новые объекты, например, так:

CREATE VIEW SUPPLY.Parts

(Number, Name, Weight, Color, City, Quan-

tity)

SELECT P.*, SUMQ.SQT

FROM P JOIN (

SELECT Pnum, SUM(Qt) AS SQT

FROM SPJ

GROUP BY Pnum

) AS SUMQ;

CREATE GLOBAL TEMPORARY TABLE SUPPLY.TQt

( Pnum Pnum PRIMARY KEY REFERENCES P,

Sumqt NUMERIC);

GRANT SELECT, INSERT, DELETE

ON SUPPLY.TQt

TO Коля, Маша;

Первый оператор добавит в существующую схему SUPPLY новое представление, второй – глобальную временную таблицу, а третий предос-

тавит ID Коля и Маша права просмотра этой новой таблицы, а также вставки и удаления строк (см. п. 7.5.2).

7.4 Работа с представлениями

7.4.1 Роль механизма представлений

Как правило, представления создаются Администратором БД в инте-

ресах конечных пользователей (КП) и представляют хранимые данные в привычной и удобной для КП форме. В общем случае для конкретного КП создаётся набор представлений, отражающий все необходимые ему в силу служебных обязанностей данные. Для этого пользователя этот набор

242

представлений и есть БД, с которой он работает. Ничего другого он не ви-

дит и об истинной организации данных ничего не знает.

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

метной области БД.

Механизм представлений, как средство определения внешних моде-

лей, обладает рядом важных свойств.

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

Пример 1. Пусть некий КП работает только с данными о поставщи-

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

творяющем условию St < 50. Ему разрешено вносить любые изменения в это подмножество строк. Кроме этого он имеет право просмотра соответ-

ствующих строк таблицы SPJ. Вносить какие-либо изменения в эту табли-

цу запрещено. Внешнюю модель для этого пользователя можно опреде-

лить с помощью двух представлений:

CREATE VIEW S_LOWER

AS SELECT *

FROM S

WHERE St < 50

WITH CHECK OPTION;

CREATE VIEW SPJ_LOWER

AS SELECT SPJ.*

FROM SPJ, S_LOWER

WHERE SPJ.Snum = S_LOWER.Snum;

Представление S_LOWER является обновляемым (см. п. 7.4.3). Поль-

зователь может ссылаться на него в любых операторах DML, однако при

243

попытках обновления данных всегда будет автоматически проверяться ус-

ловие St < 50. Любая попытка этого пользователя внести изменения в дан-

ные с нарушением этого условия будет заблокирована.

Представление SPJ_LOWER может использоваться только в опера-

торах выборки данных. Система заблокирует любой оператор обновления,

ссылающийся на это представление.

Во-вторых, представления обеспечивают частичную защиту при-

кладных программ конечного пользователя от некоторых типов изменений в структуре БД. В ряде случаев можно «незаметно» для приложений, рабо-

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

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

Пример 2. Пусть в таблицу SPJ добавлен новый столбец SPJnum –

номер поставки. Если пользователь работает с представлением

SPJ_LOWER в интерактивном режиме и ему не следует показывать номе-

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

менения в приложении или в определении представления не требуются.

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

Пример 3. Пусть АБД решил ввести в нашу учебную БД таблицу C –

город со столбцами Cnum – номер города, Ci – название города. В связи с этим пришлось изменить структуры таблиц S, P и J. В них вместо столбцов

Ci используются теперь столбцы Cnum. Пользователь, работающий с пред-

ставлением S_LOWER, не заметит этого при выборке данных, если переоп-

ределить представление так:

CREATE VIEW S_LOWER

AS SELECT S.Snum, S.Snam, S.St, C.Ci

FROM S, C

WHERE St < 50

AND S.Cnum = C.Cnum;

244

Но это представление не обновляемо (см. п. 7.4.3), потому что оно базируется на двух таблицах. Теперь при попытке обновить данные о по-

ставщиках пользователь обнаружит, что он не может это сделать.

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

полнять часто, то можно определить соответствующее представление и

“выбирать” данные из него.

Пример 4. Пусть ежедневно нужно получать все сведения о постав-

ляемых деталях и для каждой детали – число поставщиков, поставляющих её, общий объем поставок и число изделий, для которых она поставлена.

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

CREATE VIEW REPORT

AS SELECT P.*, NS, NJ, SumQt

FROM P, ( SELECT Pnum,

COUNT(DISTINCT Snum),

COUNT(DISTINCT Jnum),

SUM(Qt)

FROM SPJ

GROUP BY Pnum

) AS RPT (Pnum, NS, NJ, SumQt)

WHERE P.Pnum = RPT.Pnum;

и каждый день выдавать простой запрос: SELECT * FROM

REPORT; или ещё проще: TABLE REPORT;

Замечание. Нижеследующая формулировка невозможна, хотя логи-

чески безупречна. Почему?

CREATE VIEW REPORT(Pnum, Pnam, We, Co, Ci, NS, NJ,

SumQt)

AS SELECT P.Pnum, Pnam, We, Co, Ci,

COUNT(DISTINCT Snum),

245

COUNT(DISTINCT Jnum),

SUM(Qt)

FROM P, SPJ

WHERE P.Pnum = SPJ.Pnum

GROUP BY P.Pnum;

Итак, представления значительно расширяют выразительные воз-

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

альный недостаток – ограниченные возможности обновления данных.

Кроме того, проблемы могут возникать и при выборке данных. Для того чтобы разобраться в сути этих проблем, посмотрим, что происходит при обработке запросов на выборку/обновление, использующих представле-

ния.

7.4.2 Выборка данных из представления

Вынесенный в заголовок термин не очень удачен. На самом деле, ко-

нечно, данные выбираются из базовых таблиц, на которых основано пред-

ставление.

Стандарт не содержит явных ограничений на операции выборки из представления, хотя, как будет видно из приведённых ниже примеров,

здесь возможны проблемы31. Ссылку на представление в предложении

FROM оператора выборки данных можно трактовать как подзапрос –

часть источника данных – и выполнять обработку такого оператора в со-

ответствии с этой трактовкой. Однако эта возможность появилась только с принятием стандарта SQL2 и не используется в распространённых СУБД.

На практике реализуется концепция выборки данных из представления,

изложенная ниже.

31 Характер этих проблем таков, что их невозможно отсечь путём введения ограничений. Если бы авторы стандарта пошли по этому пути, то представление было бы совершенно бесполезным с практической точки зрения понятием языка.

246

Для того чтобы осуществить выборку, система преобразует запрос к представлению (ЗП) в запрос к базовым таблицам (ЗБТ). При этом проис-

ходит следующее:

− формируется предложение SELECT ЗБТ, совпадающее с предло-

жением SELECT ЗП с точностью до имён столбцов;

− предложение FROM ЗП преобразуется в предложение FROM

ЗБТ путём замены ссылки на представление списком ссылок на его базо-

вые таблицы;

− предикат предложения WHERE ЗП преобразуется в предикат предложения WHERE ЗБТ: все ссылки на столбцы представления заме-

няются ссылками на соответствующие столбцы базовых таблиц, и выпол-

няется конъюнкция полученного выражения с предикатом предложения

WHERE запроса из определения представления;

− если предложения GROUP BY и HAVING содержатся только в определении представления, то они добавляются к предыдущим предло-

жениям ЗБТ;

− если предложения GROUP BY и HAVING содержатся только в ЗП, то в них все ссылки на столбцы представления заменяются ссылками на столбцы соответствующих базовых таблиц, и преобразованные пред-

ложения добавляются к ЗБТ.

Замечание. Запрос к представлению порождает ошибку, если опера-

ции группирования предусмотрены и в определении представления, и в за-

просе к нему. Это следствие запрета на вложение агрегатных функций (см.

п. 7.2.10).

Примеры 1. Пусть в условиях примера 1 из п. 7.4.1 пользователь об-

ращается к БД с запросом:

SELECT S_LOWER.Snum, S_LOWER.Snam

FROM S_LOWER

WHERE S_LOWER.Ci = ‘Томск

AND S_LOWER.St = 30;

247

Система преобразует этот запрос к виду:

SELECT S.Snum, S.Snam

FROM S

WHERE S.Ci = ‘Томск

AND S.St = 30

AND S.St < 50;

Разумеется, в данном случае последнее сравнение в предикате лиш-

нее. Но если бы пользователь попытался получить через своё представле-

ние сведения о поставщиках из Томска со статусом, равным 100, то полу-

чил бы пустую таблицу. Именно последнее сравнение обеспечивает защи-

ту данных от несанкционированного просмотра.

Пример 2. В условиях примера 3 из п. 7.4.1 система преобразует предыдущий запрос в следующий запрос к базовым таблицам:

SELECT S.Snum, S.Snam

FROM S, C

WHERE C.Ci = ‘Томск

AND S.St = 30

AND S.St < 50

AND S.Cnum = C.Cnum;

Пример 3. Запрос к представлению из примера 4 из п. 7.4.1 будет очевидным образом приведён к оператору SELECT, составляющему тело определения представления. Заметим, что в определении представления мы использовали подзапрос в предложении FROM. По-видимому, в на-

стоящее время это возможно лишь теоретически.

На практике существует две возможности: либо определить пред-

ставление RPT(Pnum, NS, NJ, SumQt) и заменить подзапрос в определении

REPORT ссылкой на него, либо откорректировать определение, приведён-

ное в замечании к примеру 4 в п. 7.4.1.

Рассмотрим первый вариант:

CREATE VIEW RPT(Pnum, NS, NJ, SumQt)

248

AS SELECT Pnum,

COUNT(DISTINCT Snum),

COUNT(DISTINCT Jnum),

SUM(Qt)

FROM SPJ

GROUP BY Pnum;

CREATE VIEW REPORT

AS SELECT P.*, NS, NJ, SumQt

FROM P, RPT

WHERE P.Pnum = RPT.Pnum;

Легко убедиться в том, что описанная выше процедура преобразует запрос SELECT * FROM REPORT; в эквивалентный запрос к базовым таблицам:

SELECT P.Pnum, P.Pnam, P.We, P.Co, P.Ci,

COUNT(DISTINCT SPJ.Snum),

COUNT(DISTINCT SPJ.Jnum),

SUM(SPJ.Qt)

FROM P, SPJ

WHERE P.Pnum = SPJ.Pnum

GROUP BY P.Pnum;

Однако это недопустимый запрос! Он не будет исполнен.

Второй вариант таков:

CREATE VIEW REPORT(Pnum, Pnam, We, Co, Ci, NS, NJ,

SumQt)

AS SELECT P.Pnum, P.Pnam, P.We, P.Co, P.Ci,

COUNT(DISTINCT Snum),

COUNT(DISTINCT Jnum),

SUM(Qt)

FROM P, SPJ

WHERE P.Pnum = SPJ.Pnum

249

GROUP BY P.Pnum, P.Pnam, P.We, P.Co, P.Ci;

Перечислив все столбцы таблицы P в списке группирования, мы не изменили структуру групп, т.к. столбец Pnum является первичным ключом

P. Теперь запрос на выборку всех данных из представления REPORT имеет допустимую эквивалентную форму.

Пример 4. Попытаемся получить из только что определённого представления номера деталей, суммарные объёмы поставок которых максимальны:

SELECT Pnum

FROM REPORT

WHERE SumQt = (SELECT MAX(SumQt) FROM

REPORT);

Это была бы безупречная формула, если бы таблица REPORT была базовой. Однако исполняющая система преобразует этот запрос в следую-

щую эквивалентную форму:

SELECT P.Pnum

FROM P, SPJ

WHERE SUM(Qt) =

(SELECT MAX(SUM(Qt))

FROM P, SPJ

WHERE P.Pnum = SPJ.Pnum

GROUP BY P.Pnum, P.Pnam, P.We, P.Co, P.Ci)

AND P.Pnum = SPJ.Pnum

GROUP BY P.Pnum, P.Pnam, P.We, P.Co, P.Ci;

Это недопустимая формула. В ней агрегатная функция использована в предикате предложения WHERE и в качестве аргумента агрегатной функции. Варианты правильных формул запроса достаточно очевидны (см.

п. 7.2.12, пример 4). Однако нет никаких способов преобразования запроса к представлению в одну из этих формул.

250

7.4.3 Обновление представления

Это такой же неудачный термин, как и «выборка из представления».

Следовало бы говорить «обновление базовых таблиц через представле-

ние».

Представление трактуется стандартами языка как таблица. Поэтому в общем случае имя представления может использоваться как имя приёмни-

ка данных в основном предложении любого оператора обновления. Однако представление – это виртуальная таблица, «обновить» которую можно,

лишь фактически обновив базовые таблицы. Поэтому, обрабатывая опера-

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

Существуют типичные ситуации, в которых интерпретация некото-

рых или всех видов операций обновления представления в терминах базо-

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

ления представления REPORT (п. 7.4.1, пример 4)

UPDATE REPORT SET SumQt = 25000 WHERE Pnum = ‘P2’;

Столбец SumQt содержит значения агрегатной функции. Соответствующе-

го ему столбца нет ни в одной базовой таблице.

В ряде случаев операторы обновления представлений могут иметь

«подозрительную» интерпретацию. Действительно, что означает приве-

дённое ниже высказывание?

INSERT INTO REPORT

VALUES (‘P12’, ‘пульт’, 500, ‘белый’, ‘Яя’, 3, 5, 200);

Зная определения представления REPORT, можно предположить,

что первые пять элементов списка составляют строку таблицы Р. Тогда возможна следующая интерпретация:

INSERT INTO P

VALUES (‘P12’, ‘пульт’, 500, ‘белый’, ‘Яя’);