КаталогИндекс раздела
НазадОглавлениеВперед


4.3. Предложение INSERT

4.3.1. Вставка единственной записи в таблицу

Добавить в таблицу Блюда блюдо:

Шашлык (БЛ - 34, Блюдо - Шашлык, В - Г, Основа - Мясо, Выход - 150)

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

INSERT
INTO    Блюда (БЛ, Блюдо, В, Основа, Выход)
VALUES  (34, 'Шашлык', 'Г', 'Мясо', 150);

Создается новая запись для блюда с номером 34, с неопределенным значением в столбце Труд.

Порядок полей в INSERT не обязательно должен совпадать с порядком полей, в котором они определялись при создании таблицы. Вполне допустима и такая версия предыдущего предложения:

INSERT
INTO    Блюда (Основа, В, Блюдо, БЛ, Выход)
VALUES  ('Мясо', 'Г', 'Шашлык', 34, 150);

При известной трудоемкости приготовления шашлыка (например, 5 коп) сведения о нем можно ввести с помощью укороченного предложения:

INSERT
INTO    Блюда
VALUES  (34, 'Шашлык', 'Г', 'Мясо', 150, 5);

в котором должен соблюдаться строгий порядок перечисления вводимых значений, так как, не имея перечня загружаемых столб-цов, СУБД может использовать лишь перечень, который определен при создании модифицируемой таблицы.

В предыдущих примерах проводилась модификация стержневой сущности, т.е. таблицы с первичным ключом БЛ (см.п.2.4 в литературе [2]). Почти все СУБД имеют механизмы для предотвращения ввода не уникального первичного ключа, например, ввода "Шашлыка" под номером, меньшим 34. А как быть с ассоциациями или другими таблицами, содержащими внешние ключи?

Пусть, например, потребовалось добавить в рецепт блюда Салат летний (БЛ = 1) немного (15 г) лука (ПР = 10), и мы воспользовались предложением

INSERT
INTO    Состав (БЛ, ПР, Вес)
VALUES  (1, 10, 15);

Подобно операции DELETE операция INSERT может нарушить непротиворечивость базы данных. Если не принять специальных мер, то СУБД не проверяет, имеется ли в таблице Блюда блюдо с первичным ключом БЛ = 1 и в таблице Продукты - продукт с первичным ключом ПР = 10. Отсутствие любого из этих значений породит противоречие: в базе появится ссылка на несуществующую запись. Проблемы, возникающие при использовании внешних ключей, подробно рассмотрены в литературе [2], а здесь отме-тим, что все "приличные" СУБД имеют механизмы для предотв-ращения ввода записей со значениями внешних ключей, отсутст-вующих среди значений соответствующих первичных ключей.

4.3.2. Вставка множества записей

Создать временную таблицу К_меню, содержащую калорийность и стоимость всех блюд, которые можно приготовить из имеющихся продуктов. (Эта таблица будет использоваться шеф-поваром для составления меню на следующий день.)

Для создания описания временной таблицы можно, например, воспользоваться предложением CREATE TABLE (см.п.5.2)

CREATE TABLE К_меню
        (       Вид     CHAR (10),
                Блюдо   CHAR (60),
                Калор_блюда     INTEGER,
                Стоим_блюда     REAL);

а для ее загрузки данными √ предложение INSERT с вложенным подзапросами:

INSERT
INTO    К_меню
SELECT  Вид, Блюдо,
        INT(SUM(((Белки+Углев)*4.1+Жиры*9.3) * Вес/1000)),
        (SUM(Стоимость/К_во*Вес/1000) + MIN(Труд/100))
FROM    Блюда, Вид_блюд, Состав, Продукты, Наличие
WHERE   Блюда.БЛ        = Состав.БЛ
AND     Состав.ПР       = Продукты.ПР
AND     Состав.ПР       = Наличие.ПР
AND     Блюда.В = Вид_блюд.В
AND     БЛ NOT IN
        (       SELECT  БЛ
                FROM    Состав
                WHERE   ПР IN
                        (       SELECT  ПР
                                FROM    Наличие
                                WHERE   К_во = 0))
