Введение в стандарты языка баз данных SQL

Манипулирование данными


Как и в языке 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

Пояснения:

  • Пусть T обозначает таблицу, получаемую при вычислении выражения запроса, которое входит в спецификацию курсора.
  • Если раздел обновляемости курсора (updatabilityclause) не специфицирован, то

      (a) если спецификация курсора содержит ключевые слова INSENSITIVE, SCROLL или ORDERBY или если T является только читаемой таблицей, то по умолчанию предполагается задание раздела обновляемости с ключевым словом READONLY;

      (b) в противном случае неявно предполагается указание раздела обновляемости с ключевым словом FORUPDATE и без списка имен столбцов (т.е. предполагается, что изменения могут относиться ко всем столбцам T).




  • Если T является обновляемой таблицей, то пусть TU обозначает базовую таблицу, на которой в конечном счете базируется вычисление выражения запроса.
  • Если в спецификации сортировки содержится раздел задания порядка сортировки (collateclause), то столбец сортировки должен иметь тип данных символьных строк.
  • Если специфицирован раздел обновляемости с FORUPDATE и явным или неявным указанием списка имен столбцов, то таблица T должна быть обновляемой, и спецификация курсора не должна содержать ключевого слова INSENSITIVE.
  • Если раздел обновляемости с FORUPDATE без списка имен столбцов специфицирован или неявно подразумевается, то по умолчанию предполагается наличие списка имен столбцов, включающего имена каждого столбца TU.
  • Если специфицирован раздел обновляемости с FORUPDATE со списком имен столбцов, каждое имя в этом списке должно быть именем столбца TU.
  • Если T является обновляемой таблицей, то для каждой строки T, существует в точности одна соответствующая строка TU, из которой порождена эта строка T.
  • Спецификация INSENSITIVE означает, что после открытия курсора изменения, производимые в той же транзакции над строками таблицы TU, не должны оказывать влияния на состояние таблицы T; спецификация SCROLL означает, что после открытия курсора разрешается произвольное изменение его позиции.


  • Оператор открытия курсора определяется следующим синтаксическим правилом:

    <open statement> ::= OPEN <cursor name>



    Пояснения:

  • Пусть S обозначает спецификацию открываемого курсора.
  • При выполнении оператора открытия курсора выполняются следующие действия:


      (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> }... ]

    Пояснения:

  • Если отсутствует указание ориентации чтения (fetchorientation), неявно предполагается наличие ориентации NEXT.
  • Если неявная или явная ориентация отличается от NEXT, то в объявлении курсора должна присутствовать спецификация SCROLL.
  • Если в указании ориентации чтения присутствует спецификация простого значения, то тип данных этого значения должен быть типом точных чисел с масштабом 0.
  • Определим J следующим образом:


      (a) если в указании ориентации чтения содержится спецификация простого значения, то пусть J равняется этому значению;

      (b) если в указании ориентации присутствует NEXT или FIRST, то пусть J равняется +1;

      (c) если в указании ориентации присутствует PRIOR или LAST, то пусть J равняется -1.



  • Пусть Tt обозначает таблицу той же степени, что таблица T, соответствующая результату спецификации курсора; тогда


      (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 будет пустой таблицей.



  • Пусть N обозначает число строк в Tt. Если J положительно, то пусть K равняется J. Если J отрицательно, то пусть K равняется N+J+1. Если J равно нулю, и специфицировано ABSOLUTE, то пусть K равняется нулю; если же J равно нулю, и специфицировано RELATIVE, то пусть K равняется 1.
  • Операция чтения выполняется следующим образом:


      (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 приводятся некоторые уточнения поведения оператора:


    1. Если текущая транзакция имеет режим доступа "только чтение" и таблица, из которой удаляется кортеж не является временной, то возбуждается исключительное условие.
    2. Текущая строка помечается для удаления.
    3. Если оказалось, что помечаемая строка уже помечена для удаления оператором поискового удаления или оператором позиционного удаления, связанным с другим курсором, или помечена для обновления оператором поисковой модификации или оператором позиционной модификации, связанным с другим курсором, то в условии завершения текущего оператора сообщается соответствующее предупреждение.
    4. Строка, помеченная для удаления, реально удаляется в конце выполнения оператора позиционного удаления до проверки каких-либо ограничений целостности.
    5. Если удаляется последний кортеж, то курсор устанавливается в позицию после последней строки; в противном случае курсор устанавливается в позицию перед следующей строкой.


    Оператор позиционной модификации также мало отличается от соответствующего оператора 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:


    1. Изменения, производимые с использованием упорядоченного курсора, не должны затрагивать столбцы сортировки;
    2. Если текущая транзакция выполняется в режиме только чтения, возбуждается исключительное условие.
    3. Будем называть объектной строкой ту строку, из которой порождена текущая строка курсора.
    4. Если оказалось, что к моменту выполнения операции позиционного обновления объектная строка уже помечена для удаления некоторым поисковым оператором удаления или позиционным оператором удаления, связанным с другим курсором, или если она помечена для обновления некоторым поисковым оператором обновления или поисковым оператором обновления, связанным с другим курсором, генерируется условие завершения с соответствующим предупреждением.
    5. Ключевое слово DEFAULT в разделе SET означает, что в соответствующий столбец обновляемой таблицы должно быть помещено его значение по умолчанию.
    6. Выражение, вырабатывающее значение, в разделе SET вычисляется до обновления объектной строки; если это выражение содержит ссылку на столбец изменяемой таблицы, то это рассматривается как ссылка на значение столбца до его изменения.
    7. Курсор остается позиционированным на текущую строку.


    Оператор закрытия курсора в SQL/92 имеет такие же синтаксис и семантику, что и соответствующий оператор языка SQL/89.


    Содержание раздела