Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции О_о DataBase.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
8.68 Mб
Скачать
    1. Краткая характеристика языка sql pl db2® udb

SQL PL представляет собой высокоуровневый язык программирования, имеющий простой синтаксис и обычный набор управляющих предложений, таких как IF, ELSE, WHILE, FOR, ITERATE, а также некоторые другие предложения.

Подмножество языка SQL PL, используемое при создании триггеров и функций, определено как встроенный (inline) язык SQL PL. Слово «inline» подчеркивает тот факт, что функции, написанные с использованием встроенного SQL PL, реализуются путем встраивания (внедрения) тела функции в запрос, использующий эту функцию.

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

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

Составное динамическое предложение SQL

Составное динамическое предложение SQL имеет следующий синтаксис:

[ метка : ] BEGIN ATOMIC

объявление_SQL_переменной_или_условия ;

процедурное_предложение_SQL ;

END [ метка ]

метка – определяет метку составного предложения. Если указана начальная метка (перед фразой BEGIN), она может быть использована для уточнения SQL переменных в составном предложении, а также в предложении LEAVE. Конечная метка (после фразы END) может быть указана только в том случае, если указана начальная метка, и должна совпадать с начальной меткой. Метка может быть указана только в том случае, если составное динамическое предложение используется в определении триггера или функции.

ATOMIC – указывает, что если при выполнении составного динамического предложения возникает ошибка, выполнение составного предложения завершается, и все выполнившиеся к моменту появления ошибки предложения SQL, включенные в составное динамическое предложение, будут откачены.

Объявление SQL переменной определяет локальную переменную в составном динамическом предложении и имеет следующий вид:

DECLARE имя_SQL_переменной [ , … ] тип_данных [ DEFAULT значение ]

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

Тип данных – указывает тип данных переменной.

DEFAULT значение – задает для переменной значение по умолчанию. Может быть указано NULL. Значения переменных инициализируются при вызове динамического составного предложения. Если значение по умолчанию не указано, переменные инициализируются значением NULL.

В одном предложении DECLARE можно объявить несколько переменных одного и того же типа.

Объявление условия определяет имя условия и соответствующее значение SQLSTATE и имеет следующий вид:

DECLARE имя_условия CONDITION FOR [ SQLSTATE [ VALUE ] ] строковая_константа

Имя условия задает имя условия, на которое можно ссылаться только в том составном предложении, в котором оно определено.

FOR SQLSTATE строковая_константа – определяет значение SQLSTATE, ассоциированное с условием. Строковая константа должна иметь длину 5 символов и не должна иметь значение ’00000’.

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

Процедурное предложение SQL может быть представлено одним из следующих предложений:

  • предложения ЯМД SQL (INSERT, DELETE, UPDATE)

  • предложения формирования запросов (VALUES, SELECT),

  • управляющие предложения языка SQL PL (FOR, IF, ITERATE, LEAVE, WHILE),

  • CALL,

  • SET переменная,

  • GET DIAGNOSTICS,

  • MERGE,

  • SIGNAL.

Кроме указанных выше предложений, в составном предложении, используемом для определения функции, допускается еще и предложение RETURN.

Управляющие предложения

1. Предложение IF осуществляет выбор на основании проверки некоторых условий и имеет следующий синтаксис:

IF условие THEN процедурное_предложение_SQL ; . . .

[ ELSEIF условие THEN процедурное_предложение_ SQL ; . . . ]

[ ELSE процедурное_предложение_SQL ; . . . ]

END IF

условие – определяет условие, в соответствии с которым осуществляется выбор той или иной группы процедурных предложений SQL. Если результат вычисления условия – истина (true), выполняется процедурное предложение SQL, указанное после следующего за условием ключевого слова THEN; если же результат вычисления условия – ложь (false) или не определен (unknown), выполнение предложения IF продолжается с вычисления следующего условия, указанного конструкцией ELSEIF (если она включена в предложение), и так до тех пор, пока не будет получено значение результата истина (true) или не будет достигнута фраза ELSE предложения.

Пример:

. . .

IF rating = 1 THEN

UPDATE employee SET salary = salary * 1.10, bonus = 1000

WHERE empno = employee_number;

ELSEIF rating = 2 THEN

UPDATE employee SET salary = salary * 1.05, bonus = 500

WHERE empno = employee_number;

ELSE

UPDATE employee SET salary = salary * 1.03, bonus = 0

