Теория баз данных

       

Динамический SQL


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

Сформированный таким образом текст SQL-оператора поступает в СУБД, которая должна его скомпилировать и выполнить «на лету», в процессе работы приложения. Если мы снова вернемся к этапам выполнения SQL-операторов, то первые четыре действия, связанные с синтаксическим анализом, семантическим анализом, построением и оптимизацией плана выполнения запроса, выполняются на этапе компиляции. В момент исполнения этого оператора СУБД просто изымает хранимый план выполнения этого оператора и исполняет его.

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

На рис. 12.5 представлены условные временные диаграммы выполнения SQL-операторов в статическом SQL и в динамическом SQL. Конечно, динамический SQL гораздо менее эффективен в смысле производительности, по сравнению со статическим SQL. Поэтому во всех случаях, когда это возможно, необходимо избегать динамического SQL. Но бывают случаи, когда отказ от динам'ического SQL серьезно усложняет приложение. Например, в случае с поиском по произвольному множеству параметров невозможно заранее предусмотреть все возможные комбинации запросов, даже если возможных параметров два десятка. А если их больше, то именно динамический SQL становится наиболее удобным методом решения необъятной проблемы.

Наиболее простой формой динамического SQL является оператор непосредственного выполнения EXECUTE IMMEDIATE. Этот оператор имеет следующий синтаксис:


EXECUTE IMMEDIATE <имя_базовой переменной>

Базовая переменная содержит текст SQL оператора.

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

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

Этот этан выполняется оператором PREPARE, синтаксис которого приведен ниже:

PREPARE <имя_оператора> FROM <имя_базовой переменной>

<имя_оператора> - это идентификатор базового языка.

Далее на втором этапе этот определенный на первом этапе оператор может быть выполнен операцией EXECUTE, которая имеет синтаксис:

EXECUTE <имя__оператора> USING {<список базовых переменных> |



DESCRIPTOR <имя_дескриптора>}

Здесь DESCRIPTOR — это некоторая структура, которая описывается на клиенте, но создается и управляется сервером. Дескриптор представляет совокупность элементов данных, принадлежащих СУБД. Программное обеспечение СУБД должно содержать и поддерживать набор операций над дескрипторами. Эта структура была введена в стандарт SQL2 для типизации динамического SQL.

В стандарт SQ.L2 введены следующие операции над дескрипторами:

  • ALLOCATE DESCRIPTOR <имя_дескриптора> [WITH MAX <число_элементов>] — оператор связывает имя дескриптора с числом его базовых элементов и обеспечивает выделение памяти под данный дескриптор.

  • DEALLOCATE DESCRIPTOR <имя_дескриптора> — оператор освобождает разделяемую память СУБД, занятую хранением описания данного дескриптора. После выполнения данного оператора невозможно обратиться к дескриптору ни с одной операцией.



  • SET DESCRIPTOR {COUNT = <имя_базовой переменной> VALUE <номер элемента> {<имя_ элемента>= <имя_базовой перененной>[...]}} — оператор занесения в дескриптор описания передаваемых параметров. Описания перелаются СУБД, которая их обрабатывает, внося соответствующие изменения в область данных, отведенную под дескриптор.

  • GET DESCRIPTOR { <имя_базовой переменной> = COUNT | VALUE <номер элемента> {<имя_базовой переменной>=<имя_эленента>[...]} — оператор получения информации из дескрипторов после выполнения запроса.

  • DESCRIBE [ INPUT | OUTPUT] <имя_оператора> USING SQL DESCRIPTOR <имя_дескрипто-pa> — оператор, позволяющий получить описания таблиц результатов запросов (DESCRIBE OUTPUT) или входных параметров (DESCRIBE INPUT).

  • OPEN <имя_курсора> [USING <список базовых переменных> | USING SQL DESCRIPTOR <имя_дескриптора>] — динамический оператор открытия курсора.

  • FETCH <имя_курсора> [USING <список базовых переменных> | USING SQL DESCRIPTOR <имя_дескриптора>] — динамический оператор перемещения но курсору.

  • DEALLOCATE PREPARE <имя_оператора> — оператор уничтожает ранее подготовленный план выполнения оператора SQL и освобождает разделяемую память СУБД, связанную с храпением этого плана. Этот оператор имеет смысл применять, если вы не будете больше применять команду выполнения к подготовленному ранее оператору SQL.

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


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