До сих пор понятие "таблица", как правило, связывалось с реальной или базовой таблицей, т.е. 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 и т.д. до окончания перебора всех продуктов Харчо.