Понимание SQL (775646), страница 31
Текст из файла (страница 31)
Другая возможность состоит в том, чтобы обрабатывать переменную indicator, связывая ее с каждой переменной главного языка, специальным способом, эмулирующим поведение NULL значений SQL.
Всякий раз, когда вы используете одно из этих значений в вашей программе, например в предложении if ... then, вы можете сначала проверить связанную переменную indicator, является ли ее значение=NULL.
Если это так, то вы обрабатываете переменную по-другому. Например, если NULL значение было извлечено из поля city для главной переменной city, которая связана с переменной indicator - i_city, вы должны установить значение city равное последовательности пробелов. Это будет необходимо, только если вы будете распечатывать его на принтере; его значение не должно отличаться от логики вашей программы.
Естественно, i_city автоматически устанавливается в отрицательное значение. Предположим, что вы имели следующую конструкцию в вашей программе:
If sity = 'London' then
comm: = comm + .01
else comm: = comm - .01
Любое значение, вводимое в переменную city, или будет равно "London" или не будет равно. Следовательно, в каждом случае значение комиссионных будет либо увеличено либо уменьшено. Однако, эквивалентные команды в SQL выполняются по разному:
EXEC SQL UPDATE Salespeople
SET comm = comm + .01
WHERE sity = 'London';
и
EXEC SQL UPDATE Salespeople
SET comm = comm .01;
WHERE sity 'London';
(Вариант на ПАСКАЛе работает только с единственным значением, в то время как вариант на SQL работает со всеми таблицами.) Если значение city в варианте на SQL будет равно значению NULL , оба предиката будут неизвестны, и значение comm, следовательно, не будет изменено в любом случае.
Вы можете использовать переменную indicator чтобы сделать поведение вашего главного языка непротиворечащим этому, с помощью создания условия, которое исключает NULL значения:
If i_city > = O then
begin
If city = 'London' then
comm: = comm + .01
else comm: = comm - .01;
end;
{begin and end нужны здесь только для понимания}
______________________________________________________________
ПРИМЕЧАНИЕ: Последняя строка этого примера содержит ремарку - {begin и end необходимы только для понимания}
_______________________________________________________________
В более сложной программ, вы можете захотеть установить Булеву переменную в "верно" , чтобы указать что значение city =NULL. Затем вы можете просто проверять эту переменную всякий раз, когда вам это необходимо.
ДРУГОЕ ИСПОЛЬЗОВАНИЕ ПЕРЕМЕННОЙ INDICATOR
Переменная indicator также может использоваться для назначения значения NULL. Просто добавьте ее к имени главной переменной в команде UPDATE или INSERT тем же способом что и в команде SELECT.
Если переменная indicator имеет отрицательное значение, значение NULL будет помещено в поле. Например, следующая команда помещает значения NULL в поля city и comm, таблицы Продавцов, всякий раз, когда переменные indicator - i_a или i_b будут отрицательными; в противном случае она помещает туда значения главных переменных:
EXEC SQL INSERT INTO Salespeople
VALUES (:Id_num, :salesperson, :loc:i_a, :comm:i_b);
Переменная indicator используется также, чтобы показывать отбрасываемую строку. Это произойдет если вы вставляете значения символов SQL в главную переменную которая не достаточно длинна чтобы вместить все символы. Это особая проблема с нестандартным типами данных - VARCHAR и LONG (смотри Приложению C). В этом случае, переменная будет заполнена первыми символами строки, а последние символы будут потеряны. Если используется переменная indicator, она будет установлена в положительное значение, указывающее на длину отбрасываемой части строки, позволяя таким образом вам узнать, сколько символов было потеряно.
В этом случае, Вы можете проверить с помощью просмотра -значение переменной indicator > 0, или < 0.
РЕЗЮМЕ
Команды SQL вкладываются в процедурные языках, чтобы объединить силы двух подходов. Некоторые дополнительные средства SQL необходимы, чтобы выполнить эту работу. Вложенные команды SQL транслируемые программой, называемой прекомпилятором, в форму пригодную для использования транслятором главного языка, и используемые в этом главном языке, как вызовы процедуры к подпрограммам которые создает прекомпилятор, называются - модулями доступа.
ANSI поддерживает вложение SQL в языки: ПАСКАЛЬ, ФОРТРАН, КОБОЛ, и PL/I. Другие языки также используются, особенно Си. В попытке кратко описать вложенный SQL, имеются наиболее важные места в этой главе:
*Все вложенные команды SQL начинаются словами EXEC SQL и заканчиваются способом который зависит от используемого главного языка.
*Все главные переменные доступные в командах SQL, должны быть объявлены в разделе объявлений SQL прежде, чем они будут использованы.
*Всем главным переменным должно предшествовать двоеточие когда они используются в команде SQL.
*Запросы могут сохранять свой вывод непосредственно в главных переменных, используя предложение INTO, если и только если, они выбирают единственную строку.
*Курсоры могут использоваться для сохранения вывода запроса, и доступа к одной строке в каждый момент времени. Курсоры бывают обьявлеными (если определяют запрос в котором будут содержаться), открытыми (если выполняют запрос), и закрытыми (если удаляют вывод запроса из курсора). Если курсор открыт, команда FETCH, используется чтобы перемещать его по очереди к каждой строке вывода запроса.
*Курсоры являются модифицируемыми или только-чтение. Чтобы стать модифицируемым, курсор должен удовлетворять всем критериям которым удовлетворяет просмотр; кроме того, он не должен использовать предложений ORDER BY или UNION, которые в любом случае не могут использоваться просмотрами. Не модифицируемый курсор является курсором только-чтение.
*Если курсор модифицируемый, он может использоваться для определения, какие строки задействованы вложенными командами UPDATE и DELETE через предложение WHERE CURRENT OF.
DELETE или UPDATE должны быть вне той таблицы к которой курсор обращается в запросе.
*SQLCODE должен быть объявлен как переменная числового типа для каждой программы которая будет использовать вложенный SQL. Его значение устанавливается автоматически после выполнения каждой команды SQL.
*Если команда SQL выполнена как обычно, но не произвела вывода или ожидаемого изменения в базе данных, SQLCODE = 100. Если команда произвела ошибку, SQLCODE будет равняться некоторому аппаратно определенному отрицательному числу которое описывает ошибку.
В противном случае, SQLCODE = 0.
*Предложение WHENEVER может использоваться для определения действия которое нужно предпринять когда SQLCODE = 100 (не найдено) или когда SQLCODE равен отрицательному числу (SQLERROR).
Действием может быть или переход к некоторой определенной метке в программе (GOTO ) или отсутствие какого-либо действия вообще(продолжить). Последнее, установлено по умолчанию.
*Числовые переменные могут также использоваться как переменные indicator. Переменные indicator следуют за другим именами переменных в команде SQL, без каких бы то ни было посторонних символов кроме (необязательного) слова INDICATOR.
*Обычно, значение переменной indicator = 0. Если команда SQL пытается поместить NULL значение в главную переменную которая использует indicator, indicator будет установлен в отрицательное значение.
Этот факт можно использоваться чтобы предотвращать ошибки, и для помещения NULL значений SQL для специальной обработки их в глав ной программе.
*Переменная indicator может использоваться для вставки NULL значений в команды SQL - INSERT или UPDATE. Она также может принимать положительное значение указывающее на длину отбрасываемой части строки не поместившейся в предельные границы какой-нибудь переменной, куда эта строка помещалась.
РАБОТА С SQL
Обратите внимание: Ответы для этих упражнений написаны в псевдокодах, являющихся английским языком описания логики, которой должна следовать программа. Это сделано для того чтобы помочь читателям которые могут быть незнакомы с Паскалем(или любым другим языком). Кроме того это лучше сфокусирует ваше внимание на включаемых понятиях, опуская частности того или другого языка. Чтобы непротиворечить нашим примерам, стиль псевдокода будет напоминать Паскаль.
Мы опустим из программ все что не относится напрямую к рассматриваемым вопросам, например, определение устройств ввода-вывода, подключение к базе данных, и так далее. Конечно, имеется много способов чтобы выполнять такие упражнения; и совсем не обязательно что представленные варианты решений являются самыми удачными.
1. Разработайте простую программу которая выберет все комбинации по лей snum и cnum из таблиц Порядков и Заказчиков и выясните, всегда ли предыдущая комбинация такая же как последующая. Если комбинация из таблицы Порядков не найдена в таблице Заказчиков, значение поля snum для этой строки будет изменено на удовлетворяющее условию совпадения. Вы должны помнить, что курсор с подзапросом - модифицируем (ANSI ограничение, также применимо к просмотрам, и что базисная целостность базы данных это не тоже самое что проверка на ошибку(т.е. первичные ключи уникальны, все поля cnums в таблице Порядков правильны, и так далее).
Проверьте раздел объявлений, и убедитесь что там объявлены все используемые курсоры.
2. Предположим, что ваша программа предписывает ANSI запрещение курсоры или просмотры использующие модифицируемые подзапросы. Как вы должны изменить вышеупомянутую программу?
3. Разработайте программу которая подсказывает пользователям изменить значения поля city продавца, автоматически увеличивает комиссионные на .01 для продавца переводимого в Барселону и уменьшает их на .01 для продавца переводимого в Сан Хосе. Кроме того, продавец находящийся в Лондоне должен потерять .02 из своих комиссионных, независимо от того меняет он город или нет, в то время как продавец не находящийся в Лондоне должен иметь увеличение комиссионных на .02.
Изменение в комиссионных основывающееся на нахождении продавца в Лондоне, может применяться независимо от того куда тот переводится.
Выясните могут ли поле city или поле comm содержать NULL значения, и обработайте их, как это делается в SQL.
Предупреждение! : эта программа имеет некоторые сокращения.
(См. Приложение A - для ответов.)
Приложение 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
3003 767.19 10/03/1990 2001 1001
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 *