WHERE empno = employee_number;

END IF

2. Предложение FOR позволяет организовать циклическое выполнение группы предложений SQL PL для каждой строки некоторой таблицы. Предложение имеет следующий синтаксис:

[ метка: ] FOR имя_цикла

AS предложение_SELECT

DO

процедурное_предложение_SQL ;

. . .

END FOR [ метка ]

Пояснения:

метка – определяет метку предложения FOR. Если указана начальная метка (перед фразой FOR), она может быть использована в теле цикла в предложениях LEAVE и ITERATE. Конечная метка (после фразы END FOR) может быть указана только в том случае, если указана начальная метка, и должна совпадать с начальной меткой.

имя_цикла – определяет метку для неявного составного предложения, сгенерированного для реализации предложения FOR. Эта метка должна удовлетворять правилам задания меток составных предложений за тем исключением, что она не может быть использована в предложениях ITERATE и LEAVE в теле цикла FOR. Имя_цикла используется для уточнения имен колонок, возвращаемых указанным в FOR предложением SELECT.

Процедурные предложения SQL, указанные в теле цикла, выполняются для каждой строки таблицы, полученной в результате выполнения предложения SELECT. Значения колонок каждой строки доступны в теле цикла непосредственно через имена колонок.

Пример:

. . .

FOR vl AS SELECT firstnme, midinit, lastname FROM employee

DO

SET fullname = lastname || ’,’ || firstnme ||’ ’ || midinit;

INSERT INTO tnames VALUES (fullname);

END FOR

3. Предложение WHILE позволяет организовать циклическое выполнение группы предложений SQL PL, пока некоторое условие сохраняет значение истина. Предложение имеет следующий синтаксис:

[ метка: ] WHILE условие DO

процедурное_предложение_SQL;

. . .

END WHILE [ метка ]

Пояснения:

метка – определяет метку предложения WHILE. Если указана начальная метка (перед фразой WHILE), она может быть использована в теле цикла в предложениях LEAVE и ITERATE. Конечная метка (после фразы END WHILE) может быть указана только в том случае, если указана начальная метка, и должна совпадать с начальной меткой.

условие – определяет условие, которое вычисляется перед каждой итерацией цикла. Если результат вычисления условия – истина, тело цикла выполняется.

4. Предложение ITERATE позволяет начать новую итерацию указанного цикла:

ITERATE метка

Предложения, записанные после ITERATE, не выполняются, и управление передается на заголовок цикла, помеченного указанной меткой.

5. Предложение LEAVE позволяет прервать выполнение указанного цикла:

LEAVE метка

Предложения, записанные после LEAVE, не выполняются, и управление передается первому предложению, записанному после тела цикла, соответствующего указанной метке.

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

Предложение CALL используется для вызова процедуры и имеет следующий синтаксис:

CALL имя_процедуры [ ( список_аргументов) ]

Имя процедуры определяет процедуру, которая должна быть вызвана.

Список аргументов содержит аргументы, перечисленные через запятую. Процедура может не иметь аргументов.

В качестве аргумента может быть указано выражение или значение NULL, n-ый аргумент в списке аргументов соответствует n-ому параметру в определении процедуры, созданному с помощью предложения CREATE PROCEDURE, и должен быть совместим с ним. Так, если параметр в определении процедуры объявлен как входной (IN), соответствующий аргумент должен допускать возможность присваивания его значения параметру. Если параметр в определении процедуры объявлен как выходной (OUT), соответствующим аргументом должно быть имя переменной или маркер параметра, представленный символом «?» (вопросительный знак). Если же параметр в определении процедуры определен как INOUT, должны выполняться требования, определенные и для IN параметров, и для OUT параметров.

Например, если некоторая процедура была определена с помощью следующего предложения:

CREATE PROCEDURE PARTS_ON_HAND (IN PARTNUM INTEGER,

OUT COST DECIMAL(7,2),

INOUT QUANTITY INTEGER)

. . .

Вызов данной процедуры может иметь следующий вид:

CALL PARTS_ON_HAND (2, ?, ?)

Процедуры, вызываемые из составного динамического предложения, не должны выполнять предложения COMMIT или ROLLBACK.

Предложение SET переменная

Предложение SET имеет много вариантов использования в языке SQL PL. Здесь рассматривается предложение SET, используемое для установки значения переменной.

