Объявление курсора



Чувствительность


Выражение запроса в операторе DECLARE CURSOR определяет строки, которые находятся в области действия курсора. Возникает вопрос: что если программный код, расположенный между операторами OPEN и CLOSE, изменяет содержимое некоторых строк так, что они перестают удовлетворять условиям запроса? А если некоторые строки вообще удалены? Продолжает ли команда курсора обрабатывать все строки, которые изначально соответствовали условиям запроса, или же изменяет свое поведение в зависимости от изменений, а может, вообще игнорирует измененные или удаленные строки?
Помни: До окончания построчной обработки в результате запроса DECLARE CURSOR данные могут находиться в полном беспорядке. Такие данные недостоверны и противоречивы. Потому рекомендуется сделать курсор нечувствительным к любым изменениям. Для этого в оператор DECLARE CURSOR нужно добавить ключевое слово INSENSITIVE. В течение времени, когда курсор остается открытым, он нечувствителен к изменениям таблицы, так что область действия курсора распространяется на строки, соответствующие исходным условиям выражения запроса. Курсор не может быть нечувствительным и обновляемым в одно и то же время. Нечувствительный курсор должен быть открыт только для чтения.
Обычные операторы SQL, такие как UPDATE, INSERT или DELETE, работают с набором строк таблицы базы данных, а возможно, со всеми строками таблицы. Во время работы механизм транзакций SQL защищает ее от вмешательства других команд, работающих одновременно с теми же данными. При использовании же курсора данные более уязвимы. В течение всего времени, пока курсор открыт, данные могут быть изменены другими командами. Если открывается один курсор и начинается обработка таблицы, затем открывается другой курсор, а первый курсор остается активным, действия, производимые вторым курсором, могут повлиять на данные, используемые командой первого курсора. Предположим, составлены следующие запросы:
DECLARE Cl CURSOR FOR SELECT * FROM EMPLOYEE
ORDER BY Salary ;
DECLARE C2 CURSOR FOR SELECT * FROM EMPLOYEE



FOR UPDATE OF Salary ;

Теперь предположим, что оба курсора открыты и командой курсора С1 последовательно выбрано несколько строк, а в это время данные по зарплате обновлены с помощью С2. При этом может так получиться, что строка, уже выбранная С1, может опять появиться при последующей выборке.

Проблемы: Проблемы, возникающие в результате взаимодействий нескольких одновременно открытых курсоров или обыкновенных команд SQL и открытых курсоров, можно избежать только путем локализации транзакций. В противном случае можно нарваться на крупные неприятности. Хорошенько запомните: нельзя работать со множеством открытых курсоров.

По умолчанию чувствительность курсора находится в состоянии ASENSITIVE. Значение ASENSITIVE зависит от реализации SQL. В одной реализации оно может быть эквивалентно SENSITIVE, а в другой — INSENSITIVE. Для того чтобы выбрать, какое значение использовать в вашей реализации, прочитайте техническую документацию к вашей системе.


Объявление курсора



Объявление курсора


Чтобы использовать курсор, необходимо сначала объявить о его существовании СУБД. Это делается с помощью оператора DECLARE CURSOR. Фактически она не инициирует никакого действия, а только объявляет имя курсора для СУБД и определяет запрос, с которым будет работать курсор. Синтаксис оператора DECLARE CURSOR имеет следующий вид:
DECLARE имя_курсора [<чувствительность>]
[<перемещаемость>]
CURSOR [<состояние_фиксации>] [<возвращаемость>]
FOR выражение_запроса
[ORDER BY порядок_сортировки]
[FOR разрешение_обновления] ;
Примечание: имя курсора однозначно определяет курсор, следовательно, оно должно отличаться от любого другого имени курсора в модуле или программе.
Чтобы код был удобочитаемым, курсор следует назвать мнемонически, т.е. чтобы из названия следовало, для чего он предназначен. Название курсора должно быть связано либо с данными, определенными в запросе, либо с операциями, которые с этими данными выполняет программный код.
Совет 2

Совет 2

Чувствительность курсора может быть установлена в состояние SENSITIVE, INSENSITIVE или ASENSITIVE. Перемещаемость курсора может быть в состоянии SCROLL (с прокруткой) или NO SCROLL (без прокрутки). Состояние фиксации курсора может быть либо WITH HOLD (с фиксацией), либо WITHOUT HOLD (без фиксации), а возвращаемость — WITH RETURN (с возвратом) либо WITHOUT RETURN (без возврата).


Ориентация перемещаемого курсора



Ориентация перемещаемого курсора


Вследствие того, что в SQL курсор может быть перемещаемым, помимо NEXT можно использовать и другие значения параметра ориентации. После перемещения с ориентацией PRIOR курсор перемещается к предыдущей строке. В случае ориентации FIRST курсор перемещается к первой записи, а в случае ориентации LAST — к последней записи выборки.
Задание ориентации в виде числа требует присутствия команд ABSOLUTE и RELATIVE . Например, FETCH ABSOLUTE 7 перемещает курсор на седьмую строку от начала выборки. FETCH RELATIVE 7 перемещает курсор на семь строк ниже его текущей позиции. FETCH RELATIVE 0 не перемещает курсор.
Оператор FETCH RELATIVE 1 производит такое же действие, что и FETCH NEXT; FETCH RELATIVE-1 действует таким же образом, что и FETCH PRIOR; FETCH ABSOLUTE 1 выбирает первую запись; FETCH ABSOLUTE 2 — вторую запись и т.д. Аналогично, FETCH ABSOLUTE -1 предоставляет последнюю запись, a FETCH ABSOLUTE -2 — предшествующую последней записи выборки и т.д. Оператор FETCH ABSOLUTE 0 генерирует исключение отсутствия данных, таким же образом действует FETCH ABSOLUTE 17, если в выборке только 16 строк. Оператор FETCH <спецификация_простого_значения> возвращает запись, заданную спецификацией простого значения.


Открытие курсора



Открытие курсора


Оператор DECLARE CURSOR определяет, какие строки включать в курсор, но фактически не инициирует никакого действия, являясь лишь объявлением. Оператор OPEN активизирует курсор. Она имеет следующий вид:
OPEN имя_курсора;
Для открытия курсора, приведенного выше в разделе, посвященном предложению ORDER BY, используйте синтаксис:
DECLARE revenue CURSOR FOR
SELECT Model, Units, Price,
Units * Price AS ExtPrice
FROM TRANSDETAIL
ORDER BY Model, ExtPrice DESC ;
OPEN revenue ;
Помни: До тех пор пока курсор не открыт, осуществлять выборку строк из курсора невозможно. После открытия курсора значения переменных, содержащиеся в операторе DECLARE CURSOR, становятся фиксированными, это же относится к функциям даты-времени. Рассмотрим следующий пример:
DECLARE CURSOR C1 FOR SELECT * FROM ORDERS
WHERE ORDERS.Customer= :NAME
AND DueDate < CURRENT_DATE;
NAME := 'Acme Co' ; //Выражение базового языка
OPEN C1;
NAME := 'Omega Inc.' ; //Другое выражение базового языка
...
UPDATE ORDERS SET DueDate = CURRENT_DATE ;
Оператор OPEN фиксирует значение всех переменных, приведенных в объявлении курсора, а также значения всех функций даты-времени. Поэтому второе присваивание имени переменной (NAME := 'Omega Inc.') не влияет на выбранные курсором строки. Это значение NAME будет использоваться при последующем открытии С1. Если даже команда OPEN выполняется до полуночи, а оператор UPDATE выполняется после, значение CURRENT_DATE в операторе UPDATE вычисляется во время выполнения команды OPEN. Это справедливо даже в том случае, если в операторе DECLARE CURSOR нет функций даты-времени.
Внутренняя фиксация (для значений даты-времени)

Похожая "фиксация" значений даты-времени имеет место при выполнении обычных операторов. Посмотрите пример кода: UPDATE ORDERS SET RecheckDate = CURRENTJDATE WHERE ; Пусть сделано несколько заказов. Выполнение кода начинается за минуту до наступления полночи и продолжается пять или десять минут. Если выражение использует функцию CURRENT_DATE (или TIME, или же TIMESTAMP), значение последней на время выполнения выражения фиксируется. Таким образом, все строки ORDERS имеют дело с одинаковым значением текущей даты. Подобным образом обстоит дело и со значениями типа TIMESTAMP, в выражении используется только одно значение, независимо от того, сколько времени работает выражение. Ниже приведен интересный пример проявления такого правила. UPDATE EMPLOYEE SET KEY CURRENT_TIMESTAMP ; Можно подумать, что выражение присваивает уникальное значение идентификатора каждому сотруднику, однако оно присваивает одно и то же значение в каждой строке. Итак, команда OPEN фиксирует значения даты-времени для всех команд, используемых в курсоре.


Перемещаемость



Перемещаемость


Понятие перемещаемость (scrollability) впервые появилось в SQL-92. В реализациях, поддерживаемых SQL-86 и SQL-89. единственным разрешенным перемещением курсора было последовательное, начиная с первой строки, выбранной выражением запроса, и заканчивая последней строкой. Ключевое слово SCROLL оператора DECLARE CURSOR в SQL-92 (и в SQL:2OO3) позволяет получить доступ к строкам в любом порядке по вашему желанию. Синтаксис оператора FETCH контролирует перемещение курсора. Оператор FETCH мы рассмотрим ниже в этой главе.


Позиционные операторы DELETE и UPDATE



Позиционные операторы DELETE и UPDATE


Со строками, на которые в данный момент указывает курсор, можно выполнять операции удаления и обновления. Синтаксис оператора DELETE следующий:
DELETE FROM имя_таблицы WHERE CURRENT OF имя_курсора ;
Если курсор не указывает на строку, генерируется ошибка, и удаление не происходит. Вот синтаксис оператора UPDATE:
UPDATE имя_таблицы
SET имя_столбца = значение [,имя_столбца = значение]...
WHERE CURRENT OF имя_курсора ;
Значение, помещаемое в каждый выбранный столбец, должно являться выражением, ключевым словом или ключевым словом DEFAULT. Если при проведении операции обновления возникает какая-либо ошибка, обновление не выполняется.


Предложение ORDER BY



Предложение ORDER BY


В зависимости от того, что программный код должен делать с данными, иногда требуется обрабатывать выбранные данные в определенном порядке. Сортировку строк перед их обработкой можно выполнять с помощью предложения ORDER BY (упорядочить по). Его синтаксис имеет следующий вид:
ORDER BY спецификация_сортировки [ , спецификация_сортировки]...
Существует множество спецификаций сортировки, каждая из которых имеет следующий синтаксис:
( имя_столбца ) [ COLLATE BY имя_сопоставления ] [ ASC | DESC ]
Для сортировки по столбцу данный столбец должен присутствовать в списке выборки в выражении запроса. Сортировку по столбцам таблицы, не вошедшим в список запроса, выполнить нельзя. Например, требуется произвести операцию, не поддерживаемую SQL, со строками таблицы CUSTOMER. В данном случае можно использовать курсор:
DECLARE custl CURSOR FOR
SELECT CustID, FirstName,LastName, City, State, Phone
FROM CUSTOMER
ORDER BY State, LastName, FirstName
В этом примере оператор SELECT выводит строки, упорядоченные вначале по штату (State), затем по фамилии (LastName) и по имени (FirstName). Перед тем как перейти к первому заказчику из штата Алабама (AL), выбираются все заказчики из штата Аляска (АК). Затем все записи о заказчиках из Аляски сортируются по их фамилиям (Aaron предшествует Abbot). Там, где фамилии совпадают, сортировка производится по имени (George Aaron предшествует Нету Aaron).
Приходилось ли вам когда-нибудь делать 40 копий документа, состоящего из 20 страниц, на копировальном аппарате без сортировщика? Ужас, до чего противная работа! Необходимо организовать место для 20 кучек, которые будут соответствовать 20 страницам документа, и ходить между ними 40 раз туда и обратно, раскладывая 40 копий по этим кучкам. Такой процесс называется сопоставлением. Аналогичный процесс возможен и в SQL.
Сопоставление — это набор правил, определяющих порядок сортировки строк данных. Сортировка по алфавитному порядку установлена по умолчанию. Однако можно выбрать отличный от установленного по умолчанию порядок, по которому будут упорядочиваться данные. Для этого следует использовать необязательный оператор COLLATE BY (использовать сопоставление). Любая реализация изначально поддерживает несколько часто встречающихся сопоставлений. Можно выбрать одно из них, указав лишь, как нужно упорядочивать данные — по возрастанию или по убыванию. Для этого в конце предложения нужно добавить ключевое слово ASC или DESC соответственно.



В операторе DECLARE CURSOR можно использовать столбец, рассчитанный на основе существующих столбцов таблицы. У такого столбца нет имени, которое может использоваться в предложении ORDER BY. Чтобы иметь возможность сослаться на этот столбец, его имя нужно определить в выражении запроса оператора DECLARE CURSOR. Рассмотрим следующий пример:

DECLARE revenue CURSOR FOR

SELECT Model, Units, Price,

Units * Price AS ExtPrice

FROM TRANSDETAIL

ORDER BY Model, ExtPrice DESC ;

В этом примере нет ни одного оператора COLLATE BY в предложении ORDER BY, таким образом, использовалось сопоставление по умолчанию. В четвертом столбце, ExtPrice (общая цена), находятся данные о совокупной цене изделий определенной модели. В предложении ORDER BY задается вначале сортировка по названию модели Model, затем по общей цене ExtPrice. Сортировка по столбцу ExtPrice производится по убыванию (ключевое слово DESC), т.е. вначале обрабатываются более дорогие транзакции.

