Манипулирование данными
Как и в языке SQL/89, в SQL/92 определены два набора операторов манипулирования данных. Операторы первого набора связаны с курсором, и для них осмысленно использование только в режиме встраивания в некоторый традиционный язык программирования. Операторы второго набора предназначены для индивидуального использования и могут применяться как в режиме встраивания, так и в интерактивном режиме. Общие идеи организации обоих наборов операторов манипулирования данными в SQL/92 не изменились, но их возможности существенно расширены. Поэтому в основном мы будем останавливаться на расширениях, не обсуждая подробно всю схему выполнения операторов.
3.6.1. Операторы, связанные с курсором
Для объявления курсора используется конструкция, определяемая следующими синтаксическими правилами:
<declare cursor> ::= DECLARE <cursor name> [ INSENSITIVE ] [ SCROLL ] CURSOR FOR <cursor specification> <cursor specification> ::= <query expression> [ <order by clause> ] [ <updatability clause> ] <updatability clause> ::= FOR { READ ONLY | UPDATE [ OF <column name list> ] } <order by clause> ::= ORDER BY <sort specification list> <sort specification list> ::= <sort specification> [ { <comma> <sort specification> }... ] <sort specification> ::= <sort key> [ <collate clause > ] [ <ordering specification> ] <sort key> ::= <column name> <unsigned integer> <ordering specification> ::= ASC DESC
Пояснения:
(a) если спецификация курсора содержит ключевые слова INSENSITIVE, SCROLL или ORDERBY или если T является только читаемой таблицей, то по умолчанию предполагается задание раздела обновляемости с ключевым словом READONLY;
(b) в противном случае неявно предполагается указание раздела обновляемости с ключевым словом FORUPDATE и без списка имен столбцов (т.е. предполагается, что изменения могут относиться ко всем столбцам T).
Оператор открытия курсора определяется следующим синтаксическим правилом:
<open statement> ::= OPEN <cursor name>
Пояснения:
(a) создается копия S, и в ней все вхождения спецификации цели (имена параметров или внешних переменных) заменяются на соответствующие значения, а также символические константы и вызовы функций даты времени заменяются на соответствующие текущие значения;
(b) пусть T обозначает таблицу, специфицированную копией S;
(c) создается описатель этой таблицы и заполняется в соответствии с особенностями спецификации курсора;
(d) если S содержит INSENSITIVE, то создается копия T, курсор переводится в открытое состояние, и его позиция устанавливается перед первой строкой копии T;
(e) в противном случае курсор переводится в открытое состояние, и его позиция устанавливается перед первой строкой T.
Оператор выборки по курсору определяется следующими синтаксическими правилами:
<fetch statement> ::= FETCH [ [ <fetch orientation> ] FROM ] <cursor name> INTO <fetch target list> <fetch orientation> ::= NEXT |PRIOR |FIRST |LAST { ABSOLUTE | RELATIVE } <simple value specification> <fetch target list> ::= <target specification> [ { <comma> <target specification> }... ]
Пояснения:
(a) если в указании ориентации чтения содержится спецификация простого значения, то пусть J равняется этому значению;
(b) если в указании ориентации присутствует NEXT или FIRST, то пусть J равняется +1;
(c) если в указании ориентации присутствует PRIOR или LAST, то пусть J равняется -1.
(a) если в указании ориентации присутствует ABSOLUTE, FIRST или LAST, то пусть Ttсодержит все строки T с сохранением их порядка;
(b) если в указании ориентации присутствует NEXT или RELATIVE с положительным значением J, то
(i) если таблица T пуста или если позиция курсора установлена на последнюю строку T или за ней, то пусть Tt будет пустой таблицей;
(ii) если позиция курсора установлена на строку R, не являющуюся последней строкой T, то пусть Tt содержит все строки T, стоящие по порядку за R, с сохранением их порядка в T;
(iii) если позиция курсора установлена перед строкой R, то пусть Tt содержит строку R и все строки T, стоящие по порядку за R, с сохранением их порядка в T;
(c) если в указании ориентации присутствует PRIOR или RELATIVE с отрицательным значением J, то
(i) если таблица T пуста или если позиция курсора установлена на первую строку T или перед ней, то пусть Tt будет пустой таблицей;
(ii) если позиция курсора установлена на строку R, не являющуюся первой строкой T, то пусть Tt содержит все строки T, стоящие по порядку перед R, с сохранением их порядка в T;
(iii) если позиция курсора установлена перед строкой, следующей по порядку за R, то пусть Tt содержит строку R и все строки T, стоящие по порядку перед R, с сохранением их порядка в T;
(iv) если позиция курсора установлена после последней строки T, то пусть Tt содержит все строки T с сохранением их порядка.
(d) если специфицировано RELATIVE с нулевым значением J, то
(i) если позиция курсора установлена на строку таблицы T, то пусть Tt включает одну эту строку;
(ii) в противном случае, пусть Tt будет пустой таблицей.
(a) если K больше нуля и не больше N, то курсор позиционируется на K-тую строку Tt и соответствующую строку T; эта строка становится текущей строкой курсора;
(b) В противном случае целям, указанным в списке целей чтения, не присваиваются никакие значения и вырабатывается условие завершения "нет данных"; при этом
(i) если специфицирована ориентация RELATIVE с нулевым значением J, то позиция курсора не меняется;
(ii) если явно или неявно специфицирована ориентация NEXT, либо специфицирована ориентация ABSOLUTE или RELATIVE с K, большим чем N, либо специфицирована ориентация LAST, то курсор позиционируется за последней строкой;
(iii) в противном случае, курсор позиционируется перед первой строкой.
Оператор позиционного удаления имеет тот же синтаксис, что и соответствующий оператор языка SQL/89:
<delete statement: positioned> ::= DELETE FROM <table name> WHERE CURRENT OF <cursor name>
В принципе, оператор и выполняется так же, как предписано в SQL/89, однако в стандарте SQL/92 приводятся некоторые уточнения поведения оператора:
- Если текущая транзакция имеет режим доступа "только чтение" и таблица, из которой удаляется кортеж не является временной, то возбуждается исключительное условие.
- Текущая строка помечается для удаления.
- Если оказалось, что помечаемая строка уже помечена для удаления оператором поискового удаления или оператором позиционного удаления, связанным с другим курсором, или помечена для обновления оператором поисковой модификации или оператором позиционной модификации, связанным с другим курсором, то в условии завершения текущего оператора сообщается соответствующее предупреждение.
- Строка, помеченная для удаления, реально удаляется в конце выполнения оператора позиционного удаления до проверки каких-либо ограничений целостности.
- Если удаляется последний кортеж, то курсор устанавливается в позицию после последней строки; в противном случае курсор устанавливается в позицию перед следующей строкой.
Оператор позиционной модификации также мало отличается от соответствующего оператора SQL/89:
<update statement: positioned> ::= UPDATE <table name> SET <set clause list> WHERE CURRENT OF <cursor name> <set clause list> ::= <set clause> [ { <comma> <set clause> }... ] <set clause> ::= <object column> <equals operator> <update source> <update source> ::= <value expression> |<null specification> |DEFAULT <object column> ::= <column name>
Как и для оператора позиционного удаления, мы поясним только отличия и расширения по отношению к SQL/89:
- Изменения, производимые с использованием упорядоченного курсора, не должны затрагивать столбцы сортировки;
- Если текущая транзакция выполняется в режиме только чтения, возбуждается исключительное условие.
- Будем называть объектной строкой ту строку, из которой порождена текущая строка курсора.
- Если оказалось, что к моменту выполнения операции позиционного обновления объектная строка уже помечена для удаления некоторым поисковым оператором удаления или позиционным оператором удаления, связанным с другим курсором, или если она помечена для обновления некоторым поисковым оператором обновления или поисковым оператором обновления, связанным с другим курсором, генерируется условие завершения с соответствующим предупреждением.
- Ключевое слово DEFAULT в разделе SET означает, что в соответствующий столбец обновляемой таблицы должно быть помещено его значение по умолчанию.
- Выражение, вырабатывающее значение, в разделе SET вычисляется до обновления объектной строки; если это выражение содержит ссылку на столбец изменяемой таблицы, то это рассматривается как ссылка на значение столбца до его изменения.
- Курсор остается позиционированным на текущую строку.
Оператор закрытия курсора в SQL/92 имеет такие же синтаксис и семантику, что и соответствующий оператор языка SQL/89.