EXEC SQL BEGIN DECLARE SECTION; SQLCODE : integer; { требуемый всегда } cnum : integer; snum : integer; custnum : integer; salesnum : integer; EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE Wrong_Orders AS CURSOR FOR SELECT cnum, snum FROM Orders a WHERE snum <> (SELECT snum FROM Customers b WHERE a.cnum = b.cnum); { Мы пока еще используем здесь SQL для выполнения основной работы. Запрос выше размещает строки таблицы Заказов, которые не согласуются с таблицей Заказчиков. }
EXEC SQL DECLARE Cust_assigns AS CURSOR FOR SELECT cnum, snum FROM Customers; { Этот курсор используется для получения правильных значений snum }
begin { основная программа } EXEC SQL OPEN CURSOR Wrong_Orders; while SQLCODE = 0 do { Цикл до тех пор, пока Wrong_Orders не опустеет } begin EXEC SQL FETCH Wrong_Orders INTO (:cnum, :snum); if SQLCODE = 0 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; { основная программа }
Для данной программы, которую я использовал, решение будет состоять в том, чтобы просто включить поле onum первичным ключом таблицы Заказов, в курсор Wrong_Orders. В команде UPDATE вы будете затем использовать предикат WHERE onum =:ordernum (считая целую переменную ordernum объявленной), вместо WHERE CURRENT Of Wrong_Orders.
Результатом будет программа наподобие этой (большинство комментариев из предыдущей программы здесь исключены):
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 = 0 do {Цикл до тех пор пока Wrong_Orders не опустеет} begin EXEC SQL FETCH Wrong_Orders INTO (:odernum, :cnum, :snum); if SQLCODE = 0 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; { основная программа } 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 = 0 do { Пока эти строки в таблице Продавцов. } begin if i_com < 0 then commnull: = true; if i_cit < 0 then citynull: = true; { Установить логические флаги, которые могут показать NULLS.} if citynull then begin write ('Нет текущего значения city для продавца ', snum, ' Хотите предоставить хотя бы одно? (Y/N)'); { Подсказка покажет значение city состоящее из NULL значений. } read (response); { Ответ может быть сделан позже. } end { если citynull } else begin { не citynull } 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)'); { Обратите Внимание: Продавец, не назначеный в данное время в определенный город, не будет иметь изменений комиссионых при определении, находятся ли он в Лондоне. } read (response); { Ответ теперь имеет значение независимо от того, что 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; {основной программы}