В предложении ORDER BY по умолчанию используется порядок сортировки по возрастанию. Если в списке спецификаций присутствует сортировка DESC и следующая сортировка также должна производиться по убыванию, для нее следует указать ключевое слово DESC в явном виде. Например, выражение

ORDER BY А, В DESC, С, D, E, F

эквивалентно такому:

ORDER BY A ASC, В DESC, С ASC, D ASC, E ASC, F ASC


Разрешение обновления



Разрешение обновления


Возможны случаи, когда необходимо обновить либо удалить строки таблицы, выбираемые с помощью курсора. В других случаях требуется гарантированно исключить такое обновление или удаление. SQL предоставляет возможность осуществлять контроль с помощью

предложения разрешения обновления в операторе DECLARE CURSOR. Чтобы запретить обновление и удаление в области действия курсора, используйте оператор
FOR READ ONLY
Для разрешения обновления избранных столбцов, при том, что остальные столбцы должны быть защищены, используйте
FOR UPDATE OF имя_столбца [, имя_столбца]...
Помни: Естественно, столбцы, внесенные в приведенный список, должны присутствовать в выражении запроса оператора DECLARE CURSOR. Если предложение разрешения (или запрета) обновления отсутствует, по умолчанию данные всех столбцов, указанных в выражении запроса, могут быть обновлены. В этом случае оператор UPDATE может обновить все столбцы строки области действия курсора, а оператор DELETE может удалить такую строку.


Синтаксис оператора



Синтаксис

