20. ВВЕДЕНИЕ: ПРЕДСТАВЛЕНИЯ
ПРЕДСТАВЛЕНИЕ (VIEW) - ОБЪЕКТ ДАННЫХ КОТОРЫЙ не содержит никаких
данных его владельца. Это - тип таблицы, чье содержание выбирается из
других таблиц с помощью выполнения запроса. Поскольку значения в этих
таблицах меняются, то автоматически, их значения могут быть показаны
представлением.
В этой главе, вы узнаете что такое представления, как они создаются,
и немного об их возможностях и ограничениях. Использование представле-
ний основанных на улучшеных средствах запросов, таких как обьединение
и подзапрос, разработаных очень тщательно, в некоторых случаях даст
больший выиигрыш по сравнениию с запросами.
====== ЧТО ТАКОЕ ПРЕДСТАВЛЕНИЕ ? =====
Типы таблиц, с которыми вы имели дело до сих пор, назывались - базо-
выми таблицами. Это - таблицы, которые содержат данные. Однако имеется
другой вид таблиц: - представления. Представления - это таблицы чье
содержание выбирается или получается из других таблиц. Они работают в
запросах и операторах DML точно также как и основные таблицы, но не
содержат никаких собственных данных. Представления - подобны окнам,
через которые вы просматриваете информацию( как она есть, или в другой
форме, как вы потом увидите ), которая фактически хранится в базовой
таблице. Представление - это фактически запрос, который выполняется
всякий раз, когда представление становится темой команды. Вывод запро-
са при этом в каждый момент становится содержанием представления.
============= КОМАНДА CREATE VIEW ===========
Вы создаете представление командой CREATE VIEW. Она состоит из слов
CREATE VIEW (СОЗДАТЬ ПРЕДСТАВЛЕНИЕ), имени представления которое нужно
создать, слова AS (КАК), и далее запроса, как в следующем примере:
CREATE VIEW Londonstaff
AS SELECT *
FROM Salespeople
WHERE city = 'London';
Теперь Вы имеете представление, называемое Londonstaff. Вы можете
использовать это представление точно так же как и любую другую табли-
цу. Она может быть запрошена, модифицирована, вставлена в, удалена
из, и соединена с, другими таблицами и представлениями. Давайте сдела-
ем запрос такого представления ( вывод показан в Рисунке 20.1):
SELECT *
FROM Londonstaff;
=============== SQL Execution Log ============
| |
| SELECT * |
| FROM Londonstaff; |
| |
| ==============================================|
| snum sname city comm |
| ------ ---------- ----------- ------- |
| 1001 Peel London 0.1200 |
| 1004 Motika London 0.1100 |
| |
===============================================
20.1 Рисунок 20.1: Представление Londonstaff
Когда вы приказываете SQL выбрать(SELECT) все строки ( * ) из предс-
тавления, он выполняет запрос содержащий в определении - Loncfonstaff,
и возвращает все из его вывода. Имея предикат в запросе представления,
можно вывести только те строки из представления, которые будут удов-
летворять этому предикату. Вы могли бы вспомнить, что в Главе 15, вы
имели таблицу, называемую Londonstaff, в которую вы вставляли это же
самое содержание ( конечно, мы понимаем что таблица - не слишком вели-
ка. Если это так, вы будете должны выбрать другое имя для вашего
представления). Преимущество использования представления, по сравнению
с основной таблицы, в том, что представление будет модифицировано ав-
томатически всякий раз, когда таблица лежащая в его основе изменяется.
Содержание представления не фиксировано, и переназначается каждый раз
когда вы ссылаетесь на представление в команде. Если вы добавите завт-
ра другого, живущего в Лондоне продавца, он автоматически появится в
представлении.
Представления значительно расширяют управление вашими данными. Это -
превосходный способ дать публичный доступ к некоторой, но не всей ин-
формации в таблице. Если вы хотите чтобы ваш продавец был показан в
таблице Продавцов, но при этом не были показаны комиссии других про-
давцов, вы могли бы создать представление с использованием следующего
оператора ( вывод показан в Рисунке 20.2 )
CREATE VIEW Salesown
AS SELECT snum, sname, city
FROM Salespeople:
=============== SQL Execution Log ============
| |
| SELECT * |
| FROM Salesown; |
| |
| ==============================================|
| snum sname city |
| ------ ---------- ----------- |
| 1001 Peel London |
| 1002 Serres San Jose |
| 1004 Motika London |
| 1007 Rifkin Barcelona |
| 1003 Axelrod New York |
===============================================
Рисунок 20.2: Представление Salesown
Другими словами, это представление - такое же как для таблицы Про-
давцов, за исключением того, что поле comm, не упоминалось в запросе,
и следовательно не было включено в представление.
МОДИФИЦИРОВАНИЕ ПРЕДСТАВЛЕНИЙ
Представление может теперь изменяться командами модификации DML, но
модификация не будет воздействовать на само представление. Команды бу-
дут на самом деле перенаправлены к базовой таблице:
UPDATE Salesown
SET city = 'Palo Alto'
WHERE snum = 1004;
Его действие идентично выполнению той же команды в таблице Продавцов.
Однако, если значение комиссионных продавца будет обработано командой
UPDATE
UPDATE Salesown
SET comm = .20
WHERE snum = 1004;
она будет отвергнута, так как поле comm отсутствует в представлении
Salesown. Это важное замечание, показывающее что не все представления
могут быть модифицированы. Мы будем исследовать проблемы модификации
представлений в Главе 21.
ИМЕНОВАНИЕ СТОЛБЦОВ
В нашем примере, поля наших представлений имеют свои имена, получе-
ные прямо из имен полей основной таблицы. Это удобно. Однако, иногда
вам нужно снабжать ваши столбцы новыми именами:
* когда некоторые столбцы являются выводимыми, и проэтому не имеющими
имен.
* когда два или более столбцов в объединении, имеют те же имена что в
их базовой таблице.
Имена, которые могут стать именами полей, даются в круглых скобках,
после имени таблиц. Они не будут запрошены, если совпадают с именами
полей запрашиваемой таблицы. Тип данных и размер этих полей будут от-
личаются от запрашиваемых полей которые "передаются" в них. Обычно вы
не указываете новых имен полей, но если вы все таки сделали это, вы
должны делать это для каждого поля в представлении.
КОМБИНИРОВАНИЕ ПРЕДИКАТОВ ПРЕДСТАВЛЕНИЙ
И ОСНОВНЫХ ЗАПРОСОВ В ПРЕДСТАВЛЕНИЯХ
Когда вы делаете запрос представления, вы собственно, запрашиваете
запрос. Основной способ для SQL обойти это, - объединить предикаты
двух запросов в один. Давайте посмотрим еще раз на наше представление
с именем Londonstaff :
CREATE VIEW Londonstaff
AS SELECT *
FROM Salespeople
WHERE city = 'London';
Если мы выполняем следующий запрос в этом представлении
SELECT *
FROM Londonstaff
WHERE comm > .12;
он такой же как если бы мы выполнили следующее в таблице Продавцов:
SELECT *
FROM Salespeople
WHERE city = 'London'
AND comm > .12;
Это прекрасно, за исключением того, что появляется возможная пробле-
ма с представлением. Имеется возможность комбинации из двух полностью
допустимых предикатов и получения предиката который не будет работать.
Например, предположим что мы создаем (CREATE) следующее представление:
CREATE VIEW Ratingcount (rating, number)
AS SELECT rating, COUNT (*)
FROM Customers
GROUP BY rating;
Это дает нам число заказчиков которые мы имеем для каждого уровня
оценки(rating). Вы можете затем сделать запрос этого представления
чтобы выяснить, имеется ли какая-нибудь оценка, в настоящее время наз-
наченная для трех заказчиков:
SELECT *
FROM Ratingcount
WHERE number = 3;
Посмотрим что случится если мы скомбинируем два предиката:
SELECT rating, COUNT (*)
FROM Customers
WHERE COUNT (*) = 3
GROUP BY rating;
Это недопустимый запрос. Агрегатные функции, такие как COUNT (СЧЕТ),
не могут использоваться в предикате. Првильным способом при формирова-
нии вышеупомянутого запроса, конечно же будет следующий:
SELECT rating, COUNT (*)
FROM Customers
GROUP BY rating;
HAVING COUNT (*) = 3;
Но SQL может не выполнить превращения. Может ли равноценный запрос
вместо запроса Ratingcount потерпеть неудачу? Да может! Это - неодноз-
начная область SQL, где методика использования представлений может
дать хорошие результаты. Самое лучшее что можно сделать в случае, ког-
да об этом ничего не сказано в вашей системной документации, так это
попытка в ней разобраться. Если команда допустима, вы можете использо-
вать представления чтобы установить некоторые ограничения SQL в син-
таксисе запроса.
ГРУППОВЫЕ ПРЕДСТАВЛЕНИЯ
Групповные представления - это представления, наподобии запроса Ra-
tingcount в предыдущем примере, который содержит предложение GROUP BY,
или который основывается на других групповных представлениях.
Групповые представления могут стать превосходным способом обрабаты-
вать полученную информацию непрерывно. Предположим, что каждый день вы
должны следить за порядком номеров заказчиков, номерами продавцов при-
нимающих порядки, номерами порядков, средним от порядков, и общей сум-
мой приобретений в порядках.
Чем конструировать каждый раз сложный запрос, вы можете просто соз-
дать следующее представление:
CREATE VIEW Totalforday
AS SELECT odate, COUNT (DISTINCT cnum), COUNT
(DISTINCT snum), COUNT (onum), AVG
(amt), SUM (amt)
FROM Orders
GROUP BY odate;
Теперь вы сможете увидеть всю эту информацию с помощью простого зап-
роса:
SELECT *
FROM Totalforday;
Как мы видели, SQL запросы могут дать вам полный комплекс возможнос-
тей, так что представления обеспечивают вас чрезвычайно гибким и мощ-
ным инструментом чтобы определить точно, как ваши данные могут быть
использованы. Они могут также делать вашу работу более простой, пере-
форматируя данные удобным для вас способом и исключив двойную работу.
ПРЕДСТАВЛЕНИЯ И ОБЬЕДИНЕНИЯ
Представления не требуют чтобы их вывод осуществлялся из одной базо-
вой таблицы. Так как почти любой допустимый запрос SQL может быть ис-
пользован в представлении, он может выводить информацию из любого чис-
ла базовых таблиц, или из других представлений. Мы можем, например,
создать представление которое показывало бы, порядки продавца и заказ-
чика по имени:
CREATE VIEW Nameorders
AS SELECT onum, amt, a.snum, sname, cname
FROM Orders a, Customers b, Salespeople c
WHERE a.cnum = b.cnum
AND a.snum = c.snum;
Теперь вы можете выбрать (SELECT) все порядки заказчика или продавца
( * ), или можете увидеть эту информацию для любого порядка. Например,
чтобы увидеть все порядки продавца Rifkin, вы должны ввести следующий
запрос ( вывод показан в 20.3 Рисунке ):
SELECT *
FROM Nameorders
WHERE sname = 'Rifkin';
=============== SQL Execution Log ==============
| |
| SELECT * |
| FROM Nameorders |
| WHERE sname = 'Rifkin'; |
| =============================================== |
| onum amt snum sname cname |
| ------ -------- ----- ------- ------- |
| 3001 18.69 1007 Rifkin Cisneros |
| 3006 1098.16 1007 Rifkin Cisneros |
| |
================================================
Рисунок 20.3: Порядки Rifkin показаные в Nameorders
Вы можете также объединять представления с другими таблицами, или
базовыми таблицами или представлениями, поэтому вы можете увидеть все
порядки Axelrodа и значения его комиссиионных в каждом порядке:
SELECT a.sname, cname, amt comm
FROM Nameorders a, Salespeople b
WHERE a.sname = 'Axelrod'
AND b.snum = a.snum;
Вывод для этого запроса показывается в Рисунке 20.4.
В предикате, мы могли бы написать - " WHERE a.sname = |Axelrod' AND
b.sname = |Axelrod| " , но предикат который мы использовали здесь бо-
лее общеупотребительный. Кроме того поле snum - это первичный ключ
таблицы Продавцов, и следовательно должен по определению быть уникаль-
ным.
=============== SQL Execution Log ==============
| |
| SELECT a.sname, cname, amt * comm |
| FROM Nameorders a, Salespeople b |
| WHERE a.sname = 'Axelrod' |
| AND b.snum = a.snum; |
| =============================================== |
| onum amt snum sname cname |
| ------ -------- ----- ------- ------- |
| 3001 18.69 1007 Rifkin Cisneros |
| 3006 1098.16 1007 Rifkin Cisneros |
| |
================================================
Рисунок 20. 4: Обьединение основной таблицы с представлением
Если бы там например было два Axelrodf, вариант с именем, будет объ-
единять вместе их данные. Более предпочтительный вариант - использо-
вать поле snum чтобы хранить его отдельно.
ПРЕДСТАВЛЕНИЯ И ПОДЗАПРОСЫ
Представления могут также использовать и подзапросы, включая соотне-
сенные подзапросы. Предположим ваша компания предусматривает премию
для тех продавцов которые имеют заказчика с самым высоким порядком для
любой указанной даты. Вы можете проследить эту информацию с помощью
представления:
CREATE VIEW Elitesalesforce
AS SELECT b.odate, a.snum, a.sname,
FROM Salespeople a, Orders b
WHERE a.snum = b.snum
AND b.amt =
(SELECT MAX (amt)
FROM Orders c
WHERE c.odate = b.odate);
Если, с другой стороны, премия будет назначаться только продавцу ко-
торый имел самый высокий порядок за последние десять лет, вам необхо-
димо будет проследить их в другом представлении основанном на первом:
CREATE VIEW Bonus
AS SELECT DISTINCT snum, sname
FROM Elitesalesforce a
WHERE 10 < =
(SELECT COUNT (*)
FROM Elitesalestorce b
WHERE a.snum = b.snum);
Извлечение из этой таблицы продавца, который будет получать премию -
выпоняется простым вопросом:
SELECT *
FROM Bonus;
Теперь мы видим истинную мощность SQL. Извлечение той же полученной
информации программами RPG или COBOL будет более длительной процеду-
рой. В SQL, это - только вопрос из двух комплексных команд, сохранен-
ных, как представление совместно с простым запросом. При самостоятель-
ном запросе - мы должны заботится об этом каждый день, потому что ин-
формация которую извлекает запрос, непрерывно меняется чтобы отражать
текущее состояние базы данных.
ЧТО НЕ МОГУТ ДЕЛАТЬ ПРЕДСТАВЛЕНИЯ
Имеются большое количество типов представлений ( включая многие из
наших примеров в этой главе ) которые являются доступными только для
чтения. Это означает, что их можно запрашивать, но они не могут под-
вергаться действиям команд модификации. ( Мы будем рассматривать эту
тему в Главе 21. )
Имеются также некоторые виды запросов, которые не допустимы в опре-
делениях представлений. Одиночное представление должно основываться на
одиночном запросе; ОБЪЕДИНЕНИЕ (UNION) и ОБЪЕДИНЕНИЕ ВСЕГО (UNIOM ALL)
не разрешаются. УПОРЯДОЧЕНИЕ ПО(ORDER BY) никогда не используется в
определении представлений. Вывод запроса формирует содержание предс-
тавления, которое напоминает базовую таблицу и является - по определе-
нию - неупорядоченным.
УДАЛЕНИЕ ПРЕДСТАВЛЕНИЙ
Синтаксис удаления представления из базы данных подобен синтаксису
удаления базовых таблиц:
DROP VIEW < view name >
В этом нет необходимости, однако, сначала надо удалить все содержа-
ние как это делается с базовой таблицей, потому что содержание предс-
тавления не является созданым и сохраняется в течении определеной ко-
манды. Базовая таблица из которой представление выводится, не эффек-
тивна когда представление удалено. Помните, вы должны являться вла-
дельцем представления чтобы иметь возможность удалить его.
=============== РЕЗЮМЕ ==============
Теперь, когда вы можете использовать представления, ваша способность
отслеживать и обрабатывать содержание вашей базы данных, значительно
расширилась. Любые вещи которые вы можете создать с запросом, вы всег-
да сможете определить как представление. Запросы этих представлений,
фактически, запрос запроса. Использование представлений и для удобства
и для защиты, также удобно как и многие возможности представлений для
форматирования и получения значений из постоянно меняющегося содержа-
ния вашей базы данных. Имеется один главный вывод относительно предс-
тавлений, это способность к модификации, которую мы выбрали в отличии
от Главы 21. Как показано, вы можете модифицировать представления так-
же как и базовую таблицу, с помощью изменений применяемых к таблице из
которой получается представление, но это не всегда возможно.
*************** РАБОТА С SQL *************
1. Создайте представление которое бы показывало всех заказчиков кото-
рые имеют самые высокие оценки.
2. Создайте представление которое бы показывало номер продавца в каж-
дом городе.
3. Создайте представление которое бы показывало усредненый и общий по-
рядки для каждого продавца после его имени. Предполагается, что все
имена - уникальны.
4. Создайте представление которое бы показывало каждого продавца с
многочислеными заказчиками.
( См. Приложение A для ответов. )
|