Предложение SET может быть использовано следующим образом:

SET целевая_переменная = значение [, … ]

или

SET (целевая_переменная,) = ( список_значений ) [, … ]

Здесь целевая переменная указывает переменную, которой присваивается значение. В качестве целевой переменной может быть указано имя переменной SQL, объявленной ранее; имя колонки целевой таблицы триггера (если предложение SET используется в определении триггера – CREATE TRIGGER); имя параметра процедуры (если предложение SET используется в определении процедуры – CREATE PROCEDURE).

Значение определяет новое значение, которое должно быть присвоено целевой переменной, и может быть задано одним из трех способов: выражение, NULL или DEFAULT.

Выражение записывается в соответствии с ранее представленными правилами. Если предложение SET используется в определении триггера, выражение может включать ссылки на переменные передачи, указанные с помощью ключевых слов OLD и NEW (см. ниже описание предложения CREATE TRIGGER).

NULL – указывает пустое значение.

DEFAULT – указывает, что должно использоваться значение по умолчанию. Если целевая переменная представляет имя колонки, получаемое значение зависит от того, как эта колонка была определена при создании соответствующей таблицы. Если целевая переменная представляет переменную SQL, получаемое значение определяется из объявления переменной.

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

Если предложение SET с подзапросом используется в триггере, подзапрос может содержать ссылки на переменные передачи, указанные в конструкциях NEW и OLD.

С помощью одного предложения SET можно присвоить значения нескольким переменным.

Примеры:

1. Присвоить переменной SQL p_com значение NULL:

SET p_com = NULL

2. Увеличить значение переменной SQL p_sal на 10%:

SET p_sal = p_sal + (p_sal * .10)

3. Присвоить переменным SQL p_sal и p_com средние значения колонок SALARY и COMM:

SET (NEW_VAR.SALARY, NEW_VAR.COMM) =

(SELECT AVG(SALARY), AVG(COMM) FROM EMPLOYEE)

Предложение GET DIAGNOSTICS

Предложение GET DIAGNOSTICS позволяет получить информацию о ранее выполнившемся предложении SQL. Конкретный формат предложения GET DIAGNOSTICS зависит от того, какой результат выполнения предшествующего предложения SQL требуется получить.

1. Если необходимо получить числовой результат выполнения предшествующего предложения SQL, предложение GET DIAGNOSTICS имеет следующий вид:

GET DIAGNOSTICS имя_SQL_переменной = тип_результата

Здесь имя SQL переменной называет целочисленную переменную, которой присваивается результат выполнения предшествующего предложения SQL,

тип результата – определяет, что именно надо получить; может быть задан следующим образом:

ROW COUNT – предложение GET DIAGNOSTICS выполняется после предложений SQL DELETE, INSERT или UPDATE и возвращает количество строк, обработанных предшествующим предложением SQL;

DB2_RETURN_STATUS – предложение GET DIAGNOSTICS выполняется после предложения CALL вызова хранимой процедуры и возвращает код завершения, возвращаемый хранимой процедурой.

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

2. Если необходимо получить текст сообщения об ошибке или предупреждения, возвращаемые предшествующим предложением SQL, предложение GET DIAGNOSTICS записывается следующим образом:

GET DIAGNOSTICS EXCEPTION 1 имя_SQL_переменной = тип_сообщения

Здесь имя переменной SQL называет строковую переменную, которой присваивается сообщение,

тип сообщения – указывает, что именно надо получить; может быть задан следующим образом:

MESSAGE_TEXT – предложение GET DIAGNOSTICS возвращает сообщение об ошибке или предупреждение, полученное при выполнении предшествующего предложения SQL. Текст сообщения возвращается на языке сервера базы данных, где выполнялось соответствующее предложение SQL. Если предшествующее предложение SQL завершилось с нулевым значением SQLCODE, GET DIAGNOSTICS возвращает пустую строка.

DB2_TOKEN_STRING – предложение GET DIAGNOSTICS возвращает маркеры (tokens) сообщений об ошибке или предупреждении, полученные при выполнении предшествующего предложения SQL. Если предшествующее предложение завершилось с нулевым значением SQLCODE, или SQLCODE не имеет маркера, GET DIAGNOSTICS возвращает пустую строка.

Такую форму предложения GET DIAGNOSTICS можно использовать только в хранимых процедурах.

Пример: определить, сколько строк было модифицировано при выполнении предложения UPDATE:

