Глава 7
 
 
1. SELECT onum, snum, amt * .12 
 FROM Orders; 
 
2. SELECT 'For the city ', city, ', the highest rating is ', ", 
 MAX (rating) 
 FROM Customers 
 GROUP BY city; 
 
3 SELECT rating, cname, cnum 
 FROM Customers 
 ORDER BY rating DESC; 
 
4. SELECT odate, SUM (amt) 
 FROM Orders 
 GROUP BY odate 
 ORDER BY 2 DESC; 
 
Глава 8
 
 
1. SELECT onum, cname 
 FROM Orders, Customers 
 WHERE Customers.cnum = Orders.cnum; 
 
2. SELECT onum, cname, sname 
 FROM Orders, Customers, Salespeople 
 WHERE Customers.cnum = Orders.cnum 
 AND Salespeople.snum = Orders.snum; 
 
3. SELECT cname, sname, comm 
 FROM Salespeople, Customers 
 WHERE Salespeople.snum = Customers.snum 
 AND comm * .12; 
 
4. SELECT onum, comm * amt 
 FROM Salespeople, Orders, Customers 
 WHERE rating > 100 
 AND Orders.cnum = Customers.cnum 
 AND Orders.snum = Salespeople.snum; 
 
Глава 9
 
 
1. SELECT first.sname, second.sname 
 FROM Salespeople first, Salespeople second 
 WHERE first.city = second.city 
 AND first.sname < second.sname; 
 
Псевдонимам нет необходимости иметь именно такие имена. 
 
2. SELECT cname, first.onum, second.onum 
 FROM Orders first, Orders second, Customers 
 WHERE first.cnum = second.cnum 
 AND first.cnum = Customers.cnum 
 AND first.onum < second.onum; 
 
Ваш вывод может иметь некоторые отличи, но в вашем ответе все логические 
компоненты должны быть такими же. 
 
3. SELECT a.cname, a.city 
 FROM Customers a, Customers b 
 WHERE a.rating = b.rating 
 AND b.cnum = 2001; 
 
 
Глава 14
1. SELECT cname, city, rating, 'High Rating' 
 FROM Customers 
 WHERE rating > = 200 
 
 UNION 
 
 SELECT cname, city, rating, ' Low Ratlng' 
 FROM Customers 
 WHERE rating < 200; 
 
 или 
 
 SELECT cname, city, rating, 'High Rating' 
 FROM Customers 
 WHERE rating > = 200 
 
 UNION 
 
 SELECT cname, city, rating, ' Low Rating' 
 FROM Customers 
 WHERE NOT rating > = 200; 
 
Различие между этими двум предложениями, в форме второго предиката. Обратите 
внимание что, в обоих случаях, строка "Low Rating" имеет в начале дополнительный 
пробел для того чтобы совпадать со строкой "High Rating" по длине. 
 
2. SELECT cnum, cname 
 FROM Customers a 
 WHERE 1 < 
 (SELECT COUNT (-) 
 FROM Orders b 
 WHERE a.cnum = b.cnum) 
 
 UNION 
 
 SELECT snum, sname 
 FROM Salespeople a 
 WHERE 1 < 
 (SELECT COUNT (*) 
 FROM Orders b 
 WHERE a.snum = b.snum) 
 
 ORDER BY 2; 
 
3. SELECT snum 
 FROM Salespeople 
 WHERE city = 'San Jose' 
 
 UNION 
 
 (SELECT cnum 
 FROM Customers 
 WHERE city = 'San Jose' 
 
 UNION ALL 
 
 SELECT onum 
 FROM Orders 
 WHERE odate = 10/03/1990); 
 
Глава 18
 
1. CREATE TABLE Orders 
(onum integer NOT NULL PRIMARY KEY, 
amt decimal, 
odate date NOT NULL, 
cnum integer NOT NULL, 
snum integer NOT NULL, 
UNIOUE (snum, cnum)); 
или 
CREATE TABLE Orders 
(onum integer NOT NULL UNIQUE, 
amt decimal, 
odate date NOT NULL, 
cnum integer NOT NULL, 
snum integer NOT NULL, 
UNIQUE (snum, cnum)); 
Первое решение предпочтительнее. 
2. CREATE TABLE Salespeople 
(snum integer NOT NULL PRIMARY KEY, 
sname char(15) CHECK (sname BETWEEN 'AA' AND 'MZ'), 
city char(15), 
comm decimal NOT NULL DEFAULT = .10); 
3. CREATE TABLE Orders 
(onum integer NOT NULL, 
amt decimal, 
odate date, 
cnum integer NOT NULL, 
snum integer NOT NULL, 
CHECK ((cnum > snum) AND (onum > cnum))); 
 
Глава 19
 
1. CREATE TABLE Cityorders 
(onum integer NOT NULL PRIMARY KEY, 
amt decimal, 
cnum integer, 
snum integer, 
city char (15), 
FOREIGN KEY (onum, amt, snum) 
 REFERENCES Orders (onum, amt, snum), 
FOREIGN KEY (cnum, city) 
 REFERENCES Customers (cnum, city) ); 
2. CREATE TABLE Orders 
(onum integer NOT NULL, 
amt decimal, 
odate date, 
cnum integer NOT NULL, 
snum integer, 
prev integer, 
 UNIQUE (cnum, onum), 
 FOREIGN KEY (cnum, prev) REFERENCES Orders (cnum,onum) );9 
 
 
Глава 21
 
 
1. #1 - не модифицируемый, потому что он использует DISTINCT. 
 #2 - не модифицируемый, потому что он использует объединение, 
 агрегатную функцию, и GROUP BY. 
 #3 - не модифицируемый, потому что он основывается на #1, который 
 сам по себе не модифицируемый. 
 
2. CREATE VIEW Commissions 
 AS SELECT snum, comm 
 FROM Salespeople 
 WHERE comm BETWEEN .10 AND .20 
 WITH CHECK OPTION; 
 
3 CREATE TABLE Orders 
 (onum integer NOT NULL PRIMARY KEY, 
 amt decimal, 
 odate date DEFAULT VALUE = CURDATE, 
 snum integer, 
 cnum integer); 
 CREATE VIEW Entryorders 
 AS SELECT onum, amt, snum, cnum 
 FROM Orders; 
 
 
 
Глава 23
 
 
1. CREATE DBSPACE Myspace 
 (pctindex 15, 
 pctfree 40); 
 
2. CREATE SYNONYM Orders FOR Diane.Orders; 
 
3. Они должны быть откатаны обратно назад. 
 
4. Блокировка взаимоисключающего доступа. 
 
5. Только чтение 
Глава 24
 
1. SELECT a.tname, a.owner, b.cname, b.datatype 
 FROM SYSTEMCATOLOG a, SYSTEMCOLUMNS b 
 WHERE a.tname = b.tname 
 AND a.owner = b.owner 
 AND a.numcolumns > 4; 
Обратите Внимание: из-за того что большинство имен столбца 
объединяемых таблиц - различны, не все из используемых псевдонимов a
 и b в вышеупомянутой команде - строго обязательны. Они представлены просто для понимания.
 
 
2. SELECT tname, synowner, COUNT (ALL synonym) 
 FROM SYTEMSYNONS 
 GROUP BY tname, synowner; 
 
3 SELECT COUNT (*) 
 FROM SYSTEMCATALOG a 
 WHERE numcolumns/2 < 
 (SELECT COUNT (DISTINCT cnumber) 
 FROM SYSTEMINDEXES b 
 WHERE a.owner = b.tabowner 
 AND a.tname = b.tname); 
 
 
Глава 25
 
 
1. 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 = 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; {основной программы}