Синтаксис оператора FETCH имеет следующий вид:
FETCH [[ориентация] FROM] имя_курсора
INTO целевая_спвцификация [,целевая_спецификация]... ;
Существуют шесть вариантов ориентации:
  • NEXT

  • PRIOR

  • FIRST

  • LAST

  • ABSOLUTE

  • RELATIVE

  • <Спецификация_простого_значения>

  • По умолчанию используется NEXT — единственно возможное значение параметра ориентации в SQL до версии SQL-92. Где бы ни находился курсор, он перемещается на следующую строку в порядке, установленном выражением запроса. Если курсор расположен перед первой записью, он завершает свое выполнение на первую запись. Если он указывает на запись п, то перемещается к записи 77+1. Если курсор указывает на последнюю запись, он прекращает свою работу и в системную переменную SQLSTATE помещается код отсутствия данных. Переменная SQLSTATE, а также остальные средства обработки ошибок в SQL рассматриваются в главе 20.
    Целевыми спецификациями являются либо базовые переменные, либо параметры, в зависимости от того, определен ли курсор во встроенном SQL или в модуле. Количество и типы целевых спецификаций должны соответствовать количеству и типам столбцов, используемых в выражении запроса оператора DECLARE CURSOR. В случае встроенного SQL, если из строки таблицы выбирается список из пяти значений, в выражении запроса должны фигурировать пять переменных с правильно выбранными типами для хранения этих значений.

    SQL отличается от большинства наиболее



    В этой главе...

  • Определение области действия курсора в операторе declare

  • Открытие курсора

  • Построчная выборка данных

  • Закрытие курсора

  • SQL отличается от большинства наиболее популярных языков программирования тем, что в нем операции производятся одновременно с данными всех строк таблицы, в то время как процедурные языки обрабатывают данные построчно. Благодаря использованию курсоров в SQL становится возможным выводить, обновлять или же удалять выбранную строку в один прием, упрощая совместное использование SQL с другими языками программирования.
    По существу, курсор является указателем на определенную строку таблицы. С его помощью можно вывести, обновить или удалить строку, на которую он ссылается.
    Курсоры незаменимы, если требуется выбрать строки из таблицы, проверить их содержимое, а также выполнить различные операции на основании содержимого полей. Одного только SQL в данном случае недостаточно. С помощью SQL можно извлекать строки, однако для принятия решений на основе содержимого полей лучше использовать процедурные языки. Курсоры позволяют SQL по одной извлекать строки из таблицы и передавать их в процедурный код для обработки. Поместив код SQL в цикл, можно строка за строкой полностью обработать всю таблицу.
    В случае использования встроенного SQL в общем все выглядит так:
    EXEC SQL DECLARE CURSOR выражение
    EXEC SQL OPEN выражение
    Проверка достижения конца таблицы
    Программный код
    Начало цикла
    Программный код
    EXEC SQL FETCH
    Программный код
    Проверка достижения конца таблицы
    Конец цикла
    EXEC SQL CLOSE выражение
    Программный код
    В приведенном фрагменте кода командами SQL являются: DECLARE (объявить), OPEN (открыть), FETCH (вызвать) и CLOSE (закрыть). Каждая из этих команд детально рассматривается в этой главе.
    Совет 1

    Совет 1

    Если для выполнения операций с выбранными строками можно обойтись обычными операторами SQL, лучше так и сделать. Используйте для построчной обработки базовый язык лишь в том случае, если обычный SQL не позволяет выполнить необходимые операции.

    Выборка данных из отдельных строк



    Выборка данных из отдельных строк


    Оператор DECLARE CURSOR определяет название курсора и область его действия, оператор OPEN собирает все строки таблицы, удовлетворяющие выражению запроса DECLARE CURSOR, оператор FETCH осуществляет непосредственную выборку данных. Курсор может указывать на одну строку в области действия курсора, или на область, которая находится перед первой строкой области действия, или же на область, расположенную за последней строкой области действия курсора, или на границу строк. Определить, на что именно указывает курсор, можно, используя предложение ориентации оператора FETCH.


    Выражение запроса



    Выражение запроса


    Выражением запроса может быть любой допустимый оператор SELECT. Оператор SELECT выводит строку, на которую указывает курсор в данный конкретный момент времени. Эти строки представляют собой область действия курсора.
    Помни: Запрос не будет выполняться сразу же после выполнения оператора DECLARE CURSOR. Выборка данных обязательно начинается с оператора OPEN. Построчная обработка данных осуществляется в цикле с использованием оператора FETCH.


    Закрытие курсора



    Закрытие курсора


    Совет 3

    Совет 3

    Закончив работу с курсором, тут же закройте его. Курсоры, оставшиеся открытыми после того, как приложение закончило свою работу с ними, как правило, безобидны, но опять-таки не всегда. Кроме того, открытые курсоры используют системные ресурсы.
    По окончании работы "нечувствительного" курсора и его закрытия достаточно повторно открыть этот курсор, и он сможет работать с измененными данными.


    Составные команды

    Атомарность



    Атомарность


    Составные команды вызывают ошибки, никогда не встречающиеся в случае простых команд SQL. Выполнение обычной команды SQL может завершиться успешно или неудачно. Если команда не смогла выполниться, то в базе данных не происходит изменений. В случае составных команд это не так. Посмотрите на предыдущий пример.
    Что в имени твоем?

    Название дополнения SQL — постоянно хранимые модули (persistent stored modules) — очень метко описывает их назначение.

    Да вы уже и сами могли догадаться. Если слово модуль вам неизвестно, освежите в памяти материал главы 15. По логике хранимый модуль должен являться чем-то таким, что находится в некотором месте до тех пор, пока не потребуется. Кроме того, постоянно хранимый модуль должен быть чем-то, что находится под рукой в течение определенного периода времени. Вот, собственно, и все, о чем рассказывается в этой главе.

    Вы почти угадали, хотя логика немного увела вас в сторону. В этой главе описываются подобные модули. Но постоянно хранимые модули больше связаны с другими возможностями SQL. В SQL:2OO3 огромное количество постоянно хранимых модулей содержат необходимые функции, которые следовало включить еще в SQL-92, но этого не произошло. Такие функции значительно повышают мощность и полезность SQL, и они должны были где-то находиться. Некоторые из них действительно хранятся под своими именами (в частности, хранимые функции и хранимые процедуры). Ладно, довольно логики. Важно лишь, что эти новые средства существуют и работают.
    Что если операции вставки в таблицы Students (студенты) и Roster (расписание) произошли, а в результате вмешательства постороннего пользователя операция вставки в таблицу Receivable (плата за учебу) не выполнилась. Получится, что студент будет зачислен, но счет за обучение ему выписан не будет. Такие ошибки могут слишком дорого обойтись университету. Для предотвращения развития событий по данному сценарию необходимо ввести концепцию атомарности. Атомарная команда является неделимой. Она либо выполняется целиком, либо не выполняется вовсе. Простые команды SQL атомарны по своей природе. Другое дело — составные команды SQL. Однако и составную команду тоже можно определить атомарной. В приведенном ниже примере составная команда SQL становится безопасной благодаря введению атомарности.



    void main {

    EXEC SQL

    BEGIN ATOMIC

    INSERT INTO students (StudentID, Fname, Lname)

    VALUES (:sid, :sfname, :sid) ;

    INSERT INTO roster (ClassID, Class, StudentID)

    VALUES (:cid, :cname, :sid) ;

    INSERT INTO receivable (StudentID, Class, Fee)

    VALUES (:sid, :cname, :cfee) ;

    END ;

    /* Проверка значения SQLSTATE на код ошибки */

    }

    Ключевые слова ATOMIC после BEGIN гарантируют выполнение всей команды полностью, а в случае возникновения ошибки происходит откат к исходному состоянию базы данных.


    CASE...END CASE



    CASE...END CASE


    Существуют два вида оператора CASE: простой оператор CASE и оператор CASE с поиском. В зависимости от выполнения нескольких условий выполнение программы происходит по одному из нескольких вариантов.


    Действие и эффект обработчика



    Действие и эффект обработчика


    Как только возникает состояние, вызывающее соответствующий обработчик, выполняется действие, определенное этим обработчиком. Такое действие может быть простой или составной командой SQL. После успешного выполнения обработчика выполняется некоторое последействие, называемое эффектом. Ниже представлен список трех возможных эффектов обработчика.
  • CONTINUE. Выполнение команды, следующей после команды, инициировавшей действие обработчика.

  • EXIT. Выход из составной команды, содержащей обработчик, и выполнение следующей команды.

  • UNDO. Отмена всех предыдущих команд составной и выполнение следующей команды.

  • Эффект CONTINUE лучше всего применять в том случае, если обработчик способен устранить любую проблему, вызвавшую его. Эффект EXIT применяется, если обработчику не под силу исправить проблему, но нет необходимости отменять изменения, сделанные составной командой. Эффект UNDO позволяет вернуться в состояние до выполнения составной команды. Рассмотрим следующий пример:
    BEGIN ATOMIC
    DECLARE constraint_violation CONDITION
    FOR SQLSTATE VALUE '23000' ;
    DECLARE UNDO HANDLER
    FOR constraint_violation
    RESIGNAL ;
    INSERT INTO students (StudentID, Fname, Lname)
    VALUES (:sid, sfname, :slname) ;
    INSERT INTO roster (ClassID, Class, StudentID)
    VALUES (:sid, cname, :sid) ;
    END ;
    Если выполнение какой-либо из двух команд INSERT вызывает нарушение некоторого ограничения, например, в результате добавления записи с первичным ключом, уже присутствующим в таблице, в параметр SQLSTATE помещается значение 23000 и возникает состояние constraint_violation. Обработчик такого события отменяет изменения, внесенные в таблицы командами INSERT. Команда RESIGNAL возвращает управление процедуре, вызвавшей процедуру обработчика.
    После успешного выполнения обеих команд INSERT следующей выполняется команда за ключевым словом END.
    Помни: Ключевое слово ATOMIC является обязательным в случае эффекта UNDO. Это не распространяется на обработчики с эффектами CONTINUE или EXIT.


    FOR...DO...END FOR



    FOR...DO...END FOR


    Цикл FOR в SQL объявляет и открывает курсор, выполняет выборку строк курсора, выполняет команды тела цикла FOR для каждой строки, а затем закрывает курсор. Такой цикл позволяет построчно обрабатывать данные в SQL без обращения к базовому языку. Если реализация SQL поддерживает циклы FOR, их можно использовать в качестве альтернативы: курсорам, описанным в главе 18. Ниже приведен пример цикла FOR.
    FOR vcount AS Cursl CURSOR FOR
    SELECT AsteroidID FROM asteroid
    DO
    UPDATE asteroid SET Description = 'stony iron1
    WHERE CURRENT OF Cursl ;
    END FOR
    В данном примере происходит обновление каждой строки таблицы Asteroid путем ввода 'stony iron' в поле Description. Такой способ ввода данных очень быстрый, но не совсем правильный. Вероятно, следовало бы вначале проверить спектральные характеристики астероидов, а уже затем индивидуально вводить эту информацию в базу данных.


    Хранимые функции



    Хранимые функции


    Хранимые функции (stored functions) аналогичны хранимым процедурам. Вместе они называются хранимыми подпрограммами. Они имеют ряд отличий, например, они отличаются по способу их вызова. Хранимые процедуры вызываются в операторе CALL, а хранимые функции могут являться аргументом оператора SQL. Ниже представлен пример определения функции, сопровождаемый примером обращения к этой функции.
    CREATE FUNCTION PurchaseHistory (CustID)
    RETURNS CHAR VARYING (200)
    BEGIN
    DECLARE purch CHAR VARYING (200)
    DEFAULT '' ;
    FOR x AS SELECT *
    FROM transaction t
    WHERE t.customerID = CustID
    DO
    IF x.description <> ''
    THEN SET purch=purch ',' ;
    END IF ;
    SET purch=purch x.description ;
    END FOR
    RETURN purch ;
    END ;
    Функция, заданная подобным образом, сводит воедино описания всех покупок, произведенных клиентом с определенным идентификационным номером, выбранным из таблицы TRANSACTIONS. Следующая команда, содержащая вызов функции PurchaseHistory, заносит в таблицу информацию о всех покупках, сделанных клиентом с идентификационным номером 314259:
    SET customerID=3142 59 ;
    UPDATE customer
    SET history=PurchaseHistory (customerlD)
    WHERE customerID=314259 ;


    Хранимые модули



    Хранимые модули


    Хранимые модули (stored modules) могут содержать множество подпрограмм, т.е. процедур и (или) функций SQL. Каждый пользователь с полномочиями на выполнение модуля имеет доступ ко всем подпрограммам этого модуля. Полномочия на выполнение отдельных подпрограмм модуля предоставляться не могут. Ниже приведен пример хранимого модуля.
    CREATE MODULE mod1
    PROCEDURE MatchScore
    (IN white CHAR (20),
    IN black CHAR (20),
    IN result CHAR (3),
    OUT winner CHAR (5) )
    BEGIN ATOMIC
    CASE result
    WHEN '1-0' THEN
    SET winner = 'white' ;
    WHEN '1-0' THEN
    SET winner = 'black' ;
    ELSE
    SET winner = 'draw' ;



    END CASE

    END ;

    FUNCTION PurchaseHistory (CustID)

    RETURNS CHAR VARYING (200)

    BEGIN

    DECLARE purch CHAR VARYING (200)

    DEFAULT '' ;

    FOR X AS SELECT *

    FROM transaction t

    WHERE t.cuStomerlD = CustID

    DO

    IF x.description <> ''



    THEN SET purch = purch | | ' . ' ;

    END IF;

    SET purch = purch x.description ;

    END FOR

    RETURN purch ;

    END ;

    END MODULE ;

    Подпрограммы данного модуля никак не связаны между собой. Вообще говоря, подпрограммы можно разнести по разным модулям или собрать в один модуль, независимо от того, есть у них что-нибудь общее или нет.


    Хранимые процедуры



    Хранимые процедуры


    Хранимые процедуры (stored procedures) находятся на сервере баз данных, а не на компьютере пользователя, как это было до появления SQL/PSM. Хранимая процедура должна быть определена, после чего ее можно вызвать с помощью команды CALL. Хранение процедуры на сервере уменьшает сетевой обмен и повышает производительность. Команда CALL является единственным сообщением, передаваемым от пользователя к серверу. Ниже приведен пример создания процедуры.
    EXEC SQL
    CREATE PROCEDURE MatchScore
    (IN white CHAR (20),
    IN black CHAR (20),
    IN result CHAR (3),
    OUT winner CHAR (5) )
    BEGIN ATOMIC
    CASE result
    WHEN '1-0' THEN
    SET winner='white' ;
    WHEN '0-1 ' THEN
    SET winner='black' ;
    ELSE
    SET winner='draw' ;
    END CASE END ;
    После создания хранимой процедуры ее можно вызвать с помощью команды CALL, например:
    CALL MatchScore ('Kasparov', 'Karpov', '1-0', winner);
    Три первых аргумента являются входными параметрами, которые передаются процедуре MatchScore. Четвертый аргумент является выходным параметром, который процедура Match-Score использует для возврата своих результатов в вызывающую программу. В приведенном примере она возвращает значение 'white'.


    IF...THEN...ELSE...END IF



    IF...THEN...ELSE...END IF


    Основной управляющей структурой является IF...THEN...ELSE...END IF. Если условие IF истинно, выполняются команды предложения THEN. В противном случае выполняются команды предложения ELSE. Например:
    IF
    vfname = 'Brandon'
    THEN
    UPDATE students
    SET Fname = 'Brandon'
    WHERE StudentID = 314159 ;
    ELSE
    DELETE FROM students
    WHERE StudentID = 314159 ;
    END IF
    В приведенном примере, если переменная vfname содержит значение 'Brandon', в списке студентов произойдет обновление записи с идентификатором 314159— в поле Fname будет помещено значение 'Brandon1. Если же переменная содержит какое-либо другое значение, отличное от Brandon', запись с идентификатором 314159 будет удалена из таблицы Students.
    Выражение IF...THEN...ELSE...END IF больше всего подходит, если в зависимости от выполнения некоторого условия существуют два варианта дальнейшего поведения программы. Однако очень часто приходится иметь дело с большим количеством вариантов. В таких случаях следует использовать оператор CASE.


    ITERATE



    ITERATE


    Оператор ITERATE позволяет изменять последовательность выполнения команд в циклах SQL. Циклы SQL представлены операторами LOOP, WHILE, REPEAT и FOR. Если условие в операторах циклов является истинным или не задано, тут же оператор ITERATE начинает следующую итерацию цикла. Если же условие итерации является ложным или неопределенным, цикл завершается и выполняются следующие за ним команды:
    AsteroidPreload4:
    SET vcount = 0 ;
    WHILE
    vcount < 1000 DO
    SET vcount=vcount+l ;
    INSERT INTO asteroid (AsteroidID)
    VALUES (vcount) ;
    ITERATE AsteroidPreload4 ;
    SET vpreload = 'DONE' ;
    END WHILE AsteroidPreload4
    Оператор ITERATE все время передает управление в начало цикла WHILE, но до тех пор, пока переменная vcount не будет равна 9999. В следующей итерации переменная vcount увеличится до 10000, выполнится оператор INSERT, после чего оператор ITERATE прекратит итерации, переменная vpreload получит значение 'DONE', а выполнение перейдет к команде, следующей за циклом.


    Курсоры



    Курсоры


    В составных командах можно использовать курсоры. Как уже упоминалось в главе 18, курсоры используются для построчной обработки данных. В составной команде можно объявить курсор, использовать его, а затем забыть о нем, так как курсор уничтожается сразу после завершения выполнения составной команды. Ниже приведен пример использования курсора.
    BEGIN
    DECLARE ipocandidate CHARACTER (30) ;
    DECLARE cursorl CURSOR FOR
    SELECT company
    FROM biotech ;
    OPEN cursor1 ;
    FETCH cursor1 INTO ipocandidate ;
    CLOSE cursor1;
    END ;


    LEAVE



    LEAVE


    Оператор LEAVE (покинуть) действует согласно названию. Как только выполнение программы доходит до оператора LEAVE с меткой, он передает управление команде, расположенной сразу после помеченной. Например:
    AsteroidPreload:
    SER vcount = 0 ;
    LOOP
    SET vcount = vcount+1 ;
    IF vcount > 1000
    THEN
    LEAVE AsteroidPreload;
    END IF ;
    INSERT INTO asteroid (AsteroidID)
    VALUES (vcount) ;
    END LOOP AsteroidPreload
    Приведенный выше код создает 1000 последовательно пронумерованных записей в таблице астероидов и затем завершает цикл.


    LOOP...END LOOP



    LOOP...END LOOP


    Структура LOOP позволяет многократно выполнять некоторую последовательность команд SQL. После выполнения последней команды SQL, находящейся внутри структуры LOOP...ENDLOOP, цикл передает управление первой команде цикла, и все команды цикла выполняются еще раз. Синтаксис структуры LOOP...ENDLOOP имеет следующий вид:
    LOOP
    SET vcount=vcount+1 ;
    INSERT INTO asteroid (AsteroidID)
    VALUES (vcount) ;
    END LOOP
    Приведенный фрагмент кода готовит заготовку для таблицы астероидов, заполняя ее записями пока без данных, но с уникальными идентификаторами. По мере изучения астероидов эту таблицу можно будет заполнить и другими данными.
    Необходимо отметить, что данный фрагмент кода имеет один существенный недостаток. Созданный им цикл является бесконечным. В нем нет кода окончания, следовательно, добавление в таблицу строк будет продолжаться до тех пор, пока СУБД будет располагать местом на диске. Затем система в лучшем случае сгенерирует исключение, а в худшем — просто аварийно завершит работу.
    Для практического использования оператора LOOP необходимо иметь возможность выхода из цикла без возникновения исключения. Для этого имеется оператор LEAVE.


    Необрабатываемые состояния



    Необрабатываемые состояния


    Предположим, в предыдущем примере возникнет состояние, при котором значение SQLSTATE будет отличным от '23000'. Ваш обработчик не может обработать подобное состояние. Так как в текущей процедуре такое состояние не предусмотрено, выполняется команда RESIGNAL. После этого состояние может быть обработано на более высоком уровне. Если же и на этом уровне состояние нельзя обработать, она передается на еще более высокий уровень и т.д., пока состояние не будет обработано или пока не будет сгенерирована ошибка в основном приложении. Основная идея вышесказанного заключается в следующем: если во время выполнения команды SQL возможно появление исключений, необходимо написать обработчики всех возможных исключений. Это позволит намного упростить отладку.


    Объявление обработчиков состояний



    Объявление обработчиков состояний


    Обработчик состояния можно поместить в составную команду. При создании обработчика вначале следует объявить состояние, которое обработчик должен обрабатывать. Объявленное состояние может быть исключением или же некоторым другим состоянием. В табл. 19.2 представлены возможные состояния, а также кратко описаны причины возникновения состояния каждого вида.


    Обработка состояний



    Обработка состояний


    Программу можно написать таким образом, чтобы значение параметра SQLSTATE контролировалось после выполнения каждой команды SQL. Итак, используем приобретенные знания на практике.
  • При получении сообщения кода класса '00' вряд ли необходимо предпринимать дополнительные действия. Продолжайте делать то, что вы планировали.

  • При получении сообщения кода класса '01' или '02' разработчик должен решить, как программа должна отреагировать. Если это допустимые состояния программы, выполнение должно продолжиться по плану. В том случае, если такие сообщения не должны появляться, необходимо перейти к выполнению специальной процедуры, обрабатывающей подобные ситуации.

  • Получение какого-либо другого класса кода указывает на то, что в программе имеются ошибки. В этом случае следует перейти к процедуре обработки исключения. Конкретная процедура, на которую должно перейти выполнение программы, зависит от содержимого параметра SQLSTATE. Если существует возможность множества различных состояний, для каждого следует использовать собственную процедуру обработки, так как различные состояния часто должны обрабатываться по-разному. Некоторые ошибки несущественны или поправимы. Другие являются фатальными и приводят к аварийному завершению приложения.



  • Оператор CASE с поиском



    Оператор CASE с поиском


    Оператор CASE с поиском аналогичен простому оператору CASE, за исключением того, что используется несколько условных выражений, а не одно. Например:
    CASE
    WHEN vmajor
    IN ('Computer Science', 'Electrical Engineering')
    THEN INSERT INTO geeks (StudentID, Fname, Lname)
    VALUES(:sid, :sfname, :slname) ;
    WHEN vclub
    IN ('Amateur Radio', 'Rocket1,'Computer')
    THEN INSERT INTO geeks (StudentID, Fname, Lname)
    VALUES(:sid, :sfname, :slname) ;
    ELSE
    INSERT INTO poets (StudentID, Fname, Lname)
    VALUES(:sid, :sfname, :slname) ;
    END CASE
    Чтобы избежать возможности возникновения исключения, следует поместить всех студентов, которые не являются "физиками" (geeks), в таблицу poets ("лирики")- Конечно, не все "не физики" являются "лириками" — ведь есть же еще и "футболисты", не говоря уже о "химиках". Это не меняет сути дела, так как в оператор CASE всегда можно добавить еще несколько предложений WHEN.


    Операторы управления ветвлением



    Операторы управления ветвлением


    Основным недостатком стандарта SQL-86, не позволяющим считать SQL полноценным процедурным языком, являлось отсутствие управляющих структур. До появления SQL/PSM строгую последовательность выполнения команд нельзя было нарушить без использования базового языка, такого как С или Basic. SQL/PSM получил в свое распоряжение аналогичные управляющие структуры, позволяя тем самым решать многие задачи без привлечения других языков программирования.


    Переменные



    Переменные


    Все высокоуровневые языки программирования, такие как С или Basic, позволяют использовать переменные. До появления SQL/PSM переменные в SQL использовать было нельзя. Переменные являются символическими именами значений определенного типа. В составных командах можно объявить переменную и определить ее значение. В ходе выполнения составной команды переменная может использоваться. После завершения выполнения составной команды все переменные, объявленные в ней, уничтожаются. Таким образом, переменные в SQL являются локальными переменными составной команды, в которой они объявлены. Рассмотрим следующий пример:
    BEGIN
    DECLARE prezpay NUMERIC ;
    SELECT salary
    INTO prezpay
    FROM EMPLOYEE
    WHERE jobtitle= 'president' ;
    END ;


    Полномочия



    Полномочия


    В главе 13 рассматривались различные полномочия, предоставляемые пользователям. Владелец базы данных может предоставить другим пользователям следующие полномочия.
  • На удаление записи из таблицы.

  • На вставку записи в таблицу.

  • На обновления записи в таблице.

  • На создание ссылок на поля таблицы.

  • На использование домена.

  • SQL/PSM добавляет к уже существующим еще один вид полномочий — полномочия на выполнение. Ниже приведены два примера.
    GRANT EXECUTE on MatchScore to TournamentDirector ;
    GRANT EXECUTE on PurchaseHistory to SalesManager ;
    Эти команды предоставляют возможность руководителю шахматного турнира вызывать процедуру MatchScore, а менеджеру по продажам компании — вызывать функцию Purchase-History. Пользователи, которые не имеют полномочий на выполнение подпрограммы, не могут ее использовать.


    Присваивание



    Присваивание


    С появлением SQL/PSM SQL наконец-то получил возможность, которую всегда имели даже самые примитивные процедурные языки, — возможность присваивания значения переменной. Присваивание выглядит так:
    SET переменная = значение ;
    где переменная — имя переменной, а значение — выражение. Ниже приведено несколько примеров присваивания.
    SET vfname = 'Brandon' ;
    SET varea = 3.1416 * :radius * :radius ;
    SET vhiggsmass = NULL ;


    Простой оператор CASE



    Простой оператор CASE


    Простой оператор CASE вычисляет одно выражение. В зависимости от его значения выполнение программы происходит одним из нескольких возможных путей. Например:
    CASE vinajor
    WHEN 'Computer Science'
    THEN INSERT INTO geeks (StudentID, Fname, Lname)
    VALUES(:sid, :sfname, :slname) ;
    WHEN 'Sports Medicine'
    THEN INSERT INTO jocks (StudentID, Fname, Lname)
    VALUES(:sid, rsfname, :slname) ;
    ELSE INSERT INTO undeclared (StudentID, Fname, Lname)
    VALUES(:sid, :sfname, :slname) ;
    END CASE
    Команды предложения ELSE выполняются, если vmajor неТгопадает ни в одну из категорий, заданных предложениями THEN.


    REPEAT...UNTIL..END REPEAT



    REPEAT...UNTIL..END REPEAT


    Цикл REPEAT очень похож на цикл WHILE. Различие между ними заключается в том, что условие проверяется после выполнения команд цикла. Например:
    AsteroidPreload3 :
    SET vcount = 0 ;
    REPEAT
    SET vcount = vcount+1 ;
    INSERT INTO asteroid (AsteroidID)
    VALUES (vcount) ;
    UNTIL vcount = 1000
    END REPEAT AsteroidPreload3
    Совет 1

    Совет 1

    Хотя во всех трех приведенных выше примерах одна и та же операция с одинаковой легкостью выполнялась тремя различными методами (с помощью операторов LOOP, WHILE и REPEAT), очень часто встречаются ситуации, когда один из методов имеет явные преимущества перед другими. Поэтому лучше хорошо знать все три метода и в конкретных обстоятельствах выбрать наиболее подходящий.


    Составные команды



    Составные команды


    В этой книге SQL рассматривается как непроцедурный язык, который применяется в основном для обработки наборов данных, а не отдельных записей. В то же время в этой главе вы узнаете, что это положение постепенно меняется. SQL становится процедурным языком, в основных чертах все еще оставаясь средством для обработки наборов данных. Версия SQL, определяемая стандартом SQL-92, не соответствовала процедурной модели, в которой команды выполняются одна за другой в определенной последовательности. Команды SQL были одиночными и, как правило, встроенными в код программы C++ или Visual Basic. Фактически с помощью ранних версий SQL пользователи не могли создать запрос или выполнить некоторые другие операции с помощью последовательности операторов SQL. Выполнение же последовательности команд SQL вызывало значительное снижение производительности. Каждая выполняющаяся команда SQL должна послать сообщение с места работы пользователя на сервер баз данных, а тот должен отослать ответ в обратном направлении. Это увеличивает сетевой обмен и тем самым приводит к дополнительной нагрузке на сеть.
    SQL: 1999 и SQL:2003 предоставляют возможность создания составных команд, образованных отдельными командами SQL, выполняемыми в один прием. Использование составных команд позволяет снизить загрузку сети, поскольку все отдельные команды, образующие составную, вместе пересылаются на сервер, возвращающий обратно один ответ.
    Все команды, включенные в составную команду, должны быть расположены между ключевыми словами BEGIN и END. Например, чтобы вставить данные во множество связанных таблиц, следует использовать следующий синтаксис:
    void main {
    EXEC SQL
    BEGIN
    INSERT INTO students (StudentID, Fname, Lname)
    VALUES (:sid, :sfname, :sid) ;
    INSERT INTO roster (ClassID, Class, StudentID)
    VALUES (:cid, rename, :sid) ;
    INSERT INTO receivable (StudentID, Class, Fee)
    VALUES (:sid, :cname, :cfee) ;
    END ;
    /* Проверка значения SQLSTATE на код ошибки */
    }
    Приведенный выше небольшой фрагмент программы на языке С содержит встроенную составную команду SQL. Комментарии относятся к обработке ошибок. Если почему-то составная команда не выполнилась, в специальный параметр SQLSTATE будет помещен код ошибки. Понятно, что комментарий не может обработать ошибку. Я поместил его лишь с целью напомнить о том, что в реальной программе код обработки ошибок находится в этом месте.


    Состояния



    Состояния


    Все знают, что означает, когда о человеке говорят, что он дошел до "кондиции". Его состояние наутро после этого может быть тяжелым, очень тяжелым, или же все обойдется. Так и в SQL. Результат выполнения команды SQL может быть успешным, сомнительным или неправильным. Каждый из таких результатов является "состоянием" (condition).
    Каждый раз, когда выполняется команда SQL, сервер базы данных обновляет значение параметра статуса SQLSTATE. Он представляет собой поле из пяти символов. Значение SQLSTATE содержит информацию об успешном или неудачном завершении команды. В случае возникновения ошибки значение содержит ее код.
    Первые два из пяти символов значения класса SQLSTATE содержат информацию о том, выполнены ли команды SQL успешно, непонятно как или неудачно. В табл. 19.1 приведены четыре возможных результата.


    Значения класса sqlstate



    Таблица 19.1. Значения класса sqlstate



    Класс Описание
    00 Успешное завершение
    01 Предупреждение
    02 Не найден
    Другое Сгенерировано исключение

    Значение класса '00' означает, что предыдущая команда SQL выполнена успешно. В большинстве случаев это наиболее желаемый результат.
    Значение класса '01' означает предупреждение. Предупреждение указывает на то, что в ходе выполнения команды SQL случилось что-то незапланированное. В данном случае СУБД не "знает", произошла ошибка или нет. Предупреждение обращает внимание разработчика на то, что требуется тщательно проверить команду SQL.

    Значение класса '02' означает, что не получено никаких данных в результате выполнения команды SQL. Это может быть хорошим или плохим известием, в зависимости от обстоятельств. Иногда результат в виде пустой таблицы — как раз то, что требуется разработчику.
    Любой код, отличный от значений '00', '0Г или '02', указывает на наличие ошибки в программе. Три последних символа параметра SQLSTATE содержат код ошибки. Два символа кода класса и три символа кода ошибки вместе составляют пять символов значения SQLSTATE.


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



    Таблица 19.2. Состояния, которые можно определить в обработчике



    Состояние Описание
    SQLSTATE VALUE ' xxyyy ' Соответствующее значение sqlstate
    SQLEXCEPTION Класс sqlstate, отличный от '00', ' 01' или '02'
    SQLWARNING Класс ' 01'
    NOT FOUND Класс ' 02'

    Ниже приведен пример объявления состояния.
    BEGIN
    DECLARE constraint_violation CONDITION
    FOR SQLSTATE VALUE '23 000' ;
    END ;
    Приведенный пример не является взятым из жизни, поскольку внутри структуры BEGIN...END должны располагаться и команда SQL, ответственная за возникновение особого состояния, и его обработчик.


    Сложные команды, атомарность, курсоры, переменные



    В этой главе...

  • Сложные команды, атомарность, курсоры, переменные и состояния

  • Управляющие структуры

  • Создание циклов

  • Использование хранимых процедур и функций

  • Предоставление полномочий на выполнение

  • Создание и использование хранимых модулей

  • В течение многих лет ведущие специалисты в области технологий баз данных работали над разработкой стандартов. После выхода очередного стандарта и начала его применения пользователями и программистами во всем мире сразу начинается процесс разработки следующего. Так было и в случае SQL-92. Семь лет разделяет выпуск SQL-92 и выход первого компонента SQL: 1999. Однако все эти годы продолжалась кипучая деятельность, в результате которой ANSI и ISO выпустили дополнение к SQL-92, названное SQL-92/PSM (Persistent Stored Modules — постоянно хранимые модули). Это дополнение послужило основой для одного из разделов стандарта SQL: 1999 с тем же названием. SQL/PSM как часть SQL:2003 определяет набор операторов, предоставляющих SQL возможности по созданию управляющих структур, обычных для наиболее мощных языков программирования. Благодаря этому стало возможным решать многие задачи только с использованием SQL, без привлечения других программных средств. Предыдущие версии SQL требовали непрерывного переключения между SQL и процедурным базовым языком.

    Оператор ELSE является необязательным. Однако,



    Внимание

    Оператор ELSE является необязательным. Однако, если он отсутствует и выражение CASE не соответствует ни одному предложению THEN, SQL генерирует исключение.

    WHILE...DO...END WHILE



    WHILE...DO...END WHILE


    Оператор WHILE предоставляет другой метод многократного выполнения последовательности команд SQL. Если условие оператора WHILE истинно, цикл продолжает выполняться. Если нет — выполнение цикла тут же прекращается. Например:
    AsteroidPreload2 :
    SET vcount = 0 ;
    WHILE
    vcount < 100 0 DO
    SET vcount = vcount+1 ;
    INSERT INTO asteroid (AsteroidID)
    VALUES (vcount) ;
    END WHILE AsteroidPreload2
    Результат работы этого кода точно такой же, как в предыдущем случае. Это еще раз подтверждает то, что в SQL существует много методов решения поставленной задачи. Забота программиста — выбрать наиболее подходящий.


    Предложение WHENEVER

    Что означает информация, возвращаемая параметром SQLSTATE



    Что означает информация, возвращаемая параметром SQLSTATE


    В элементах CONNECTTON_NAME и ENVIRONMENTJVAME хранятся названия соединения и той среды, с которой было установлено соединение во время выполнения оператора SQL.
    Если информация из параметра SQLSTATE относится к работе с таблицей, то эту таблицу определяют элементы CATALOG_NAME, SCHEMA_NAME и TABLE_NAME. Если появление ошибки как-то связано со столбцом таблицы, его имя помещается в элемент COLUMN_NAME. Если нештатная ситуация имеет отношение к курсору, его имя будет находиться в элементе CURSOR_NAME.
    Иногда СУБД, чтобы объяснить ситуацию, создает строку текста на каком-либо языке, например английском. Такого рода информация содержится в элементе MESSAGE_TEXT. Его содержимое определяется не стандартом SQL.2003, а реализацией. Если в элементе MESSAGEJTEXT имеется сообщение, его длина в символах записывается в элемент MESSAGE_LENGTH, а длина в октетах — в элемент MESSAGE_OCTET_LENGTH. У сообщения, состоящего из обычных ASCII-символов, значения MESSAGE_LENGTH и MESSAGE_OCTET_LENGTH равны между собой. А если сообщение составлено на китайском, японском или любом другом языке, в котором для выражения символа требуется больше одного октета, то значения MESSAGE_LENGTH и MESSAGE_OCTET_LENGTH будут разными.
    Чтобы получить диагностическую информацию из области заголовка, воспользуйтесь выражением:
    GET DIAGNOSTICS переменная1 = элемент1 [, переменная2 = елемент2] ... ;
    где переменная_n — это параметр или базовая переменная; элемент_n — любое из следующих ключевых слов: NUMBER, MORE, COMMAND_FUNCTION, DYNAMIC_FUNCTION или ROW_COUNT.
    А чтобы получить диагностическую информацию из информационной области, используют следующий синтаксис:
    GET DIAGNOSTICS EXCEPTION номер-состояния
    переменная1 = элемент1 [, переменная2 = элемент2] ... ;
    где переменная_n — это параметр или базовая переменная; элемент_n — любое из семнадцати ключевых слов элементов информационной области. Эти ключевые слова приведены в табл. 20.2. И наконец, номер состояния— это значение элемента CONDITION_NUMBER информационной области.


    Область диагностики



    Область диагностики


    Хотя параметр SQLSTATE в состоянии дать информацию о том, почему неудачно завершился некоторый оператор, но такая информация все же неполная. Поэтому стандарт SQL:2003, кроме того, еще дает возможность перехватывать дополнительную информацию о состоянии и хранить ее в области диагностики. Многократное определение области диагностики работает по принципу стека LIFO (last-in-first-out — последним вошел, первым вышел). Дополнительная информация о состоянии может быть особенно полезной тогда, когда при выполнении единственного оператора SQL появилось множество ошибок. Параметр SQLSTATE сообщает только об одной из них, а область диагностики может рассказать сразу о множестве ошибок (а возможно, и обо всех).
    Область диагностики — это структура данных СУБД, состоящая из двух компонентов.
    Заголовок. В нем находится общая информация о последнем выполнявшемся операторе SQL.
    Информационная область. В ней находится подробная информация о каждом коде (ошибка, предупреждение или успешное выполнение), который был сгенерирован в результате выполнения оператора.


    Область заголовка диагностики



    Область заголовка диагностики


    В главе 14 мы изучали оператор SET TRANSACTION (задать транзакцию). В нем можно указать DIAGNOSTICS SIZE (размер диагностики). Этот размер является количеством информационных областей, выделяемых для хранения информации о состоянии. Если в операторе

    SET TRANSACTION не будет предложения DIAGNOSTICS SIZE, то СУБД выделит количество информационных областей, которое в ней установлено по умолчанию.

    Заголовок области состоит из восьми элементов, которые приведены в табл. 20.1.


    Обработка исключений



    Обработка исключений


    Если параметр состояния SQLSTATE не равен 00000, 00001 или 00002, значит, возникла исключительная ситуация, которую, возможно, нужно будет обработать.

  • Обработка может состоять в возвращении управления родительской процедуре, в которой была вызвана подпроцедура — источник исключения.

  • Второй способ обработки состоит в использовании предложения WHENEVER для перехода на нужную процедуру обработки или выполнения какого-либо другого действия.

  • Третий способ заключается в том, чтобы обрабатывать ситуацию прямо на месте, используя для этого составной оператор SQL. Составным называется такой SQL-оператор, который состоит из более простых операторов SQL, находящихся между ключевыми словами BEGIN (начало) и END (конец).

  • Ниже приведен пример составного оператора, выполняющего обработку исключительных ситуаций.
    BEGIN
    DECLARE ValueOutOfRange EXCEPTION FOR SQLSTATE '73003' ;
    INSERT INTO FOODS
    (Calories)
    VALUES
    (:cal)
    SIGNAL ValueOutOfRange ;
    MESSAGE 'Обрабатывается новое значение количества калорий'
    EXCEPTION
    WHEN ValueOutOfRange THEN
    MESSAGE 'Обработка ошибки выхода количества калорий за допустимый диапазон' ;
    WHEN OTHERS THEN
    RESIGNAL ;
    END
    С помощью одного или нескольких объявлений можно задать имена для всех возможных значений параметра SQLSTATE. Одним из операторов, которые могут вызвать исключительную ситуацию, является INSERT. Если значение :cal превысит максимальное значение элемента данных типа SMALLINT, параметру SQLSTATE будет присвоено значение '73003'. Сигнал о возникновении исключительной ситуации подает оператор SIGNAL (сигнализировать). Этот оператор очищает область диагностики, а также присваивает полю RETURNED_SQLSTATE этой области значение параметра SQLSTATE. Если исключения не было, выполняется обычная последовательность операторов, роль которой в нашем примере играет MESSAGE 'Обрабатывается новое значение количества калорий1. Если же это исключение все же имело место, то обычная последовательность пропускается и выполняется оператор EXCEPTION.
    Как только возникает исключение ValueOutOfRange (значение вне диапазона), выполняется последовательность операторов, представленных в нашем примере одним — MESSAGE 'Обработка ошибки выхода количества калорий за допустимый диапазон'. Когда возникнет какое-либо другое исключение, выполняется оператор RESIGNAL (сигнализировать повторно). Он просто передает управление вызывающей родительской процедуре. В этой процедуре, возможно, есть дополнительный код обработки ошибок, с помощью которого можно обрабатывать исключительные ситуации, не связанные с выходом за пределы диапазона.







    Предложение WHENEVER



    Предложение WHENEVER


    А зачем, собственно, знать, что оператор SQL не выполнился успешно, если с этим уже ничего не поделаешь? Дело здесь вот в чем. Если произошла ошибка, то нельзя, чтобы приложение выполнялось так, будто ничего не случилось. Нужно иметь возможность узнать об ошибке и затем что-то предпринять, чтобы ее исправить. А если исправить ее невозможно, нужно сообщить об ошибке пользователю и корректно завершить приложение. В SQL для обработки исключительных ситуаций, или, как их еще называют, исключений, имеется такой механизм, как предложение WHENEVER.
    Предложение WHENEVER фактически является объявлением, поэтому его помещают в разделе объявлений SQL-приложения перед выполняемым кодом SQL. У этого предложения такой синтаксис:
    WHENEVER состояние действие ;
    Состояниями могут быть SQLERROR (ошибка SQL) или NOT FOUND (не найден). А действием — CONTINUE (продолжать) или GOTO адрес (перейти по адресу). Если код класса в параметре SQLSTATE не равен 00, 01 или 02, то возникает состояние SQLERROR. А если параметр SQLSTATE равен 02000, то возникает состояние NOT FOUND.
    Если действием является CONTINUE, то выполнение кода происходит по обычному сценарию. Но когда вместо CONTINUE задано GOTO адрес (или GO TO адрес), точка выполнения перемещается по указанному адресу в программе. Адресом перехода может быть и условное выражение, которое проверяет значение параметра SQLSTATE и, в зависимости от результатов проверки, переводит выполнение по требуемому адресу. Вот несколько примеров предложения WHENEVER:
    WHENEVER SQLERROR GO TO error_trap ;
    ИЛИ
    WHENEVER NOT FOUND CONTINUE ;
    GO TO — это макрокоманда. Реализация, точнее препроцессор встроенного языка, вставляет после каждого оператора EXEC SQL следующую проверку:
    IF SQLSTATE <> '00000'
    AND SQLSTATE <> '00001'
    AND SQLSTATE <> '00002'
    THEN GOTO error_trap;
    Опция CONTINUE означает отсутствие действий, т.е. действие "игнорируй ошибку".


    Пример нарушения ограничения



    Пример нарушения ограничения


    Из всей информации, предоставляемой оператором GET DIAGNOSTICS, самой важной является информация о нарушении ограничения. Рассмотрим пример. Создана таблица EMPLOYEE (сотрудник) со столбцами ID (идентификатор) и Salary (зарплата):
    CREATE TABLE EMPLOYEE
    (ID CHAR(5) CONSTRAINT EmpPK PRIMARY KEY,
    Salary DEC(8,2) CONSTRAINT EmpSal CHECK Salary > 0,
    Dept CHAR(5) CONSTAINT EmpDept
    REFERENCES DEPARTMENT) ;
    Кроме того, имеется таблица DEPARTMENT (отдел) со столбцами DeptNo (номер отдела) и Budget (бюджет):
    CREATE TABLE DEPARTMENT
    (DeptNo CHAR(5),
    Budget DEC(12,2) CONSTRAINT DeptBudget
    CHECK(Budget >= SELECT SUM(Salary) FROM EMPLOYEE
    WHERE EMPLOYEE.Dept=DEPARTMENT.DeptNo),
    ...) ;
    А теперь посмотрите на следующий оператор INSERT:
    INSERT INTO EMPLOYEE VALUES(:ID_VAR, :SAL__VAR, :DEPT_VAR);
    Предположим, что вы получили значение SQLSTATE, равное '23000'. Посмотрев в документацию по SQL, вы видите, что этому значению соответствует описание "нарушение ограничения целостности". Это означает, что имеет место одна из следующих ситуаций.
  • Значение IDJVAR повторяет уже существующее значение ID, т.е. нарушено ограничение PRIMARY KEY.

  • Значение SALJVAR отрицательное — иначе говоря, нарушено ограничение CHECK на столбце Salary.

  • Значение DEPT_VAR не является правильным ключом, соответствующим какой-либо из строк таблицы DEPARTMENT, так что нарушено ограничение REFERENCES в столбце Dept.

  • Значение SAL_VAR настолько большое, что у сотрудников, работающих в отделе, для которого вводятся новые данные, сумма окладов превышает значение Budget для этого отдела. На этот раз имеется нарушение ограничения CHECK в столбце Budget таблицы DEPARTMENT. (Вспомните, что при изменении базы данных должны проверяться все связанные с ним ограничения, а не только те, которые определены в изменяемых таблицах.)

  • Обычно, чтобы узнать причины невыполнения оператора INSERT, приходится проводить большое количество тестов. Но на этот раз все, что нужно, можно узнать с помощью команды GET DIAGNOSTICS:
    DECLARE ConstNameVar CHAR(18) ;
    GET DIAGNOSTICS EXCEPTION 1
    ConstNameVar = CONSTRAINT_NAME ;
    И если значение SQLSTATE равно '23000', то этот оператор GET DIAGNOSTICS присваивает переменной ConstNameVar одно из следующих значений: 'EmpPK', 'EmpSal', 'EmpDept' или 'DeptBudget'. Обратите внимание, для того, чтобы однозначно определить ограничение CONSTRAINT_NAME, еще могут понадобиться значения элементов CONSTRAINT_SCHEMA и CONSTRAINT_CATALOG.


    SQLSTATE



    SQLSTATE


    Параметр SQLSTATE позволяет определить множество нештатных ситуаций. Он представляет собой строку из пяти символов, в которой могут находиться буквы в верхнем регистре от А до Z и цифры от 0 до 9. Эта строка делится на две группы — двухсимвольный код класса и трехсимвольный код подкласса.
    В стандарте SQL:2003 определены все коды класса, начинающиеся с букв от А до Н или с цифр от 0 до 4. Поэтому любой такой код во всех реализациях означает одно и то же. Что касается кодов классов, которые начинаются с букв от I до Z или с цифр от 5 до 9, то их значение определяется конкретными реализациями СУБД. Дело в том, что спецификация SQL не может предусмотреть все ситуации, которые могут произойти в каждой реализации. Впрочем, если говорить откровенно, разработчикам нужно пореже использовать эти нестандартные коды классов. Нестандартные коды усложняют переход с одной СУБД на другую. Лучше, конечно, вообще обойтись стандартными кодами, а нестандартные использовать только в виде исключения.
    Если в параметре SQLSTATE код класса равен 00, оператор завершился успешно. А код класса, равный 01, означает уже другое: хотя оператор и завершился успешно, но вывел предупреждение. Если нет данных, значение этого кода становится равным 02. Любое другое значение кода класса, находящееся в параметре SQLSTATE, означает, что выполнение опера-гора не было успешным.
    Так как после каждой операции SQL параметр SQLSTATE обновляется, проверять его можно после выполнения каждого оператора. Если значение параметра SQLSTATE — 00000 (успешное завершение), то можно приступить к выполнению следующей запланированной операции. Ну а если в нем находится что-то другое, то для обработки ситуации, возможно, придется отклониться от той обычной последовательности выполнения кода. Какое из нескольких возможных действий следует выполнить — зависит от находящихся в параметре SQLSTATE значений кодов класса и подкласса.
    Чтобы параметр состояния SQLSTATE можно было использовать в программе, написанной на модульном языке (о таких программах см. в главе 15), ссылку на этот параметр надо поместить в определении процедуры. Как это делается, показано в следующем примере с процедурой NUTRIENT (питательность), которая работает с таблицей FOODS (продукты питания), имеющей столбцы Foodname (название продукта), Calories (калории), Protein (белки), Fat (жиры) и Carbohidrate (углеводы):



    PROCEDURE NUTRIENT

    (SQLSTATE, :foodname CHAR (20), :calories SMALLINT,

    :rprotein DECIMAL (5,1), :fat DECIMAL (5,1),

    :carbo DECIMAL (5,1))

    INSERT INTO FOODS

    (Foodname, Calories, Protein, Fat, Carbohidrate)

    VALUES

    (:foodname, rcalories, :protein, :fat, :carbo) ;

    В нужном месте программы, написанной на процедурном языке, вы можете присвоить параметрам определенные значения (возможно, используя пользовательский ввод), а затем вызвать саму процедуру. Синтаксис этой операции в разных языках разный и выглядит примерно так:

    foodname = "Okra, boiled" ;

    calories = 29 ;

    protein = 2.0 ;

    fat = 0.3 ;

    carbo = 6.0 ,-

    NUTRIENT(state, foodname, calories, protein, fat, carbo) ;

    Значение SQLSTATE возвращается переменной state (состояние). Ваша программа может проверять эту переменную и, в зависимости от ее значения, выполнять то или иное действие. (Для тех, кто не знает, окра — это такое растение, которое еще называется бамией. В пищу идут недозрелые стручки, которые варят, и созревшие семена, из которых делают суррогат кофе. — Примеч. пер.)


    Область заголовка диагностики



    Таблица 20.1. Область заголовка диагностики



    Поля Тип данных
    number (количество) Точный числовой, масштаб О
    row_count (количество строк) Точный числовой, масштаб О
    command_functton (командная функция) Символьная строка переменного размера, не менее 128 символов
    COMMAND_FUNCTION_CODE (КОД КОМЭНДНОЙ фуНКЦИИ) Точный числовой, масштаб О
    more (больше) Символьная строка, длина 1
    transact ions_commi ted (фиксированные транзакции) Точный числовой, масштаб О
    transactions_rolled_back (откатанные транзакции) Точный числовой, масштаб О
    transactions_active (состояние транзакции) Точный числовой, масштаб О

    Ниже эти элементы описаны более детально.
  • В поле NUMBER хранится количество областей, заполненных диагностической информацией о текущей операции.

  • В поле ROW_COUNT содержится количество строк, задействованных при выполнении оператора SQL INSERT, UPDATE или DELETE.

  • Поле COMMAND_FUNCTION описывает только что выполненный динамический оператор SQL (если последний выполненный оператор SQL действительно был динамическим).

  • Поле COMMAND_FUNCTION_CODE отображает номер кода для только что выполненного динамического оператора SQL (если последний выполненный оператор SQL действительно был динамическим). Каждая динамическая функция имеет соответствующий код.

  • Поле MORE содержит одно из значений: 'Y' (да) или 'N' (нет). Значение 'Y' указывает на то, что записей состояния больше, чем может вместить область диагностики. Значение 'N' означает, что все сгенерированные записи состояния представлены в области диагностики. Вы можете получить необходимое количество записей, увеличив его, используя оператор SET TRANSACTIONS, однако эта возможность зависит от используемой вами реализации.

  • Поле TRANSACTIONS_COMMITED содержит количество совершенных транзакций.

  • Поле TRANSACTIONS_ROLLED_BACK содержит количество транзакций, которые были откатаны.

  • Поле TRANSACTIONS_ACTIVE содержит значение 'Г, если транзакция в настоящее время активна, и значение '0' в противном случае. Транзакция считается допустимой для активизации, если открыт курсор или СУБД находится в ожидании отложенного параметра.

  • Информационная область диагностики

    В информационных областях хранятся данные по каждой отдельной ошибке, предупреждению или состоянию успешного завершения. Каждая информационная область (табл. 20.2) состоит из 26 элементов.


    Информационная область диагностики



    Таблица 20.2. Информационная область диагностики



    Элемент Тип данных
    CONDITION_NUMBER (номер состояния) Точный числовой, масштаб 0
    RETURNED_SQLSTATE (значение SQLSTATE) Символьная строка, 6 символов
    MESSAGE_TEXT (текст сообщения) Символьная строка переменного размера,

    не менее 128 символов
    MESSAGE_LENGTH (длина сообщения) Точный числовой, масштаб 0
    MESSAGE OCTET LENGTH (длина сообщения в октетах) Точный числовой, масштаб 0
    CLASS_ORIGIN (источник класса) Символьная строка переменного размера,

    не менее 128 символов
    SUBCLASS_ORIGIN (источник подкласса) Символьная строка переменного размера,

    не менее 128 символов
    CONNECTION_NAME (имя соединения) Символьная строка переменного размера,

    не менее 128 символов
    SERVER_NAME (имя сервера) Символьная строка переменного размера,

    не менее 128 символов
    CONTRAINT_CATALOG (каталог ограничения) Символьная строка переменного размера,

    не менее 128 символов
    CONTRAINT_SCHEMA (схема ограничения) Символьная строка переменного размера,

    не менее 128 символов
    CONSTRAINT_NAME (имя ограничения) Символьная строка переменного размера,

    не менее 128 символов
    ENVIRONMENT_NAME (имя среды) Символьная строка переменного размера,

    не менее 128 символов
    CATALOG_NAME (имя каталога) Символьная строка переменного размера,

    не менее 128 символов
    SCHEMA_NAME (имя схемы) Символьная строка переменного размера,

    не менее 128 символов
    TABLE_NAME (имя таблицы) Символьная строка переменного размера,

    не менее 128 символов
    COLUMN_NAME (имя столбца) Символьная строка переменного размера,

    не менее 128 символов
    CURSOR_NAME (имя курсора) Символьная строка переменного размера,

    не менее 128 символов
    CONDITION_IDENTIFIER (идентификатор состояния) Символьная строка переменного размера,

    не менее 128 символов
    PARAMETR_NAME (имя параметра) Символьная строка переменного размера,

    не менее 128 символов
    ROUTINE_CATALOG (каталог программы) Символьная строка переменного размера,

    не менее 128 символов
    ROUTINE_SCHEMA (схема программы) Символьная строка переменного размера,

    не менее 128 символов
    ROUTINE_NAME (имя программы) Символьная строка переменного размера,

    не менее 128 символов
    SPECIFIC_NAME (специфическое имя) Символьная строка переменного размера,

    не менее 128 символов
    TRIGGER_CATALOG (каталог триггера) Символьная строка переменного размера,

    не менее 128 символов
    TRIGGER_SCHEMA (схема триггера) Символьная строка переменного размера,

    не менее 128 символов
    TRIGGER_NAME (имя триггера) Символьная строка переменного размера,

    не менее 128 символов
    <


    В элементе CONDITION_NUMBER содержится порядковый номер информационной области. Если оператор создает пять элементов состояния, которые заполняют пять информационных областей, то значение CONDITION_NUMBER для пятой такой области будет равно пяти. Чтобы получить доступ к конкретной информационной области, используйте оператор GET DIAGNOSTICS (получить диагностику) вместе с требуемым значением CONDITTONJSrUMBER. (Об операторе GET DIAGNOSTICS рассказывается ниже, в разделе "Что означает информация, возвращаемая SQLSTATE".) А в элементе RETURNED_SQLSTATE находится значение SQLSTATE, соответствующее данным этой информационной области.
    Элемент CLASS_ORIGIN сообщает, откуда взято значение для кода класса, возвращаемое в параметре SQLSTATE. Если значение определено стандартом SQL, то элемент CLASS_ORIGIN равен TSO 9075'. А если оно определено реализацией СУБД, то в элементе CLASS_ORIGIN находится строка, в которой указана СУБД-источник. Элемент SUBCLASS_ORIGIN, в свою очередь, сообщает источник значения для кода подкласса, которое возвращено в параметре SQLSTATE.
    Значение, находящееся в элементе CLASS_ORIGIN, является достаточно важным. Значение SQLSTATE, равное, например, '22012', относится к стандартным значениям этого параметра. Поэтому вам известно, что оно означает одно и то же во всех реализациях SQL. Однако если значение SQLSTATE равно '22500', первые два символа находятся в стандартном диапазоне и указывают на исключительную ситуацию, связанную с отсутствием данных, а последние три символа уже находятся в диапазоне, определяемом реализацией. Ну а если значение SQLSTATE равно '90001', то это значение полностью находится в диапазоне, определяемом реализацией. Одни и те же значения SQLSTATE, находящиеся в таком диапазоне, могут в разных реализациях означать совершенно различные понятия.
    А где же найти описание '22500' или '90001' Для этого надо взглянуть в документацию пользователя СУБД. А какой именно СУБД? Ведь с помощью оператора CONNECT можно соединиться сразу с несколькими. Чтобы узнать, какой из них является источником ошибки, взгляните на элементы CLASS_ORIGIN и SUBCLASS_ORIGIN. В них находятся значения, которые определяют каждое приложение. Проверяя эти значения, можно определить, к какой СУБД относятся значения SQLSTATE. Значения, находящиеся в элементах CLASS_ORIGIN и SUBCLASS_ORIGIN, также определяются реализацией, но обычно содержат название компании-разработчика СУБД.
    Если ошибка является нарушением ограничения, это ограничение можно определить с помощью элементов CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA и CONSTRAINT_NAME.

    было бы замечательно, чтобы каждое



    В этой главе...

  • Подача сигнала об ошибке

  • Переход к коду обработки ошибок

  • Ограничение, вызвавшее ошибку

  • Ошибка какой СУБД произошла

  • Правда, было бы замечательно, чтобы каждое написанное вами приложение все время работало прекрасно? Еще бы! А если еще и выиграть 57 миллионов долларов в лотерею, что проводится в штате Орегон, то вообще было бы все круто! К сожалению, вероятность первого события не превышает вероятности второго. Те или иные состояния ошибки случаются неизбежно, поэтому полезно знать их причины. В SQL:2003 механизмом, передающим информацию об ошибке, является параметр состояния (или переменная базового языка) SQLSTATE (состояние SQL). С помощью этой информации можно выполнить те или иные действия, которые помогают исправить ошибку.
    Скажем, предложение WHENEVER (как только) дает возможность выполнять заранее заготовленное действие, как только возникает некоторая ситуация, например, когда у параметра SQLSTATE появляется ненулевое значение. Кроме того, подробную информацию о состоянии только что выполненного оператора SQL можно найти в области диагностики. В данной главе рассказывается об этих полезных средствах и о том, как их использовать.

    Ввод новых ограничений в уже созданную таблицу



    Ввод новых ограничений в уже созданную таблицу


    Особенно полезен оператор GET DIAGNOSTICS для определения нарушаемых ограничений при изменении исходных таблиц. Например, в таблицу с помощью оператора ALTER TABLE вводят ограничения, которых не было при написании программы:
    ALTER TABLE EMPLOYEE
    ADD CONSTRAINT SalLimit CHECK(Salary < 200000) ;
    Теперь, когда вы вставите данные в таблицу EMPLOYEE или обновите в ней столбец Salary и значение в этом столбце превысит 200000, значение SQLSTATE станет равно '23000'. В таких случаях можно запрограммировать вывод каких-либо полезных сообщений. Например, такого рода: "Неправильное выполнение оператора INSERT: нарушение ограничения SalLimit".


    Игнорирование масштаба проекта



    Игнорирование масштаба проекта


    В начале разработки проекта ваш клиент рассказывает, что именно он ждет от нового приложения. К сожалению, клиент почти всегда забывает что-то сказать, причем его забывчивость чем-то одним, как правило, не ограничивается. В процессе работы неожиданно возникают и добавляются в проект новые требования. И если вам за проект установлена не почасовая оплата, то этот рост его масштабов может привести к тому, что когда-то прибыльный проект станет убыточным. Все, что вы обязуетесь сделать, должно быть зафиксировано в письменном виде еще до начала работы над проектом. А что касается новых требований, появляющихся во время работы над проектом, то их надо подкреплять дополнительным временем и бюджетом.


    Использование только своих любимых системных архитектур



    Использование только своих любимых системных архитектур


    Никто не может быть экспертом по всем вопросам. СУБД, работающие в среде дистанционной обработки данных, отличаются от тех, которые работают в средах клиент/сервер, средах с разделением ресурсов или распределенных средах. Одна или две системы, в которых вы эксперт, могут не подходить для полученного вами задания. Но все равно нужно выбрать самую лучшую архитектуру, даже если это означает передачу задания кому-либо другому. Лучше совсем не получить задание, чем получить его и сделать такую систему, которая не нужна клиенту.


    Мнение, что клиенты знают, чего хотят



    Мнение, что клиенты знают, чего хотят


    Обычно клиенты приглашают вас спроектировать для них базу данных, когда сталкиваются с трудностями, а имеющиеся у них методы не работают. Клиенты часто уверены, что им известно, в чем состоит проблема и как ее решать. По их мнению, все, что они должны сделать, — это рассказать, что именно вам следует делать.
    Однако давать клиенту в точности то, что он просит, — это рецепт заведомой неудачи. Большинство пользователей и их менеджеров не владеют знаниями и квалификацией, нужными для точного определения проблемы, поэтому у них нет шанса найти самое лучшее решение.
    Перед вами стоит задача — тактично убедить клиента, что вы эксперт по анализу систем и что вам необходимо провести такой анализ, чтобы вскрыть реальную причину проблемы. Ведь реальная причина обычно скрыта за более очевидными симптомами.


    Отказ от консультации с другими специалистами



    Отказ от консультации с другими специалистами


    Никто не совершенен. Даже самый лучший проектировщик или разработчик может пропустить важные моменты, которые являются очевидными для любого, кто взглянет на ситуацию с другой точки зрения. И действительно, если вам приходится выставлять свой проект на суд общественности, это вас дисциплинирует и, возможно, помогает избежать многочисленных неприятностей, с которыми в противном случае вы бы наверняка столкнулись. Перед тем как разрабатывать приложение, обязательно покажите проект компетентным профессионалам.


    Отказ от создания документации



    Отказ от создания документации


    Если вы думаете, что ваше приложение настолько совершенно, что за ним не придется смотреть, то сильно ошибаетесь. Единственное в этом мире, в чем можно быть абсолютно уверенным, — это то, что все течет, все изменяется. Это следует учитывать. И если тщательно не документировать, что было сделано и почему сделано именно так, а не иначе, то через шесть месяцев вы уже не сможете этого вспомнить. Кроме того, если вы перейдете в другой отдел или получите огромный выигрыш в лотерею и уволитесь, не оставив документацию по своему проекту, ваш преемник наверняка не сможет внести никаких изменений в ваше творение, чтобы оно соответствовало новым требованиям. И тогда ему, возможно, придется выбросить приложение и начать все с самого начала. Документируйте свою работу не просто в достаточной степени, а с большим запасом. Делайте документацию более подробной, чем это нужно с точки зрения здравого смысла. И если через шесть или восемь месяцев вы вернетесь к проекту, то будете рады, что вся нужная информация задокументирована.






    Отсутствие бета-тестирования



    Отсутствие бета-тестирования


    Приложение, работающее с базами данных, чтобы быть полезным, должно быть сложным. В то же время сложное приложение не может не иметь ошибок. Даже если вы будете проверять свое приложение всеми способами, до которых только сможете додуматься, все равно в нем останутся незамеченные сбойные участки. Бета-тестирование — это передача приложения тем людям, которые не разбираются в нем так хорошо, как вы. Вот они-то наверняка столкнутся со всеми неприятностями, которые вам никогда не встретятся по той причине, что вы слишком много знаете о своем приложении. И все ошибки, выявленные бета-тестерами, вам нужно будет исправить, причем еще до того, как продукт станет использоваться официально.


    Отсутствие обратной связи с клиентами



    Отсутствие обратной связи с клиентами


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


    Применение только своих любимых сред разработки



    Применение только своих любимых сред разработки


    Вы, возможно, потратили месяцы или даже годы на то, чтобы стать специалистом в использовании конкретной СУБД или среды разработки приложений. Но ваша любимая среда, не важно какая, имеет как достоинства, так и недостатки. Время от времени вам будут попадаться задачи-разработки, которые предъявляют высокие требования именно к тем областям, в которых ваша любимая среда разработки находится отнюдь не на высоте. Так что вместо того, чтобы придумывать не самое лучшее решение, лучше остановиться и подумать. У вас есть два варианта. Первый состоит в том, чтобы освоить более подходящий инструмент, а затем использовать его. Второй вариант — это чистосердечно заявить своим клиентам, что их задачу лучше решать с помощью инструмента, в котором вы явно не эксперт. Затем предложите им нанять того, кто сможет продуктивно работать с этим инструментом. Такое профессиональное поведение заставит клиентов еще больше вас уважать. (Но, к сожалению, если вы работаете не на себя, а на фирму, то тогда есть опасность, что вас могут просто сократить.)


    Проектирование таблиц базы данных отдельно друг от друга



    Проектирование таблиц базы данных отдельно друг от друга


    В результате того, что объекты данных и их связи друг с другом определены неправильно, в базе имеются такие таблицы, благодаря которым в данных постоянно появляются ошибки, и это может свести на нет ценность любых результатов. Чтобы спроектировать добротную базу данных, необходимо проанализировать общую схему объектов данных и тщательно проследить их связи друг с другом. Обычно существует не менее одного правильного проекта. Необходимо определить, какой из них вам подходит, учитывая при этом потребности вашего клиента, как нынешние, так и будущие.


    Учет только технических факторов



    Учет только технических факторов


    Разработчики приложений часто рассматривают свои будущие проекты только с точки зрения технической выполнимости и потом оценивают требуемые усилия и время исходя из одного этого фактора. Однако на проект могут оказывать влияние и такие вещи, как максимальная стоимость, имеющиеся ресурсы, требования расписания и организационная политика. На практике они могут превратить технически выполнимый проект в сплошной кошмар. Перед тем как начинать разработку проекта, изучите все сопутствующие ему факторы. Возможно, вы решите, что нет смысла заниматься этим проектом, и намного лучше прийти к этому заключению в самом начале, чем тогда, когда на проект уже затрачены большие усилия.


    Дважды проверяйте запросы, имеющие операторы JOIN



    Дважды проверяйте запросы, имеющие операторы JOIN


    Общеизвестно, что операторы JOIN наглядными никак не назовешь. И если какое-либо из них находится в вашем запросе, то, перед тем, как добавлять в запрос какие-либо предложения WHERE или другие усложняющие компоненты, обязательно проверьте, делает ли это предложение то, что вы от него ожидаете.


    Используйте круглые скобки с ключевыми словами AND, OR и NOT



    Используйте круглые скобки с ключевыми словами AND, OR и NOT


    Когда AND и OR используются вместе, SQL иногда не обрабатывает выражение в том порядке, который вы ожидаете. Чтобы полученный результат был тем, на который вы рассчитываете, используйте круглые скобки. Несколько лишних щелчков на кнопках — это достаточно низкая цена, которую следует заплатить за более достоверные результаты. Кроме того, круглые скобки помогают сделать так, чтобы ключевое слово NOT применялось именно необходимому к терму или выражению.


    Испытывайте запросы на тестовой базе данных



    Испытывайте запросы на тестовой базе данных


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


    Подводите итоги, используя предложение GROUP BY



    Подводите итоги, используя предложение GROUP BY


    Скажем, у вас есть таблица NATIONAL (Национальная бейсбольная лига), содержащая поля с фамилией игрока (поле Player), командой (поле Team) и количеством успешных ударов битой по мячу (поле Homers) для каждого игрока из Национальной лиги. Итоговые данные для всех команд можно получить, если использовать примерно такой запрос:
    SELECT Team, SUM (Homers)
    FROM NATIONAL
    GROUP BY Team ;
    В результате его выполнения получается список команд, в котором за каждой из них указано общее количество успешных ударов битой, выполненных всеми ее игроками.


    Предусмотрите достойный выход из ошибочных ситуаций



    Предусмотрите достойный выход из ошибочных ситуаций


    Делаете ли вы одноразовые запросы с консоли или вставляете запросы в приложение, но время от времени SQL вместо нужных вам результатов выдает сообщение об ошибке. Работая с консоли, вы на основе полученного сообщения можете решить, что же вам делать, а затем выполнить нужное действие. Что касается приложения, то здесь другая ситуация. Пользователь приложения, вероятно, не знает, какое действие является правильным. Поэтому организуйте в своем приложении всеохватную обработку ошибок. Это нужно, чтобы не пропустить ни одной мыслимой ошибки, которая только может возникнуть. Создание кода обработки ошибок потребует больших усилий, но это лучше, чем заставлять пользователя недоуменно смотреть на "зависший" экран.







    Проверяйте структуру базы данных



    Проверяйте структуру базы данных


    Если полученные из базы данные не кажутся вам разумными, проверьте структуру этой базы. Существует много баз данных с неудачной структурой, и если вы работаете с такой базой, то вначале исправьте ее структуру, а лишь затем используйте другое "лекарство". Помните — хорошая структура является предварительным условием сохранения целостности данных.


    Регулярно выполняйте резервное копирование своих баз данных



    Регулярно выполняйте резервное копирование своих баз данных


    Если ваш жесткий диск был разрушен скачком напряжения в сети, огнем, землетрясением или в результате минометного обстрела, то получить данные с этого диска будет нелегко. Поэтому чаще делайте резервные копии и убирайте носители в сухое прохладное место. Что считать безопасным местом, зависит от того, насколько важными являются ваши данные. Им может быть несгораемый сейф, находящийся в той же комнате, что и компьютер, или другое здание. Удобнее всего для этих целей использовать бетонный бункер, выдолбленный в скале и укрепленный настолько, что может выдержать ядерное нападение. Какой уровень безопасности нужен вашим данным — это уже решать вам.


    Трижды проверяйте запросы с подвыборками



    Трижды проверяйте запросы с подвыборками


    Подзапросы позволяют совмещать данные одной таблицы с данными другой, и их часто используют неправильно. Необходимо проверять, чтобы данные, получаемые внутренним оператором SELECT, были теми, которые нужны внешнему оператору SELECT для получения нужного конечного результата. А если имеется более двух уровней подвыборок, то надо быть еще более осторожным.


    Управляйте полномочиями на получение данных



    Управляйте полномочиями на получение данных


    Многие люди не пользуются средствами безопасности, которые имеются в их СУБД. Они не хотят возиться с этими возможностями, считая, что с их данными не может случиться ничего плохого. Не играйте с огнем, иначе останетесь на пепелище. Установите и поддерживайте безопасность для всех объектов баз данных, имеющих хотя бы малейшую ценность.


    Внимательно относитесь к ограничениям предложения GROUP BY



    Внимательно относитесь к ограничениям предложения GROUP BY


    Предположим, вам нужен список самых результативных хиттеров (игроков с битой) Национальной лиги. Проанализируйте следующий запрос:
    SELECT Player, Team, Homers
    FROM NATIONAL
    WHERE Homers >= 2 0
    GROUP BY Team ;
    В большинстве реализаций этот запрос возвращает сообщение об ошибке. Обычно в списке выборке могут появляться только те столбцы, которые применяются для группирования, или столбцы, используемые в итоговой функции. С учетом этого следующий запрос уже вполне работоспособный:
    SELECT Player, Team, Homers
    FROM NATIONAL
    WHERE Homers >= 20
    GROUP BY Team, Player, Homers ;
    Так как все столбцы, которые вы хотите отобразить, указаны в предложении GROUP BY, то запрос выполнится успешно и выведет те результаты, которые вам нужны. Благодаря этой формулировке полученный список будет сперва отсортирован по полю Team, затем по полю Player и Homers.


    Зарезервированные слова



    Зарезервированные слова SQL:2003

    ABS COLLATE DETERMINISTIC
    ALL COLUMN DISCONNECT
    ALLOCATE COMMIT DISTINCT
    ALTER CONDITION DOUBLE
    AND CONNECT DROP
    ANY CONSTRAINT DYNAMIC
    ARE CONVERT EACH
    ARRAY CORR ELEMENT
    AS CORRESPONDING ELSE
    ASENSITIVE COUNT END
    ASYMMETRIC COVAR_POP END-EXEC
    AT COVAR_SAMP ESCAPE
    ATOMIC CREATE EVERY
    AUTHORIZATION CROSS EXCEPT
    AVG CUBE EXEC
    BEGIN CUME_DIST EXECUTE
    BETWEEN CURRENT EXISTS
    BIGINT CURRENT_COLLATION EXP
    BINARY CURRENT_DATE EXTERNAL
    BLOB CURRENT_DEFAULT_TRANSFORM_GROUP EXTRACT
    BOOLEAN CURRENT_PATH FALSE
    BOTH CURRENT_ROLE FETCH
    BY CURRENT_TIME FILTER
    CALL CURRENT_TIMESTAMP FLOAT
    CALLED CURRENT_TRANSFORM_GROUP_FOR_TYPE FLOOR
    CARDINALITY CURRENT_USER FOR
    CASCADED CURSOR FOREIGN
    CASE CYCLE FREE
    CAST DATE FROM
    CEIL DAY FULL
    CEILING DEALLOCATE FUNCTION
    CHAR DEC FUSION
    CHAR_LENGTH DECIMAL GET
    CHARACTER DECLARE GLOBAL
    CHARACTER_LENGTH DAFAULT GRANT
    CHECK DELETE GROUP
    CLOB DENSE_RANC GROUPING
    CLOSE DEREF HAVING
    COALESCE DESCRIBE HOLD
    HOUR NONE REGR_SYY
    IDENTITY NORMALIZE RELEASE
    IN NOT RESULT
    INDICATOR NULL RETURN
    INNER NULLIF RETURNS
    INOUT NUMERIC REVOKE
    INSENSITIVE OCTET_LENGHT RIGHT
    INSERT OF ROLLBACK
    INT OLD ROLLUP
    INTEGER ON ROW
    INTERSECT ONLY ROW_NUMBER
    INTERSECTION OPEN ROWS
    INTERVAL OR SAVEPOINT
    INTO ORDER SCOPE
    IS OUT SCROLL
    JOIN OUTER SEARCH
    LANGUAGE OVER SECOND
    LARGE OVERLAPS SELECT
    LATERAL OVERLAY SENSITIVE
    LEADING PARAMETER SESSION_USER
    LEFT PARTITION SET
    LIKE PERCENT_RANK SIMILAR
    LN PERCENTILE_DISC SMALLINT
    LOCAL POSITION SOME
    LOCALTIME POWER SPECIFIC
    LOCALTIMESTAMP PRECISION SPECIFICTYPE
    LOWER PREPARE SQL
    MATCH PRIMARY SQLEXEPTION
    MAX PROCEDURE SQLSTATE
    MEMBER RANGE SQLWARNING
    MERGE RANK SQRT
    METHOD READS START
    MIN REAL STATIC
    MINUTE RECURSIVE STDDEV_POP
    MOD REF STRDDEV_SAMP
    MODIFIERS REFERENCES SUBMULTISET
    MODULE REFERENCING SUBSTRING
    MONTH REGR_AVGX SUM
    MULTISET REGR_AVGY SYMMETRIC
    NATIONAL REGR_COUNT SYSTEM
    NATURAL REGR_INTERCEPT SYSTEM_USER
    NCHAR REGR_R2 TABLE
    NCLOB REGR_SLOPE TABLESAMPLE
    NEW REGR_SXX THEN
    NO REGR SXY TIME
    TIMESTAMP UNION VAR_SAMP
    TIMEZONE_HOUR UNIQUE VARCHAR
    TIMEZONE_MINUTE UNKNOWN VARYING
    TO UNNEST WHEN
    TRAILING UPDATE WHENEVER
    TRANSLATE UPPER WHERE
    TRANSLATION USER WIDTH_BUCKET
    TREAT USING WINDOW
    TRIGGER VALUE WITH
    TRIM VALUES WITHING
    TRUE VAR POP WITHOUT
    YEAR



    Словарь терминов



    Словарь терминов


    API (Application Programmer's Interface — интерфейс прикладного программиста). Стандартное средство взаимодействия приложения и базы данных или другого системного ресурса.
    CODASYL DBTG. Сетевая модель базы данных. Обратите внимание: в данном случае термин "сетевая" относится не к соединениям по сети, а к структуре данных (т.е. подразумевается не иерархическая, а сетевая структура).
    Internet. Всемирная компьютерная сеть.
    IPX/SPX. Один из протоколов локальных сетей.
    Java. Платформенно-независимый компилируемый язык, специально предназначенный для разработки Web-приложений.
    JavaScript. Язык сценариев, который позволяет программировать Web-страницы, написанные с помощью HTML.
    JDBC (Java DataBase Connectivity — Java-интерфейс взаимодействия с базами данных). Стандартный интерфейс между аплетом или приложением, написанными на Java, и базой данных. Стандарту JDBC предшествовал стандарт ODBC.
    NetBEUI. Один из протоколов локальных сетей.
    ODBC (Open DataBase Connectivity— открытый интерфейс доступа к базам данных). Стандартный интерфейс между базой данных и приложением, которое пытается получить доступ к данным базы. ODBC определяется международным (ISO) и американским (ANSI) стандартами.
    Oracle. Система управления реляционными базами данных, распространяемая компанией Oracle Corporation.
    RAD-инструмент (rapid application development tool — инструмент быстрой разработки приложений). Патентованная графически ориентированная альтернатива языку SQL. Существует множество таких инструментов.
    SEQUEL. Подъязык данных, созданный фирмой IBM. Предшественник SQL.
    SQL. Основной стандартный подъязык данных. Специально предназначен для создания реляционных баз данных, манипуляции и управления ими. Его последней версией является SQL:2OO3.
    SQL, встроенный (SQL, embedded). SQL-код, встроенный в программу, написанную на базовом языке.
    SQL, динамический (SQL, dynamic). Средство создания приложений, которое не требует, чтобы во время компиляции были известны все элементы данных.



    SQL, интерактивный (SQL, interactive). Взаимодействие с базой данных в реальном времени.

    SQL/DS. Система управления реляционными базами данных, распространяемая фирмой IBM Corporation.

    ТСР/IР (Transmission Control Protocol/Internet Protocol — протокол управления передачей/протокол Internet). Сетевой протокол, используемый в Intenet и интранет.

    World Wide Web ("Всемирная паутина"). Часть Internet, для просмотра которой требуется графический пользовательский интерфейс. Доступ к Web выполняется с помощью приложений, называемых Web-браузерами, а информация находится на Web-cepeepax.

    XML (extensible Markup Language — расширяемый язык разметки). Широко используемый язык разметки, который применяется для обмена данными между системами на разных платформах.

    Администратор базы данных (DBA — Database Administrator). Человек, который отвечает за функционирование, целостность и сохранность базы данных.

    Аномалия вставки (insertion anomaly). Несогласованность в многотабличной базе данных. Иногда появляется при вставке строки в одну из таблиц этой базы.

    Аномалия модификации (modification anomaly). Несогласованность данных, которая иногда возникает при модификации (вставке, удалении или обновлении), выполняемой в одной из таблиц базы данных.

    Аномалия обновления (update anomaly). Несогласованность данных, которая иногда возникает в базе данных при обновлении строки одной из таблиц.

    Аномалия удаления (deletion anomaly). Несогласованность в многотабличной базе данных. Иногда появляется при удалении строки в одной из таблиц этой базы.

    Аплет (applet). Небольшое приложение, написанное на языке Java и находящееся на Web-сервере. Предназначено для загрузки и выполнения на Web-клиенте, соединенном с этим сервером.

    Атомарный (atomic). Неспособный к делению на части.

    Атрибут (attribute). Компонент структурированного типа или отношения.

    База данных (database). Самоописательный набор интегрированных записей.

    База данных корпорации (database, enterprise). База данных, в которой находится информация, используемая во всей корпорации.



    База данных организации (database, organizational). База данных, в которой находится информация, используемая во всей организации.

    База данных, персональная (database, personal). База данных, предназначенная для использования одним человеком на единственном компьютере.

    База данных рабочей группы (database, workgroup). База данных, предназначенная для использования внутри организации каким-либо ее отделом или рабочей группой.

    Базовая переменная (host variable). Переменная приложения, написанного на процедурном базовом языке, и доступная встроенному коду SQL.

    Брандмауэр (firewall). Программное обеспечение (или комбинация программного и аппаратного обеспечения) для изоляции сети интранет от Internet и контроля трафика между ними.

    Виртуальная таблица (virtual table). Представление.

    Владелец схемы (schema owner). Пользователь, указанный при создании схемы в качестве ее владельца.

    Вложенный запрос (nested query). Оператор, в котором содержится один или множество подзапросов.

    Внешний ключ (foreign key). Столбец или набор столбцов в таблице из базы данных, который ссылается на первичный ключ из другой таблицы той же базы данных.

    Выражение со значением (value expression). Выражение, в котором комбинируется не менее двух значений.

    Выражение со значением даты-времени (value expression, datetime). Выражение со значением, в котором используются данные типа DATE, TIME, TIMESTAMP или INTERVAL.

    Выражение со значением типа записи (row value expression). Заключенный в круглые скобки список значащих выражений, которые отделены друг от друга запятыми.

    Выражение со значением, строковое (value expression, string). Выражение со значением, в котором символьные строки комбинируются с помощью оператора конкатенации.

    Выражение со значением, условное (value expression, conditional). Выражение со значением, аргументы которого, в зависимости от истинности или ложности некоторых условий, имеют те или иные значения.

    Выражение со значением, числовое (value expression, numeric). Выражение со значением, в котором числовые значения комбинируются с помощью операторов сложения, вычитания, умножения или деления.



    Дескриптор (descriptor). Область памяти, используемая для передачи информации между процедурным кодом приложения и кодом динамического SQL того же приложения.

    Домен (domain). Набор всех значений, допустимых для элемента базы данных.

    Драйвер (driver). Интерфейсная часть СУБД, которая прямо стыкуется с базой данных. Драйверы входят в состав серверной части (back end).

    Запись (record). Представление некоторого физического или умозрительного объекта.

    Запрос (query). Вопрос, который вы задаете о данных, находящихся в базе.

    Зарезервированные слова (reserved words). Слова, имеющее в SQL специальное значение, которые нельзя использовать в качестве имен переменных или каким-то другим не предназначенным для них способом.

    Иерархическая модель базы данных (hierarchical database model). Модель организации данных в древовидной структуре.

    Избыточность данных (data redundancy). Хранение одних и тех же данных одновременно в нескольких местах базы.

    Индекс (index). Таблица с указателями, которые применяются, чтобы быстро находить строки в таблице данных.

    Информационная схема (information schema). Системные таблицы, в которых хранятся метаданные (metadata) базы данных.

    Источник данных (data source). Местонахождение данных, используемых приложением базы данных. Источником данных может быть СУБД или файл данных.

    Итоговая функция (aggregate function). Функция, которая выдает единственный результат после обработки целого набора табличных строк. Также называется функцией набора (setfunction).

    Каталог (catalog). Поименованная совокупность схем.

    Кластер (cluster). Поименованная совокупность каталогов.

    Клиент (client). Рабочая станция отдельного пользователя, на которой находится клиентская часть (front end) СУБД, отображающая информацию на экране и реагирующая на ввод, выполняемый пользователем.

    Клиентская часть (front end). Часть СУБД, которая непосредственно взаимодействует с пользователем.

    Концептуальное представление (conceptual view). Схема базы данных.

    Курсор (cursor). Средство SQL, позволяющее определить набор строк, упорядочить их, а также выбрать текущую строку в этом наборе.



    Логические связки (logical connectives). Используются для получения более сложных предикатов за счет объединения или изменения логических значений простых предикатов.

    Масштаб (scale). Количество цифр в дробной части числового элемента данных.

    Менеджер драйверов (driver manager). Компонент ODBC-совместимого интерфейса базы данных. На машинах с операционной системой Windows менеджер драйверов — это библиотека динамической компоновки, которая связывает источники данных с соответствующими драйверами.

    Метаданные (metadata). Данные о структуре данных, хранящихся в базе.

    Модуль Netscape (Netscape plug-in). Программный компонент, загружаемый с Web-сервера на Web-клиент, для расширения функциональных возможностей браузера.

    Модульный язык (module language). Форма SQL, при которой операторы SQL размещаются в модулях, вызываемых прикладной программой, написанной на базовом языке.

    Нормализация (normalization). Прием, который уменьшает или устраняет возможность появления в базе данных аномалий модификации.

    Область диагностики (diagnostics area). Структура данных, управляемая СУБД. В ней хранится подробная информация о последнем выполнявшемся операторе SQL, а также обо всех ошибках, которые произошли при его выполнении.

    Объединение (join). Реляционный оператор, который объединяет данные из множества таблиц в одну таблицу.

    Объект (object). Однозначно определяемый предмет.

    Объектная целостность (entity integrity). Свойство таблицы из базы данных. Состоит в том, что таблица полностью соответствует моделируемому ею объекту из реального мира.

    Ограничение (constraint). Требование, предъявляемое к данным базы.

    Ограничение, задержанное (constraint, deferred). Ограничение, которое не применяется, пока не будет определено как немедленное (immediate) или пока не будет выполнен оператор COMMIT, завершающий транзакцию.

    Одновременный доступ (concurrent access). Ситуация, когда с одними и теми же табличными строками из базы данных одновременно работают не менее двух пользователей.



    Отношение (relation). Двумерный массив строк и столбцов, причем у каждого из его элементов может быть только одно значение, а строки друг друга не повторяют.

    Параметр (parameter). Переменная в приложении, написанном на модульном языке SQL.

    Первичный ключ (primary key). Столбец или набор столбцов в таблице базы данных, который однозначно идентифицирует каждую строку в этой таблице.

    Плоский файл (flat file). Набор записей с данными, который имеет минимальную структуру.

    Подзапрос (subquery). Запрос, находящийся внутри другого запроса.

    Подтип (subtype). Тип данных является подтипом другого типа данных, если каждое значение первого является также значением второго.

    Подъязык данных (data sublanguage). Подмножество "полноценного" компьютерного языка, предназначенное специально для обработки данных. SQL является подъязыком данных.

    Последовательность сопоставления (collating sequence). Способ упорядочения для символов в символьном наборе. Все последовательности сопоставления, заданные для наборов с латинскими символами (а, Ь, с), задают естественное упорядочение (а, Ь, с...). Они отличаются способами упорядочения специальных символов (+, -, <, ? и т.д.), а также для цифр и букв по отношению друг к другу.

    Предикат (predicate). Утверждение, которое может быть истинным или ложным.

    Представление (view). Компонент базы данных, который ведет себя как таблица, но самостоятельно не существует.

    Преобразование (mapping). Преобразование данных из одного формата в другой.

    Процедурный язык (procedural language). Язык программирования, на котором решение задачи записывается в виде последовательности действий.

    Псевдоним (alias). Краткий заменитель имени таблицы.

    Публикация базы данных (database publishing). Действие, в результате которого содержимое базы данных становится доступным в Internet или интранет.

    Распределенная обработка данных (distributed data processing). Система, в которой данные обрабатываются множеством серверов.

    Реализация (implementation). Отдельная реляционная СУБД, работающая на конкретной аппаратной платформе.



    Сервер базы данных (database server). Серверная часть в системе клиент/сервер (client/server system).

    Серверная часть (back end). Часть СУБД, которая непосредственно взаимодействует с базой данных.

    Сетевая модель базы данных (network database model). Способ организации базы данных, при котором каждый из элементов данных (узел) разрешается связывать с любым другим. Используется для минимизации избыточности данных.

    Сеть интранет (intranet). Сеть, в которой используется аппаратное и программное обеспечение World Wide Web, но доступная пользователям, работающим в одной организации.

    Система дистанционной обработки (teleprocessing system). Мощный центральный процессор, соединенный с множеством терминалов.

    Система клиент/сервер (client/server system). Многопользовательская система, в которой "центральная машина" (сервер) соединяется с множеством интеллектуальных пользовательских рабочих станций (клиентов).

    Составной ключ (composite key). Ключ, состоящий не менее чем из двух столбцов таблицы.

    Ссылочная целостность (referential integrity). Состояние, при котором все таблицы базы данных согласованы друг с другом.

    Столбец (column). Компонент таблицы, в котором находится один из ее атрибутов.

    Строка (row). Последовательность пар (имя поля, значение).

    Структурированный тип (structured type). Тип, определяемый пользователем, представленный как перечень определений атрибутов и методов. Структурированный тип не базируется на отдельном предопределенном исходном типе.

    СУБД (DBMS). Система управления базами данных.

    Супертип (supertype). Тип данных является супертипом другого типа данных, если каждое значение второго является также значением первого.

    Схема (schema). Структура всей базы данных. Информация, которая описывает схему, является метаданными (metadata) базы данных.

    Таблица (table). Отношение.

    Таблица трансляции (translation table). Инструмент для преобразования символьных строк из одного набора символов в другой.

    Тип данных (data type). Совокупность значений, способных представлять данные.



    Тип коллекций (collection type). Тип данных, которые позволяют хранить множество объектов в одном поле строки таблицы.

    Тип ссылки (reference type). Тип данных, значения которых являются ссылками на другие данные.

    Тип, определяемый пользователем (user-defined type). Тип, характеристики которого определяются пользователем.

    Точность (precision). Максимальное количество цифр, которое может иметь числовой элемент данных.

    Транзакция (transaction). Последовательность операторов SQL, результат выполнения которой доступен другим транзакциям только после полного выполнения всех операторов этой транзакции.

    Транзитивная зависимость (transitive dependency). Один атрибут отношения зависит от второго атрибута, который, в свою очередь, зависит от третьего.

    Триггер (trigger). Небольшой код, который определяет реакцию СУБД на некоторые операторы SQL.

    Управляющий элемент ActiveX (ActiveX control). Повторно используемый программный компонент, который можно встраивать в приложение, уменьшая таким образом время разработки. ActiveX использует фирменную технологию Microsoft. Такие компоненты могут использоваться только в средах разработки в операционных системах Windows.

    Утверждение (assertion). Ограничение, указанное не в операторе CREATE TABLE, а в CREATE ASSERTION. Обычно применяется к более чем одной таблице.

    Файловый сервер (file server). Серверный компонент системы с разделением ресурсов. Не содержит никаких программ управления базой данных.

    Функциональная зависимость (functional dependency). Связь между атрибутами отношения.

    Функция значения (value function). Функция, которая выполняет операцию с одной символьной строкой, числом или значением типа даты-времени.

    Функция набора (set function). Функция, которая в результате обработки целого набора табличных строк выдает единственный результат. Также называется итоговой функцией (aggregate function).

    Функция-мутатор (mutator function). Функция, связанная с типом, определяемым пользователем, и имеющая два параметра, зависящих от некоторого атрибута этого типа. Первый параметр (результат) имеет тот же тип, что и тип, определяемый пользователем, а второй параметр — тот же тип, что и определяющий атрибут.



    Целостность домена (domain integrity). Свойство столбца из таблицы базы данных. Состоит в том, что все элементы данных из этого столбца находятся в его домене.

    Ядро базы данных (database engine). Часть СУБД, которая непосредственно взаимодействует с базой данных и является одним из компонентов серверной части (back end).

    Язык манипулирования данными (DML — Data Manipulation Language). Часть SQL, отвечающая за непосредственную работу с данными базы.

    Язык определения данных (DDL — Data Definition Language). Часть SQL, которая используется для определения, изменения и уничтожения структур базы данных.

    Язык разметки гипертекста (HTML — HyperText Markup Language). Стандартный язык форматирования Web-документов.

    Язык управления данными (DCL — Data Control Language). Часть SQL, отвечающая за защиту базы данных.



    

        Базы данных: Разработка - Управление - Excel