UPDATE CORPDATA.PROJECT SET PRSTAFF = PRSTAFF + 1.5

WHERE DEPTNO = deptnbr;

GET DIAGNOSTICS rcount = ROW_COUNT;

...

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

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

Предложение MERGE имеет следующий синтаксис:

MERGE INTO целевой_объект [ [ AS ] корреляционное_имя [ ( имя_колонки, …) ] ]

USING источник ON условие_поиска

WHEN условие_соответствия THEN операция

. . .

[ ELSE IGNORE ]

Условие соответствия задается в виде:

[ NOT ] MATCHED [ AND условие_поиска ]

Операция задается в виде предложений SQL INSERT, DELETE, UPDATE, которые записываются обычным образом, за тем исключением, что в них отсутствует имя таблицы, или предложения SIGNAL.

Целевой объект задает имя таблицы или представления, для которых выполняются операции вставки, удаления и модификации, определяемые предложением MERGE, с учетом всех ограничений, которые накладываются на модифицируемые объекты базы данных. При необходимости, имя целевого объекта может быть заменено корреляционным именем, которое записывается и используется точно так же, как и корреляционные имена в запросах (см. описание предложения SELECT).

USING источник – указывает множество строк результирующей таблицы, которая должна быть соединена с целевой таблицей. Если в результирующей таблице нет строк, генерируется предупреждение «не найдено» (SQLSTATE 02000).

ON условие_поиска – указывает, какие строки из источника должны быть использованы операциями, указанными в предложении. Каждое имя колонки в условии поиска, за исключением тех, которые указаны в подзапросах, должно именовать колонку целевого объекта или источника. Если условие поиска включает подзапрос, в котором указана целевая таблица предложения MERGE, подзапрос будет полностью выполнен, прежде чем какие-либо строки в целевой таблице будут модифицированы или вставлены. Условие поиска применяется к каждой строке целевой таблицы и таблицы источника. Для тех строк таблицы источника, для которых условие поиска истинно, выполняются указанные в предложении операции удаления и модификации. Для тех строк таблицы источника, для которых условие поиска не истинно, выполняются указанные в предложении операции вставки.

WHEN условие_соответствия – указывает условие, при котором выполняется указанная операция. Условия соответствия вычисляются в порядке их записи. Строки, для которых условие соответствия истинно, не рассматриваются в последующих условиях. Rows for which the matching-condition evaluates to true are not considered in subsequent matching conditions.

MATCHED – указывает, что операция должна выполняться только для тех строк, для которых условие поиска, указанное в конструкции ON, истинно. В этом случае, после THEN могут быть указаны только операции UPDATE, DELETE и SIGNAL.

NOT MATCHED – указывает, что операция должна выполняться только для тех строк, для которых условие поиска, указанное в конструкции ON, ложно или не определено. В этом случае, после THEN могут быть указаны только операции INSERT и SIGNAL.

AND условие_поиска – определяет дополнительное условие поиска, которое должно быть применено к отобранным строкам, для того чтобы выполнить операции, указанные после THEN.

ELSE IGNORE – указывает, что никакие действия не должны выполняться для тех строк, для которых условие соответствие не истинно.

Рассмотрим некоторые примеры.

Пример 1. Пусть определена таблица ACTIVITIES с колонками ActID (PK) – код работы и Descr – описание работы. Кроме этой таблицы, имеется таблица ARCHIVE, имеющая такую же структуру. Если в таблице ACTIVITIES описание некоторой работы изменено, или вставлена новая работа, соответствующие изменения должны быть внесены и в таблицу ARCHIVE.

MERGE INTO Archive Ar

USING (SELECT ActID, Descr FROM Activities) Ac

ON (Ar.ActID = Ac.ActID)

WHEN MATCHED THEN UPDATE SET Descr = Ac.Descr

WHEN NOT MATCHED THEN INSERT (ActID, Descr) VALUES (Ac.ActID, Ac.Descr)

Пример 2. Пусть в базе данных необходимо хранить следующую информацию о назначенных работах: код работы (ActID), ее описание (Descr), дата завершения работы (EDate) и дата модификации информации о работе (MDate). Пусть все работы распределены по группам, и для каждой группы работ определена своя таблица с первичным ключом ActID (например, таблица Activities_GroupA содержит все работы, относящиеся к группе А). Колонка EDate в таблице объявлена как NULL колонка: для некоторых работ могут быть не назначены даты окончания.

