16.5. Динамический SQL в Oracle V.6

Описанный в стандарте SQL/89 набор операторов SQL предназначен для встраивания в программу на обычном языке программирования. Поэтому в этом наборе перемешаны операторы "истинного" реляционного языка запросов (например, оператор удаления из таблицы части строк, удовлетворяющих заданному значению) и операторы работы с курсорами, позволяющими обеспечить построчный доступ к таблице-результату запроса.

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

Один из возможных путей расширения состоит в использовании специальной группы операторов, обеспечивающих динамическую компиляцию (во время выполнения прикладной программы) базового подмножества операторов SQL и поддерживающих их корректное выполнение. Некоторый набор таких операторов входил в диалект SQL, реализованный в System R, несколько отличный набор входит в реализацию Oracle V.6 и наконец, в новом стандарте SQL/92 появилась стандартная версия динамического SQL.

Поскольку в СУБД Oracle средства динамического SQL реализованы уже сравнительно давно, имеет смысл рассмотреть сначала их, чтобы иметь основу для сравнения с SQL/92.

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

16.5.1. Оператор подготовки

Оператор PREPARE имеет синтаксис:

<prepare-statement> ::=
   PREPARE <statement-name> FROM <host-string-variable>
<statement-name> ::= <name>

Во время выполнения оператора PREPARE символьная строка, содержащаяся в host-string-variable, передается компилятору SQL, который обрабатывает ее почти таким же образом, как если бы получил в статике. Построенный при выполнении оператора PREPARE код остается действующим до конца транзакции или до повторного выполнения данного оператора PREPARE в пределах этой же транзакции.

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

16.5.2. Оператор получения описания подготовленного оператора

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

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

16.5.3. Оператор выполнения подготовленного оператора

Оператор EXECUTE служит для выполнения ранее подготовленного оператора SQL типа 'N' (не требующего применения курсора) или для совмещенной подготовки и выполнения такого оператора. Синтаксис оператора EXECUTE:

<execute-statement> ::=
   EXECUTE
 {<statement-name> [USING <host-vars-list>]
 ( IMMEDIATE <host-string-variable> }

Для выполнения подготовленного оператора служит первый вариант оператора EXECUTE. В этом случае <statement-name> должен задавать имя, употреблявшееся ранее в операторе PREPARE. Если в подготовленном операторе присутствуют формальные параметры, то в операторе EXECUTE должен задаваться список фактических параметров <host-vars-list>. Число и типы фактических параметров должны соответствовать числу и типам формальных параметров подготовленного оператора.

Второй вариант оператора EXECUTE предназначен в Oracle для совмещенной подготовки и выполнения оператора SQL типа 'N'. В этом случае параметром оператора EXECUTE является строка, которая должна содержать текст оператора SQL (эту строку разрешается также задавать литерально). Запрещается использование в этом операторе переменных включающей программы (формальных параметров).

16.5.4. Работа с динамическими операторами SQL через курсоры

Для использования таких операторов используется расширение механизма курсоров стандарта SQL. Во-первых, при определении курсора можно указывать не только литеральную спецификацию курсора, но и имя оператора, вводимое с помощью оператора PREPARE (в этом случае оператор PREPARE должен текстуально находиться выше оператора DECLARE). Тем самым полный синтаксис оператора DECLARE становится следующим:

<declare cursor> ::=
   DECLARE <cursor name> CURSOR
   FOR { <cursor specification> | <statement-name> }

Далее, поскольку для такого курсора в статике неизвестна информация о входных и выходных переменных включающей программы, то используется другая форма операторов OPEN и FETCH.

Полный синтаксис этих операторов становится следующим:

<open statement> ::=
   OPEN <cursor name>
  [USING { <host-vars-list> | DESCRIPTOR <descr-name> }]
<fetch statement> ::=
   FETCH <cursor name>
 { INTO <fetch target list>
 ( USING <host-vars-list>
 ( USING DESCRIPTOR <descr-name> }

Как видно, предлагается два способа задания фактических входных и выходных параметров: прямое с указанием в операторах OPEN и/или FETCH списков имен переменных включающей программы и косвенное, когда число параметров и их адреса сообщаются через дополнительную структуру-дескриптор.

Первый способ предлагается использовать для работы с операторами выборки, для которых фиксирован набор формальных входных и выходных параметров. Точнее говоря, что касается выходных параметров, должны быть фиксированы число и типы элементов списка выборки.

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

Предыдущая глава || Оглавление || Следующая глава


Copyright © CIT