Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
М. ГРУБЕР_SQL.doc
Скачиваний:
22
Добавлен:
18.04.2019
Размер:
1.4 Mб
Скачать

Не вставляйте дубликаты строк

Последовательность команд в предшествующем разделе может быть проблематичной. Продавец Serres находится в San Jose, и, следовательно, будет вставлен с помощью первой команды. Вторая команда попытается вставить его снова, поскольку он имеет еще одного заказчика в San Jose. Если имеются любые ограничения в таблице SJpeople, которые вынуждают ее значения быть уникальными, эта вторая вставка потерпит неудачу (как это и должно было быть). Двойные строки это плохо (cм. Главу 18 для подробностей об ограничениях).

Было бы лучше, если бы вы могли как-то выяснить, что эти значения уже были вставлены в таблицу, прежде чем вы попытаетесь сделать это снова, с помощью добавления другого подзапроса (использующего операторы типа EXISTS, IN, <> ALL, и так далее) к предикату.

К сожалению, чтобы сделать эту работу, вы должны будете сослаться на саму таблицу SJpeople в предложении FROM этого нового подзапроса, а, как мы говорили ранее, вы не можете ссылаться на таблицу, которая задействована (целиком) в любом подзапросе команды модификации.

В случае INSERT, это будет также препятствовать соотнесенным подзапросам, основанным на таблице, в которую вы вставляете значения. Это имеет значение, потому что, с помощью INSERT, вы создаете новую строку в таблице. "Текущая строка" не будет существовать до тех пор, пока INSERT не закончит ее обрабатывать.

Использование подзапросов, созданных во внешней таблице запроса

Запрещение на ссылку к таблице, которая модифицируется командой INSERT, не предохранит вас от использования подзапросов, которые ссылаются к таблице, используемой в предложении FROM внешней команды SELECT. Таблица, из которой вы выбираете значения, чтобы произвести их для INSERT, не будет задействована командой; и вы сможете ссылаться к этой таблице любым способом, которым вы обычно это делали, но только если эта таблица указана в автономном запросе. Предположим, что мы имеем таблицу с именем Samecity, в которой мы запомним продавцов с заказчиками в их городах.

Мы можем заполнить таблицу, используя соотнесенный подзапрос:

INSERT INTO (Samecity SELECT * FROM (Salespeople outer WHERE city IN (SELECT city FROM Customers inner WHERE inner.snum = outer.snum);

Ни таблица Samecity, ни таблица Продавцов не должны быть использованы во внешних или внутренних запросах INSERT.

В качестве другого примера, предположим, что вы имеете премию для продавца, который имеет самый большой заказ на каждый день. Вы следите за ним в таблице с именем Bonus, которая содержит поле snum продавцов, поле odate и поле amt. Вы должны заполнить эту таблицу информацией, которая хранится в таблице Заказов, используя следующую команду:

INSERT INTO Bonus SELECT snum, odate, amt FROM Orders a WHERE amt = (SELECT MAX (amt) FROM Orders b WHERE a.odate = b.odate);

Даже если эта команда имеет подзапрос, который базируется на той же самой таблице, что и внешний запрос, он не ссылается к таблице Bonus, на которую воздействует команда. Что для нас абсолютно приемлемо.

Логика запроса, естественно, должна просматривать таблицу Заказов, и находить для каждой строки максимум Заказа сумм приобретений для этой даты. Если эта величина — такая же, как у текущей строки, текущая строка является наибольшим Заказом для этой даты, и данные вставляются в таблицу Bonus.