Пусть также имеется архивная таблица Archive, в которой собрана информация о работах всех групп. По сравнению с основными таблицами, в архивную таблицу добавлена колонка Group – группа работ, и первичный ключ определяется двумя колонками – ActID и Group. Кроме того, в архивной таблице колонка EDate определена как обязательная (NOT NULL), а для колонки MDate определено значение по умолчанию CURRENT TIMESTAMP.

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

MERGE INTO Archive Ar

USING (SELECT ActID, Descr, EDate, MDate FROM Activities_GroupA) Ac

ON (Ar.ActID = Ac.ActID) AND Ar.Group = ’A’

WHEN MATCHED AND Ac.EDate IS NULL THEN

SIGNAL SQLSTATE ’70001’

SET MESSAGE_TEXT = Ac.ActID CONCAT ’ cannot be modified. Reason: Date is not known’

WHEN MATCHED AND Ac.EDate < CURRENT DATE THEN DELETE

WHEN MATCHED AND Ar.MDate < Ac.MDate THEN

UPDATE SET (Descr, EDate, MDate) = (Ac.Descr, Ac.EDate, DEFAULT)

WHEN NOT MATCHED AND Ac.EDate IS NULL THEN

SIGNAL SQLSTATE ’70002’

SET MESSAGE_TEXT = ac.ActID CONCAT ’ cannot be inserted. Reason: Date is not known’

WHEN NOT MATCHED AND Ac.EDate >= CURRENT DATE THEN

INSERT (Group, ActID, Descr, EDate)

VALUES (’A’, Ac.ActID, Ac.Descr, Ac.EDate)

ELSE IGNORE

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

Предложение SIGNAL используется для генерации сообщения об ошибке или предупреждения и может быть задано одним из двух способов:

SIGNAL SQLSTATE [ VALUE ] значение_SQLSTATE [ дополнительная_информация ]

или

SIGNAL имя_условия [ дополнительная_информация ]

Дополнительная информация представляет собой текст сообщения об ошибке и может быть задана в виде:

SET MESSAGE_TEXT = диагностическое_сообщение

SQLSTATE VALUE значение_SQLSTATE – задает строковую константу, представляющую значение SQLSTATE. Константа должна иметь длину 5 символов и должна удовлетворять правилам формирования значения SQLSTATE:

  • каждый символ строки может быть представлен цифрой (от '0' до '9') или буквой верхнего регистра (от 'A' до 'Z');

  • первые два символа SQLSTATE, определяющие класс ошибки, не могут иметь значение '00', так как это значение определяет успешное выполнение предложения.

Если предложение SIGNAL используется в определении триггера или функции, должны выполняться еще и следующие правила:

  • первые два символа SQLSTATE не могут иметь значение '01' или '02', так как эти значения не относятся к классу ошибок;

  • если класс ошибки в SQLSTATE начинается цифрой от '0' до '6' или буквой от 'A' до 'H', тогда подкласс ошибки (последние три символа в значении SQLSTATE) должен начинаться буквой от 'I' до 'Z';

  • если класс ошибки в SQLSTATE начинается цифрой '7', '8', '9', или буквой от 'I' до 'Z', тогда подкласс ошибки может использовать любые цифры от '0' до '9' или буквы от 'A' до 'Z'.

Если значение SQLSTATE не удовлетворяет приведенным выше правилам, возвращается ошибка.

Вместо конкретного значения SQLSTATE может быть указано имя переменной, имеющей тип CHAR(5) и значение, удовлетворяющее описанным выше правилам.

Имя условия – указывает имя условия, объявленного в том же составном предложении, в котором используется предложение SIGNAL.

SET MESSAGE_TEXT = диагностическое_сообщение – указывает строку, описывающую ошибку или предупреждение.

Если выполняется предложение SIGNAL, возвращаемое значение SQLCODE определяется в зависимости от указанного в SIGNAL значения SQLSTATE: если класс ошибки, указанный в SQLSTATE, имеет значение ’01’ или ’02’, возвращается предупреждение или состояние «не найдено», и значение SQLCODE устанавливается равным +438. В остальных случаях, возвращается состояние ошибки, и значение SQLCODE устанавливается равным -438.

Пример:

SIGNAL SQLSTATE ’75002’ SET MESSAGE_TEXT = ’Customer number is not known’;