Мы пока ещё используем здесь 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 bWHERE 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; {основной программы}
Приложение B - ТИПЫ ДАННЫХ В SQL
Типы данных, распознаваемые с помощью ANSI, состоят из символов и различных типов чисел, которые могут классифицироваться как точные числа и приблизительные числа.
Точные числовые типы это числа с десятичной точкой или без десятичной точки. Приблизительные числовые типы это числа в показательной (экспоненциальной по основанию 10) записи.
Для всех прочих типов отличия слишком малы чтобы их как-то классифицировать.
Иногда типы данных используют аргумент, который называют размером аргумента, чей точный формат и значение меняется в зависимости от конкретного типа.
Значения по умолчанию обеспечены для всех типов, если размер аргумента отсутствует.