Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Приложение A

ОТВЕТЫ ДЛЯ УПРАЖНЕНИЙ

Глава 1

1. cnum

2. rating

3. Другим словом для строки является - запись. Другим словом для столбца

является - поле.

4. Потому что строки, по определению, находятся без какого либо

определенного упорядочения.

Глава 2

1. Символ ( или текст ) и номер

2. Нет

3. Язык Манипулирования Данными (ЯЗЫК DML)

4. Это слово в SQL имеет специальное учебное значение.

Глава 3

1. SELECT onum, amt, odate

FROM Orders;

2. SELECT *

FROM Customers

WHERE snum = 1001;

3 SELECT city, sname, snum, comm

FROM Salespeople;

4. SELECT rating, cname

FROM Customers

WHERE city = 'SanJose';

5. SELECT DISTINCT snum

FROM Orders;

Глава 4

1. SELECT * FROM Orders WHERE amt > 1000;

2. SELECT sname, city

FROM Salespeople

WHERE city = 'London'

AND comm > .10;

3. SELECT *

FROM Customers

WHERE rating > 100

OR city = 'Rome';

или

SELECT *

FROM Customers

WHERE NOT rating < = 100

OR city = 'Rome';

или

SELECT *

FROM Customers

WHERE NOT (rating < = 100

AND city < > 'Rome');

Могут быть еще другие решения.

4. onum amt odate cnum snum

3001 18.69 10/03/1990 2008 1007

3003 767.19 10/03/1990 2001 1001

3005 5160.45 10/03/1990 2003 1002

3009 1713.23 10/04/1990 2002 1003

3007 75.75 10/04/1990 2004 1002

3008 4723.00 10/05/1990 2006 1001

3010 1309.95 10/06/1990 2004 1002

3011 9891.88 10/06/1990 2006 1001

5. onum amt odate cnum snum

3001 18.69 10/03/1990 2008 1007

onum amt odate cnum snum

3006 1098.16 10/03/1990 2008 1007

3009 1713.23 10/04/1990 2002 1003

3007 75.75 10/04/1990 2004 1002

3008 4723.00 10/05/1990 2006 1001

3010 1309.95 10/06/1990 2004 1002

3011 9891.88 10/06/1990 2006 1001

6. SELECT *

FROM Salespeople;

Глава 5

1. SELECT *

FROM Orders

WHERE odate IN (10/03/1990,10/04/1990);

и

SELECT *

FROM Orders

WHERE odate BETWEEN 10/03/1990 AND 10/04,1990;

2. SELECT *

FROM Customers

WHERE snum IN (1001,1004);

3. SELECT *

FROM Customers

WHERE cname BETWEEN 'A' AND 'H';

ПРИМЕЧАНИЕ: ВЫ ASCII базовой системе Hoffman не буде выве-

ден из-за конечных пробелов после H. По той же самой причине вот-

орая граница не может быть G, поскольку она не выведет имена

Giovanni и Grass.

G может использоваться в сопровождении с Z, так чтобы следовать

за другими символами в алфавитном порядке, а не предшествовать

им, как это делают пробелы.

4. SELECT *

FROM Customers

WHERE cname LIKE 'C%';

5. SELECT *

FROM Orders

WHERE amt < > O

AND (amt IS NOT NULL);

или

SELECT *

FROM Orders

WHERE NOT (amt = O

OR amt IS NULL);

Глава 6


1. SELECT COUNT(*)

FROM Orders

WHERE odate = 10/03/1990;

2. SELECT COUNT (DISTINCT city)

FROM Customers;

3. SELECT cnum, MIN (amt)

FROM Orders

GROUP BY cnum;

4 SELECT MIN (cname)

FROM Customers

WHERE cname LIKE 'G%';

5. SELECT city,

MAX (rating)

FROM Customers

GROUP BY city;