GROUP BY Вид, Блюдо
ORDER BY Вид, 3;

В этом запросе предложение SELECT выполняется так же, как обычно (см. описание запроса в п.3.6), но результат не выводится на экран, а копируется в таблицу К_меню. Теперь с этой копией можно работать как с обычной базовой таблицей (Блюда, Про-дукты,...), т.е. выбирать из нее даннные на экран или принтер, обновлять в ней данные и т.п. Никакая из этих операций не будет оказывать влияния на исходные данные (например, изменение в ней названия блюда Салат летний на Салат весенний не приведет к подобному изменению в таблице Блюда, где сохранится старое название). Так как это может привести к противоречиям, то подобные временные таблицы уничтожают после их использования. Поэтому программа, обслуживающая шеф-повара, должна исполнять предложение DROP TABLE К_меню после того, как будет закончено составление меню.

4.3.3. Использование INSERT...SELECT для построения внешнего соединения

Рассмотренное в п.3.2.3 естественное соединение двух таблиц не включает тех строк какой-либо из них, для которых нет соответствующих строк в другой таблице. Например, если в таблицу Блюда были занесены под номером 34 сведения о Шашлыке, а рецепт его приготовления не был занесен в таблицу Рецепты, то при загрузке их естественного соединения в таблицу Временная:

CREATE TABLE Временная
        (       Вид     CHAR (8),
                Блюдо   CHAR (60),
                Рецепт  CHAR (560));

INSERT
INTO    Временная
SELECT  Вид, Блюдо, Рецепт
FROM    Блюда, Рецепты, Вид_блюд
WHERE   Блюда.БЛ = Рецепты.БЛ
AND     Блюда.В = Вид_блюд.В;

в ней не окажется строки с Шашлыком (в таблице Рецепты не обнаружен код 34, и строка с этим кодом исключена из результата).

Следовательно, в некотором смысле можно считать, что при обычном соединении теряется информация для таких несоответствующих строк. Однако иногда (как и в приведенном примере) может потребоваться способность сохранить эту информацию. В этом случае можно воспользоваться так называемым внешним соединением:

INSERT
INTO    Временная
SELECT  Вид, Блюдо, Рецепт
FROM    Блюда, Рецепты, Вид_блюд
WHERE   Блюда.БЛ = Рецепты.БЛ
AND     Блюда.В = Вид_блюд.В;

INSERT
INTO    Временная
SELECT  Вид, Блюдо, ⌠???■
FROM    Блюда, Вид_блюд
WHERE   Блюда.В = Вид_блюд.В
AND     БЛ NOT IN
        (       SELECT  БЛ
                FROM    Рецепты);

В результате будет создана базовая таблица

Вид БлюдоРецепт
ЗакускаСалат летнийПомидоры и яблоки нарезать...
Закуска Салат мясной Вареное охлажденное мясо, ...
. . .
Напиток Кофе черный Кофеварку или кастрюлю спо...
Напиток Кофе на молоке Сварить черный кофе, как ...
Горячее Шашлык???

где первые 33 строки соответствуют первому INSERT и представляют собой проекцию естественного соединения таблиц Блюда и Рецепты по кодам блюд (БЛ), включающую три столбца. Последняя строка результата соответствует второму INSERT и сохраняет информацию о блюде Шашлык, рецепт котого пока не введен в таблицу Рецепты.

Заметим, что для внешнего соединения нужны два отдельных INSERT...SELECT. Однако тот же результат можно получить и одним INSERT...SELECT, используя фразу UNION, объединяющую предложения SELECT из двух INSERT:

INSERT
INTO    Временная
SELECT  Вид, Блюдо, Рецепт
FROM    Блюда, Рецепты, Вид_блюд
WHERE   Блюда.БЛ = Рецепты.БЛ
AND     Блюда.В = Вид_блюд.В
UNION
SELECT  Вид, Блюдо, ⌠???■
FROM    Блюда, Вид_блюд
WHERE   Блюда.В = Вид_блюд.В
AND     БЛ NOT IN
        (       SELECT  БЛ
                FROM    Рецепты);       


КаталогИндекс раздела
НазадОглавлениеВперед