Предложение WHERE CURRENT OF означает что DELETE применяется к строке которая в настоящее время выбрана курсором. Здесь подразумевается, что и курсор и команда DELETE, ссылаются на одну и ту же таблицу, и следовательно, что запрос в курсоре - это не обьединение.
Курсор должен также быть модифицируемым. Являясь модифицируемым, курсор должен удовлетворять тем же условиям что и представления (см. Главу 21). Кроме того, ORDER BY и UNION, которые не разрешены в представлениях, в курсорах - разрешаются, но предохраняют курсор от модифицируемости. Обратите внимание в вышеупомянутом примере, что мы должны выбирать строки из курсора в набор переменных, даже если мы не собирались использовать эти переменные. Этого требует синтаксис команды FETCH. UPDATE работает так же. Вы можете увеличить значение комиссионных всем продавцам, которые имеют заказчиков с оценкой=300, следующим способом. Сначала вы обьявляете курсор:
EXEC SOL DECLARE CURSOR High_Cust AS
SELECT *
FROM Salespeople
WHERE snum IN
(SELECT snum
FROM Customers
WHERE rating=300);
Затем вы выполняете модификации в цикле:
EXEC SQL OPEN CURSOR High_cust;
while SQLCODE=0 do
begin
EXEC SOL FETCH High_cust
INTO :id_num, :salesperson, :loc, :comm;
EXEC SQL UPDATE Salespeople
SET comm=comm + .01
WHERE CURRENT OF High_cust;
end;
EXEC SQL CLOSE CURSOR High_cust;
Обратите внимание: что некоторые реализации требуют, чтобы вы указывали в определении курсора, что курсор будет использоваться для выполнения команды UPDATE на определенных столбцах. Это делается с помощью заключительной фразы определения курсора - FOR UPDATE
Чтобы обьявить курсор High_cust таким способом, так чтобы вы могли модифицировать командой UPDATE столбец comm, вы должны ввести следующее предложение:
EXEC SQL DECLARE CURSOR High_Cust AS
SELECT *
FROM Salespeople
WHERE snum IN
(SELECT snum
FROM Customers
WHERE rating=300)
FOR UPDATE OF comm;
Это обеспечит вас определенной защитой от случайных модификаций, которые могут разрушить весь порядок в базе данных.
Пустые (NULLS) значения - это специальные маркеры определяемые самой SQL. Они не могут помещаться в главные переменные. Попытка вставить NULL значения в главнуюпеременную будет некорректна, так как главные языки не поддерживают NULL значений в SQL, по определению. Хотя результат при попытке вставить NULL значение в главную переменную определяет проектировщик, этот результат не должен ротиворечить теории базы данных, и поэтому обязан произвести ошибку: код SQLCODE ввиде отрицательного числа, и вызвать подпрограмму управления ошибкой. Естеcтвенно вам нужно этого избежать. Поэтому, вы можете выбрать NULL значения с допустимыми значениями, не приводящими к разрушению вашей программы. Даже если программа и не разрушится, значения в главных переменных станут неправильными, потому что они не могут иметь NULL значений. Альтернативным методом предоставляемым для этой ситуацией является - функция переменной indicator(указатель). Переменная indicator - обьявленная в разделе объявлений SQL напоминает другие переменные. Она может иметь тип главного языка который соответствует числовому типу в SQL. Всякий раз, когда вы выполняете операцию, которая должна поместить NULL значение в переменную главного языка, вы должны использовать переменную indicator, для надежности. Вы помещаете переменную indicator в команду SQL непосредственно после переменной главного языка которую вы хотите защитить, без каких-либо пробелов или запятых, хотя вы и можете, при желании, вставить слово - INDICATOR. Переменной indicator в команде, изначально присваивается значение 0. Однако, если производится значение NULL, переменная indicator становится равной отрицательному числу. Вы можете проверить значение переменной indicator, чтобы узнать, было ли найдено значение NULL. Давайте предположим, что поля city и comm, таблицы Продавцов, не имеют ограничения NOT NULL, и что мы объявили вразделе обьявлений SQL, две ПАСКАЛЬевские переменные
целого типа, i_a и i_b. (Нет ничего такого в разделеобьявлений, что могло бы представить их как переменные indicator. Они станут переменными indicator, когда будут использоваться как переменные indicator. )
Имеется одна возможность:
EXEC SQL OPEN CURSOR High_cust;
while SQLCODE=O do
begin
EXEC SQL FETCH High_cust
INTO :id_num, :salesperson,
:loc:i_a, :commINDlCATOR:i_b;
If i_a >=O and i_b >=O then
{no NULLs produced}
EXEC SQL UPDATE Salespeople
SET comm=comm + .01
WHERE CURRENT OF Hlgh_cust;
else
{one or both NULL}
begin
If i_a < O then
writeln ('salesperson ', id_num, ' has no city');
If i_b < O then
writeln ('salesperson ', id_num, ' has no
commission');
end;
{else}
end; {while}
EXEC SQL CLOSE CURSOR High_cust;