1.3. Таблицы SQL
До сих пор понятие "таблица", как правило, связывалось с реальной или базовой таблицей, т.е. c таблицей, для каждой строки которой в действительности имеется некоторый двойник, хранящийся в физической памяти машины (рис.1.2). Однако SQL использует и создает ряд виртуальных (как будто существующих) таблиц: представлений, курсоров и неименованных рабочих таблиц, в которых формируются результаты запросов на получение данных из базовых таблиц и, возможно, представлений. Это таблицы, которые не существуют в базе данных, но как бы существуют с точки зрения пользователя.
Базовые таблицы создаются с помощью предложения CREATE TABLE (создать таблицу), подробное описание которого приведено в главе 5. Здесь же приведем пример предложения для создания описания таблицы Блюда:
Рис. 1.2. База данных в восприятии пользователя
CREATE TABLE Блюда
(БЛ SMALLINT,
Блюдо CHAR (70),
В CHAR (1),
Основа CHAR (10),
Выход FLOAT,
Труд SMALLINT);
Предложение CREAT TABLE специфицирует имя базовой таблицы, которая должна быть создана, имена ее столбцов и типы данных для этих столбцов (а также, возможно, некоторую дополнительную информацию, не иллюстрируемую данным примером). CREAT TABLE - выполняемое предложение. Если его ввести с терминала, система тотчас построит таблицу Блюда, которая сначала будет пустой: она будет содержать только строку заголовков столбцов, но не будет еще содержать никаких строк с данными. Однако можно немедленно приступить к вставке таких строк данных, возможно, с помощью предложения INSERT и создать таблицу, аналогичную таблице Блюда рис.1.1.
Если теперь потребовалось узнать какие овощные блюда может приготовить повар пансионата, то можно набрать на терминале следующий текст запроса:
SELECT БЛ,Блюдо
FROM Блюда
WHERE Основа = 'Овощи';
и мгновенно получить на экране следующий результат его реализации:
БЛ | Блюдо |
1 | Салат летний |
3 | Салат витаминный |
17 | Морковь с рисом |
23 | Помидоры с луком |
Для выполнения этого предложения SELECT (выбрать), подробное описание которого будет дано в главах 2 и 3, СУБД должна сначала сформировать пустую рабочую таблицу, состоящую из столбцов БЛ и Блюдо, тип данных которых должен совпадать с типом данных аналогичных столбцов базовой таблицы Блюда. Затем она должна выбрать из таблицы Блюда все строки, у которых в столбце Основа хранится слово Овощи, выделить из этих строк столбцы БЛ и Блюдо и загрузить укороченные строки в рабочую таблицу. Наконец, СУБД должна выполнить процедуры по организации вывода содержимого рабочей таблицы на экран терминала (при этом если в рабочей таблице содержится более 20-24 строк, она должна использовать процедуры постраничного вывода и т.п.). После выполнения запроса СУБД должна уничтожить рабочую таблицу.
Если, например, надо получить значение калорийности всех овощей, включенных в таблицу Продукты, то можно набрать на терминале запрос
SELECT Продукт, Белки, Жиры, Углев,
((Белки+Углев)*4.1+Жиры*9.3)
FROM Продукты
WHERE Продукт IN ('Морковь','Лук','Помидоры','Зелень');
и получить на экране следующий результат его реализации:
Продукт | Белки | Жиры | Углев | ((Белки+Углев)*4.1+Жиры*9.3) |
Морковь | 13. | 1. | 70. | 349.6 |
Лук | 17. | 0. | 95. | 459.2 |
Помидоры | 6. | 0. | 42. | 196.8 |
Зелень | 9. | 0. | 20. | 118.9 |
В последнем столбце этой рабочей таблицы приведены данные о калорийности продуктов, отсутствующие в явном виде в базовой таблице Продукты. Эти данные вычислены по хранимым значениям основных питательных веществ продуктов, помещены в рабочую таблицу и будут существовать до момента смены изображения на экране. Однако если необходимо сохранить эти данные в какой-либо базовой таблице, то существует предложение (INSERT), позволяющее переписать содержимое рабочей таблицы в указанные столбцы базовой таблицы (реляционная операция присваивания).
Часто пользователя не устраивает как способ описания нужного набора выводимых строк, так и результат выполнения запроса, сформированного из данных одной таблицы. Ему хотелось бы уточнить выводимые (запрашиваемые) данные сведениями из других таблиц.
Например, в запросе на получение состава овощных блюд
SELECT БЛ,ПР,Вес
FROM Состав
WHERE БЛ IN (1,3,17,23);
пришлось перечислять номера этих блюд, так как в таблице Состав нет данных об основных продуктах блюда (они есть в таблице Блюда).
Полученный состав овощных блюд (рис.1.3,а) оказался "слепым": в нем и блюда и продукты представлены номерами, а не именами. Удобнее и нагляднее (рис.1.3,б)
а) | б) |
БЛ | ПР | Вес | Блюдо |
1 | 11 | 100 | Салат летний |
1 | 15 | 80 | Салат летний |
1 | 12 | 5 | Салат летний |
1 | 4 | 15 | Салат летний |
3 | 11 | 55 | Салат витаминный |
3 | 15 | 55 | Салат витаминный |
3 | 6 | 50 | Салат витаминный |
3 | 12 | 20 | Салат витаминный |
3 | 10 | 15 | Салат витаминный |
3 | 16 | 5 | Салат витаминный |
17 | 9 | 150 | Морковь с рисом |
17 | 7 | 50 | Морковь с рисом |
17 | 13 | 25 | Морковь с рисом |
17 | 3 | 20 | Морковь с рисом |
17 | 12 | 10 | Морковь с рисом |
17 | 14 | 5 | Морковь с рисом |
23 | 11 | 250 | Помидоры с луком |
23 | 10 | 65 | Помидоры с луком |
23 | 3 | 20 | Помидоры с луком |
|
Продукт | Вес |
Помидоры | 100 |
Яблоки | 80 |
Зелень | 5 |
Майонез | 15 |
Помидоры | 55 |
Яблоки | 55 |
Сметана | 50 |
Зелень | 20 |
Лук | 15 |
Сахар | 5 |
Морковь | 150 |
Молоко | 50 |
Рис | 25 |
Масло | 20 |
Зелень | 10 |
Мука | 5 |
Помидоры | 250 |
Лук | 65 |
Масло | 20 |
|
Рис. 1.3. Состав овощных блюд базы данных ПАНСИОН
запрос сформированный по трем таблицам:
SELECT Блюдо, Продукт, Вес
FROM Состав,Б люда, Продукты
WHERE Состав.БЛ = Блюда.БЛ
AND Состав.ПР = Продукты.ПР
AND Основа = 'Овощи';
В нем для получения рабочей таблицы выполняется естественное соединение [2] таблиц Блюда, Продукты и Состав (условие соединения - равенство значений номеров блюд и значений номеров продуктов). Затем выделяются строки, у которых в столбце Основа хранится слово Овощи, и из этих строк - столбцы Блюдо, Продукт и Вес.
Если пользователи достаточно часто интересуются составом различных блюд, то для упрощения формирования запросов целесообразно создать представление.
Представление - это пустая именованная таблица, определяемая перечнем тех столбцов таблиц и признаками тех их строк, которые хотелось бы в ней увидеть. Представление является как бы "окном" в одну или несколько базовых таблиц. Оно создается с помощью предложения CREATE VIEW (создать представление), подробное описание которого приведено в главе 5. Здесь же приведем пример предложения для создания представления Состав_блюд:
CREATE VIEW Состав_блюд
AS SELECT Блюдо, Продукт, Вес
FROM Состав,Блюда,Продукты
WHERE Состав.БЛ = Блюда.БЛ
AND Состав.ПР = Продукты.ПР;
Оно описывает пустую таблицу, в которую при реализации запроса будут загружаться данные из столбцов Блюдо, Продукт и Вес таблиц Блюда, Продукты и Состав, соответственно. Теперь для получения состава овощных блюд можно дать запрос
SELECT Блюдо,Продукт,Вес
FROM Состав_блюд
WHERE Основа = 'Овощи';
и получить на экране терминала данные, которые представлены на рис. 1.3,б. А для получения состава супа Харчо можно дать запрос
SELECT Блюдо, Продукт, Вес
FROM Состав_блюд
WHERE Блюдо = 'Суп харчо';
О целесообразности создания представлений будет рассказано ниже, а здесь лишь отметим, что они позволяют повысить уровень логической независимости данных, упростить их восприятие и "скрыть" от некоторых пользователей те или иные данные, например, данные о новых ценах на продукты первой необходимости или из какой рыбы приготавливается "Судак по-польски".
Наконец, еще об одних виртуальных таблицах - курсорах. Курсор - это пустая именованная таблица, определяемая перечнем тех столбцов базовых таблиц и признаками тех их строк, которые хотелось бы в ней увидеть. В чем же различие между курсором и представлением?
Для пользователя представления почти не отличаются от базовых таблиц (есть лишь некоторые ограничения при выполнении различных операций манипулирования данными). Они могут использоваться как в интерактивном режиме, так и в прикладных программах. Курсоры же созданы для процедурной работы с таблицей в прикладных программах. Например, после объявления курсора
DECLARE Блюд_состав CURSOR FOR
SELECT Блюдо,Продукт,Вес
FROM Состав,Блюда,Продукты
WHERE Состав.БЛ = Блюда.БЛ
AND Состав.ПР = Продукты.ПР
AND Блюдо = 'Суп харчо';
и его активизации (OPEN Блюд_состав) будет создана временная таблица с составом блюда "Суп харчо" и специальным указателем, определяющим в качестве текущей первую строку этой таблицы. С помощью предложения FETCH (выбрать), которое обычно исполняется в программном цикле, можно присвоить определенным переменным значения указанных столбцов этой строки. Одновременно курсор будет передвинут к следующей строке таблицы. После обработки в программе полученных значений переменных выполняется следующее предложение FETCH и т.д. до окончания перебора всех продуктов Харчо.
1.2 | Содержание | 2.1