6 SELECT odate, count (DISTINCT snum

FROM Orders

GROUP BY odate;

Глава 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;

Глава 10

1. SELECT *

FROM Orders

WHERE cnum =

(SELECT cnum

FROM Customers

WHERE cname = 'Cisneros');

или

SELECT *

FROM Orders

WHERE cnum IN

(SELECT cnum

FROM Customers

WHERE cname = 'Cisneros');

2. SELECT DISTINCT cname, rating

FROM Customers, Orders

WHERE amt >

(SELECT AVG (amt)

FROM Orders)

AND Orders.cnum = Customers.cnum;

3 SELECT snum, SUM (amt)

FROM Orders

GROUP BY snum

HAVING SUM (amt) >

(SELECT MAX (amt)

FROM Orders);

Глава 11

1. SELECT cnum, cname

FROM Customers outer

WHERE rating =

(SELECT MAX (rating)

FROM Customers inner

WHERE inner.city = outer.city);

2. Решение с помощью соотнесенног7о подзапроса:

SELECT snum, sname

FROM Salespeople main

WHERE city IN

(SELECT city

FROM Customers inner

WHERE inner.snum < > main.snum);

Решение с помощью объединения:

SELECT DISTINCT first.snum, sname

FROM Salespeople first, Customers second

WHERE first.city = second.city

AND first.snum < > second.snum;

Соотнесенный подзапрос находит всех заказчиков не обслуживаемых данным продавцом и выясняет: живет ли кто-нибудь из их в его городе. Решение с помощью обьединения является более простым и более интуитивным. Оно находит случаи где поля city совпадают, а поля snums нет. Следовательно обьединение является более изящным решением для этой проблемы, чем то которое мы исследовали до этого. Имеется еще более изящное решение с помощью подзапроса, с которым Вы столкнетесь позже.

Глава 12

1. SELECT *

FROM Salespeople first

WHERE EXISTS

(SELECT *

FROM Customers second

WHERE first.snum = second.snum

AND rating = 300);

2. SELECT a.snum, sname, a.city, comm

FROM Salespeople a, Customers b

WHERE a.snum = b.snum

AND b.rating = 300;

3. SELECT *

FROM Salespeople a

WHERE EXISTS

(SELECT *

FROM Customers b

WHERE b.city = a.city

AND a.snum < > b.snum);

4. SELECT *

FROM Customers a

WHERE EXISTS

(SELECT *

FROM Orders b

WHERE a.snum = b.snum

AND a.cnum < > b.cnum)

Глава 13

1. SELECT *

FROM Customers

WHERE rating > = ANY

(SELECT rating

FROM Customers

WHERE snum = 1002);

2. cnum cname city rating snum

2002 Giovanni Rome 200 1003

2003 Liu San Jose 200 1002

2004 Grass Berlin 300 1002

2008 Cisneros SanJose 300 1007

3. SELECT *

FROM Salespeople

WHERE city < > ALL

(SELECT city

FROM Customers);

или

SELECT *

FROM Salespeople

WHERE NOT city = ANY

(SELECT city

FROM Customers);

4. SELECT *

FROM Orders

WHERE amt > ALL

(SELECT amt

FROM Orders a, Customers b

WHERE a.cnum = b.cnum

AND b.city = 'London');

5. SELECT *

FROM Orders

WHERE amt >

(SELECT MAX (amt)

FROM Orders a, Customers b

WHERE a.cnum = b.cnum

AND b.city = 'London');

Глава 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

Различие между этими двумя предложениями, в форме второго предиката.

Обратите внимание что, в обоих случаях, строка "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);

Глава 15

1. INSERT INTO Salespeople (city, cname, comm, cnum)

VALUES ('San Jose', 'Blanco', NULL, 1100);

2. DELETE FROM Orders WHERE cnum = 2006;

3. UPDATE Customers

SET rating = rating + 100

WHERE city = 'Rome';

4. UPDATE Customers

SET snum = 1004

WHERE snum = 1002;

Глава 16

1. INSERT INTO Multicust

SELECT *

FROM Salespeople

WHERE 1 <

(SELECT COUNT (*)

FROM Customers

WHERE Customers.snum = Salespeople.snum);

2. DELETE FROM Customers

WHERE NOT EXISTS

(SELECT *

FROM Orders

WHERE cnum = Customers.cnum);

3. UPDATE Salespeople

SET comm = comm + (comm * .2)

WHERE 3000 <

(SELECT SUM (amt)

FROM Orders

WHERE snum = Salespeople.snum);

В более сложный вариант этой команды можно было бы вставить проверку

чтобы убедиться, что значения комиссионных не превышают 1.0 ( 100 % ):

UPDATE Salespeople

SET comm = comm + (comm * .2)

WHERE 3000 <

(SELECT SUM (amt)

FROM Orders

WHERE snum = Salespeople.snum)

AND comm + (comm * .2) < 1.0;

Эти проблемы могут иметь другие, такие же хорошие решения.

1. CREATE TABLE Customers

(cnum integer,

cname char(10),

city char(10),

rating integer,

snum integer);

2. CREATE INDEX Datesearch ON Orders(odate);

( Все индексные имена используемые в этих ответах - произвольные. )

3. CREATE UNIQUE INDEX Onumkey ON Orders(onum);

4. CREATE INDEX Mydate ON Orders(snum, odate);

5. CREATE UNIQUE INDEX Combination ON

Customers(snum, rating);

Глава 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

Глава 20

1. CREATE VIEW Highratings

AS SELECT *

FROM Customers

WHERE rating =

(SELECT MAX (rating)

FROM Customers);

2. CREATE VIEW Citynumber

AS SELECT city, COUNT (DISTINCT snum)

FROM Salespeople

GROUP BY city;

3. CREATE VIEW Nameorders

AS SELECT sname, AVG (amt), SUM (amt)

FROM Salespeople, Orders

WHERE Salespeople.snum = Orders.snum

GROUP BY sname;

4 CREATE VIEW Multcustomers

AS SELECT *

FROM Salespeople a

WHERE 1 <

(SELECT COUNT (*)

FROM Customers b

WHERE a.snum = b.snum);

Глава 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;

Глава 22

1. GRANT UPDATE (rating) ON Customers TO Janet;

2. GRANT SELECT ON Orders TO Stephen WITH GRANT OPTION;

3. REVOKE INSERT ON Salespeople FROM Claire;

4. Шаг 1: CREATE VIEW Jerrysview

AS SELECT *

FROM Customers

WHERE rating BETWEEN 100 AND 500

WITH CHECK OPTION;

Шаг 2: GRANT INSERT, UPDATE ON Jerrysview TO Jerry;

5. Шаг 1: CREATE VIEW Janetsview

AS SELECT *

FROM Customers

WHERE rating =

(SELECT MIN (rating)

FROM Customers);

Шаг 2: GRANT SELECT ON Janetsview TO Janet;

Глава 23

1. CREATE DBSPACE Myspace

(pctindex 15,

pctfree 40);

2. CREATE SYNONYM Orders FOR Diane.Orders;

3. Они должны быть откатаны обратно назад.

4. Блокировка взаимоисключающего доступа.

5. Толко чтение

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; {основной программы}