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 в синтаксисе запроса.
ГРУППОВЫЕ ПРЕДСТАВЛЕНИЯ
Групповые представления - это представления, наподобие запроса
Ratingcount в предыдущем примере, который содержит предложение
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 для ответов. )
Содержание | Дальше
|