Мы пока еще используем здесь SQL для выполнения основной работы. Запрос выше размещает строки таблицы Порядков которые не согласуются с таблицей Заказчиков.
EXEC SQL DECLARE Cust_assigns AS CURSOR FOR SELECT cnum, snum FROM Customers;
{Этот курсор используется для получения правильных значений snum}
begin { основная программа } EXEC SQL OPEN CURSOR Wrong_Orders; while SQLCODE = O do
{Цикл до тех пор пока Wrong_Orders не опустеет}
begin EXEC SQL FETCH Wrong_Orders INTO (:cnum, :snum); if SQLCODE = O then begin
{Когда Wrong_Orders опустеет, мы не хотели бы продолжать выполнение этого цикла до бесконечности}
EXEC SQL OPEN CURSOR Cust_Assigns; repeat EXEC SQL FETCH Cust_Assigns INTO (:custnum, :salesnum); until :custnum = :cnum;
{Повторять FETCH до тех пор пока ... команда будет просматривать Cust_Assigns курсор до строки которая соответствует текущему значению cnum найденного в Wrong_Orders}
EXEC SQL CLOSE CURSOR Cust_assigns;
{Поэтому мы будем начинать новый вывод в следующий раз через цикл. Значение в котором мы получим из этого курсора сохраняется в переменной - salesnum.}
EXEC SQL UPDATE Orders SET snum = :salesnum WHERE CURRENT OF Wrong_Orders; end; {Если SQLCODE = 0}. end;
{ Пока SQLCODE . . . выполнить }
EXEC SQL CLOSE CURSOR Wrong_Orders; end; { основная программа } 2.
Для данной программы которую использовал, решение будет состоять в том, чтобы просто включить поле onum, первичным ключом таблицы Порядков, в курсор Wrong_Orders. В команде UPDATE, вы будете затем использовать предикат WHERE onum =:ordernum ( считая целую переменную - odernum, объявленой), вместо WHERE CURRENT Of Wrong_Orders. Результатом будет программа наподобие этой ( большинство комментариев из предыдущей программы здесь исключены ):
EXEC SQL BEGIN DECLARE SECTION; SQLCODE: integer; odernum integer; cnum integer; snum integer; custnum: integer; salesnum: integer; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE Wrong_Orders AS CURSOR FOR SELECT onum, cnum, snum FROM Orders a WHERE snum < > (SELECT snum FROM Customers b WHERE a.cnum = b.cnum); EXEC SQL DECLARE Cust _ assigns AS CURSOR FOR SELECT cnum, snum FROM Customers; begin { основная программа } EXEC SQL OPEN CURSOR Wrong_Orders; while SQLCODE = O do {Цикл до тех пор пока Wrong_Orders не опустеет} begin EXEC SQL FETCH Wrong_Orders INTO (:odernum, :cnum, :snum); if SQLCODE = O then begin EXEC SQL OPEN CURSOR Cust_Assigns; repeat EXEC SQL FETCH Cust_Assigns INTO (:custnum, :salesnum); until :custnum = :cnum; EXEC SQL CLOSE CURSOR Cust_assigns; EXEC SQL UPDATE Orders SET snum = :salesnum WHERE CURRENT OF Wrong_Orders; end; {If SQLCODE = 0} end; { While SQLCODE . . . do } EXEC SQL CLOSE CURSOR Wrong_Orders; end; { main program } 3. EXEC SQL BEGIN DECLARE SECTION; SQLCODE integer; newcity packed array[1. .12] of char; commnull boolean; citynull boolean; response char; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE CURSOR Salesperson AS SELECT * FROM SALESPEOPLE; begln { main program } EXEC SQL OPEN CURSOR Salesperson; EXEC SQL FETCH Salesperson INTO (:snum, :sname, :city:i_cit, :comm:i_com); {Выборка первой строки} while SQLCODE = O do {Пока эти строки в таблице Продавцов.} begin if i_com < O then commnull: = true; if i_cit < O then citynull: = true; { Установить логические флаги которые могут показать NULLS.} if citynull then begin write ('Нет текущего значения city для продавца ', snum, ' Хотите предоставить хотя бы одно? (Y/N)'); {Подсказка покажет значение city состоящее из NULL значений.} read (ответ); {Ответ может быть сделан позже.} end {если конечно - citynull} else { не citynull } begin if not commnull then { Чтобы выполнять сравнение и операции только для не-NULL значений связи } begin if city = 'London' then comm: = comm * .02 * .02 else comm: = comm + .02; end; {Даже если значение и не - commnull, begin и end здесь для ясности.} write ('Текущий city для продавца', snum, 'есть', city, Хотите его изменить? (Y/N)'); 3. Обратите Внимание: Продавец не назначенный в данное время в определенный город, не будет иметь изменений комиссионных при определении находится ли он в Лондоне. read (ответ); {Ответ теперь имеет значение независимо от того что citynull - верен или неверен.} end; {иначе не citynull} if response = 'Y' then begin write ('Введите новое значение city:'); read (newcity); if not commnull then {Эта операция может быть выполнена только для не-NULL значений. } case newcity of: begin 'Barcelona':comm:= comm + .01, 'San Jose': comm: = comm *.01 end; {случно и если не commnull} EXEC SQL UPDATE Salespeople SET city = :newcity, comm = :comm:i_com WHERE CURRENT OF Salesperson; {Переменна индикатора может поместить NULL значение в поле comm если так назначено.} end; { Если ответ = 'Y', или если ответ < > 'Y', изменений не будет. } EXEC SQL FETCH Salesperson INTO (:snum, :sname, :city:i_clt, :comm:l_com); {выборка следующей строки} end; {если SQLCODE = 0} EXEC SQL CLOSE CURSOR Salesperson; end; {основной программы}