Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Статический SQL – разновидность программного SQL, предназначенная для встраивания SQL-операторов в текст программы на языке программирования высокого уровня.




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

Рассмотрим два основных этапа, связанных с работой статического SQL, – компиляция программы и работа (выполнение) программы.

Схема компиляции и сборки программы выглядит следующим образом (рис. 13.1):

· Программа, включающая операторы языка программирования высокого уровня (ЯПВУ) вместе с операторами SQL, подается на вход специального препроцессора, который выделяет из нее части, связанные с SQL.

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

· Сами инструкции SQL препроцессор выделяет в отдельный файл.

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

· Наряду с этими операциями происходит работа с файлом, содержащим SQL-инструкции. В литературе этот модуль часто носит название «модуль запросов к базе данных» (Database Request Module, DBRM) [1]. Обработку этого модуля осуществляет специальная утилита, которая обычно носит название BIND. Для каждой инструкции SQL утилита выполняет следующие действия:

- осуществляет синтаксический анализ запроса (проверяет, является ли запрос корректным);

- проверяет, существуют ли в базе данных те объекты, на которые ссылается запрос;

- выбирает, каким образом осуществлять выполнение запроса – план выполнения запроса;

· Все планы выполнения запросов сохраняются в СУБД для последующего использования.

 

Рис. 13.1. Схема компиляции программы с встроенными инструкциями
статического SQL

 

Схема выполнения программы выглядит следующим образом (рис. 13.2.):

Программа запускается на выполнение обычным образом. При необходимости выполнить запрос программой осуществляется вызов специальной функции СУБД, которая отыскивает уже сформированный ранее план выполнения запроса. СУБД выполняет запрос в соответствии с выбранным планом. Результат выполнения запроса поступает в приложение.

 

 

Рис. 49. Схема выполнения программы с встроенными инструкциями
статического SQL

 

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

Таблица 13.1.

Основные команды статического SQL

 

EXEC SQL Спецификатор, указывающий, что следующая за ним инструкция является инструкцией встроенного SQL
; В языке C – признак окончания инструкции встроенного SQL
DECLARE TABLE Объявляет таблицу, которая потом будет использоваться в инструкциях встроенного SQL
SQLCODE Переменная для обработки ошибок
SQLSTATE Переменная для обработки ошибок
GET DIAGNOSTICS Инструкция для обработки ошибок
WHENEVER SQLERROR SQLWARNING NOT FOUND GOTO CONTINUE Набор совместно используемых инструкций для упрощения обработки ошибок
BEGIN DECLARE SECTION END DECLARE SECTION Инструкции для определения области, в которой будут объявлены переменные, впоследствии используемые в запросах SQL
INTO Используется в операторе SELECT для указания переменной, в которую необходимо поместить результат выполнения запроса
DECLARE CURSOR Курсор – специальный инструмент, предназначенный для обработки результатов запроса, содержащих более одной строки. Работа с курсором похожа на работу с файлами. Данная инструкция служит для создания курсора и связывания его с конкретным запросом  
OPEN Команда, открывающая курсор и побуждающая СУБД начать выполнение запроса. Устанавливает курсор перед первой строкой результата запроса  
FETCH Команда, перемещающая указатель текущей строки (курсор) на следующую строку. В некоторых СУБД и стандарте SQL-92 реализованы разные формы команды FETCH, перемещающие курсор на произвольную строку результатов запроса  
CLOSE Закрывает курсор и прекращает доступ к результатам запроса  
       

Использование описанной выше схемы компиляции/сборки/выпол­нения программы позволяет:

· использовать SQL совместно с программой на языке программирования высокого уровня;

· заранее осуществлять проверку синтаксиса запросов и оптимизацию их выполнения (выбор плана). Понятно, что проверка синтаксиса выполняется быстро, но выбор плана выполнения – весьма трудоемкая процедура. Тот факт, что она выполняется один раз на этапе компиляции, позволяет говорить о существенном уменьшении накладных расходов.

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

 

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

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

История возникновения динамического SQL во многом связана с компанией IBM, внедрившей этот мощный инструмент в свою СУБД DB2. Стандарты SQL, в частности SQL-1, не поддерживали динамического SQL. Лишь в 1992 году в стандарт SQL-2 были включены спецификации динамического SQL. Основной концепцией динамического SQL является следующее утверждение: встроенная инструкция SQL не записывается в исходный текст программы, вместо этого программа формирует текст инструкции во время выполнения в одной из своих областей данных, а затем передает сформированную инструкцию в СУБД для динамического выполнения [1].

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

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

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

Таблица 13.2.

Основные команды динамического SQL

EXECUTE IMMEDIATE Немедленное выполнение инструкции
PREPARE Подготовка инструкции к выполнению
EXECUTE Выполнение подготовленной ранее инст­рукции
DESCRIBE Специальная команда, участвующая при возврате результата выполнения инструкций динамического SQL
DECLARE CURSOR Разновидность инструкции DECLARE CURSOR, применявшейся ранее в рамках статического SQL, содержащая вместо запроса его имя (связанное с запросом при помощи инструкции PREPARE)
OPEN FETCH CLOSE Разновидности инструкций для работы с курсором в динамическом SQL

 

Рассмотрим схему функционирования динамического SQL (рис.13.3). Схема предусматривает одноэтапное и двухэтапное выполнение инструкций.

Одноэтапное выполнение инструкций осуществляется командой EXECUTE IMMEDIATE.

 

Рис. 13.3.. Схема выполнения программы со встроенными инструкциями
динамического SQL с применением одноэтапной схемы

 

Схема выполнения инструкции подразумевает:

· динамическое формирование команды SQL в строковом виде во время работы программы;

· передачу строкового вида инструкции в СУБД при помощи команды EXECUTE IMMEDIATE;

· выполнение инструкции системой управления БД, включающее синтаксический анализ, проверку параметров, оптимизацию (выбор плана) и выполнение этого плана.

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

Двухэтапное выполнение инструкций основано на следующем соображении: скорее всего, команда динамического SQL в таком виде, как она поступает на выполнение, будет выполняться неоднократно. При этом могут меняться какие-то конкретные детали. А это значит, что инструкцию можно параметризовать. Использование параметризованных инструкций позволяет сделать схему выполнения двухэтапной, разделив процесс на «подготовку инструкции» и «выполнение инструкции» (рис. 13.4.).

Рис. 13.4. Схема выполнения программы со встроенными инструкциями
динамического SQL с применением двухэтапной схемы

 

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

На этапе выполнения СУБД подставляет значения параметров (полученные из программы) и использует сформированный ранее план выполнения для достижения результата.

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

 

13.4. Интерфейсы программирования приложений (API).
DB-Library, ODBC, OCI, JDBC

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

Наряду с описанным выше механизмом существует и активно применяется еще один подход, связанный с наличием специальных интерфейсов – API (application programming interface – интерфейс программирования приложений). Эти API представляют собой библиотеки функций, разработанные для обеспечения связи прикладной программы с СУБД посредством выполнения SQL-запросов. Прикладная программа вызывает специальные функции библиотеки для передачи в СУБД SQL-запроса в текстовом виде и для получения результатов выполнения запросов, а также различной служебной информации.

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

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

В данном разделе рассматривается подход, основанный на интерфейсе программирования приложений.

Посмотрим, как работают прикладные программы, использующие различные API. Принципы работы разных библиотек аналогичны. Схема работы приложения совместно с SQL API выглядит следующим образом [1]:

· программа получает доступ к базе данных путем вызова одной или нескольких API-функций, подключающих программу к СУБД и к конкретной базе данных;

· для пересылки инструкций SQL в СУБД программа формирует инструкцию в виде текстовой строки и затем передает эту строку в качестве параметра при вызове API-функции;

· программа вызывает выполнение API-функции для проверки состояния переданной в СУБД инструкции и обработки ошибок;

· если инструкция SQL представляет собой запрос на выборку, то, вызывая API-функции, программа записывает результаты запроса в свои переменные; обычно за один вызов возвращается одна строка или столбец данных;

· свое обращение к базе данных программа заканчивает вызовом API-функции, отключающей ее от СУБД.

Из имеющихся для реализации SQL-запросов интерфейсов API на настоящий момент выделилось несколько библиотек, «стандартных» в том смысле, что они активно применяются множеством разработчиков по всему миру. Данное пособие не является подробным руководством по всем этим библиотекам. Более того, для их профессионального освоения необходимо серьезное изучение соответствующей литературы. В рамках данного курса мы лишь приведем обзор этих библиотек, рассмотрим основные заложенные в них идеи. Подробно эти SQL API описаны, например в [1].

Протокол ODBC

ODBC (Open Database Connectivity – открытый доступ к базам данных) – разработанный компанией Microsoft универсальный интерфейс программирования приложений для доступа к базам данных [1].

Основной целью разработки протокола ODBC считается стандартизация механизмов взаимодействия с различными СУБД. Основная проблема, связанная с разработкой приложений, взаимодействующих с базами данных на основе специальных SQL API, состояла в том, что каждая СУБД имела собственный программный интерфейс доступа, каждый из них имел свои особенности и функционировал не совсем так, как другие. В связи с этим разработка приложения существенно зависела от используемой СУБД. Компания Microsoft сделала важный шаг для решения этой проблемы. Основная идея заключалась в разработке универсального интерфейса на уровне семейства операционных систем Windows, который мог бы быть поддержан в разных СУБД.

Рассмотрим кратко структуру программного обеспечения ODBC [1]:

· интерфейс вызовов функций ODBC: это так называемый верхний уровень ODBC, содержащий API, который и используется непосредственно приложениями. Данный API реализован в виде библиотеки динамической компоновки Dll и входит в состав операционной системы Windows;

· драйверы ODBC: это так называемый нижний уровень ODBC, содержащий набор драйверов для СУБД, поддерживающих протокол ODBC. В рамках технологии для каждой СУБД может быть разработан соответствующий ODBC-драйвер, который будет являться промежуточным звеном между прикладной программой и СУБД, транслируя вызовы функций СУБД в вызовы внутренних специализированных функций СУБД. Таким образом решается проблема стандартизации. Для многих современных СУБД существуют специализированные драйверы ODBC, отдельно устанавливаемые в операционную систему;

· диспетчер драйверов ODBC: данный программный механизм представляет средний уровень ODBC, управляя процессом загрузки необходимых драйверов.

Схема выполнения программы с использованием протокола ODBC для доступа к данным приводится на рис.13.5.

 

 

Рис. 13.5. Схема выполнения программы с использованием протокола ODBC
для доступа к данным

 

Перечень некоторых базисных функций ODBC API приводится в следующей таблице.

Таблица 13.3.

Базисные функции ODBC API

Назначение Функция Описание
Соединение с источником данных     SQLAlocEnv Получает указатель окружения. Одно окружение может служить для создания нескольких соединений.
SQLAlIoc Connect Получает указатель соединения.
SQLConnect Соединяется с указанным драйвером, используя имя источника данных, идентификатор пользователя и пароль.
Подготовка SQL запросов       SQLAllocStmt Размещает указатель выражения.
SQLPrepare Подготавливает SQL выражение для дальнейшего использования.
SQLGet CursorName Возвращает имя, связанное c указателем выражения.
SQLSet CursorName Устанавливает имя курсора.
Выполнение запросов SQLExecute Выполняет заранее подготовленный запрос.
    SQLExec Direct Выполняет запрос.
Выборка результатов и информации о результатах     SQLRow Count Возвращает количество записей, задействованных в операциях вставки, удаления, модификации.
SQLNum ResultCol Возвращает количество колонок в выбранном наборе данных.
SQLDescribe Col Описывает колонку в выбранном наборе данных.
SQLCol Attributes Описывает атрибуты колонки в выбранном наборе данных.
SQLBindCol Присваивает место в памяти для колонки в выбранном наборе данных и указывает ее тип данных.
SQLFetch Возвращает несколько наборов данных.

 

Протокол JDBC

JDBC (Java Database Connectivity) представляет собой API для выполнения SQL-запросов к базам данных из программ, написанных на языке Java [1].

Рассмотрим основные принципы JDBC.

С развитием глобальных сетей, в частности Интернета, и всех сопутствующих технологий стали появляться новые языки, специально предназначенные для работы в новых условиях. Одним из таких языков является язык программирования Java. В настоящее время Интернет-приложения занимают существенное место на рынке, работая в рамках 2-, 3- и многозвенной архитектуры. При этом значение языка Java как средства создания приложений, работающих с базами данных, существенно возрастает. Именно это и явилось одной из основных причин разработки нового программного интерфейса – JDBC. Первоначально интерфейс JDBC был разработан компанией Sun Microsystems, в настоящий момент этот API поддерживается всеми ведущими коммерческими СУБД.

Известно несколько различных версий JDBC. Так, версия 1.0 содержала некоторые средства доступа к данным:

· диспетчер драйверов (для подключения к разным СУБД);

· механизм управления сеансами (для одновременной работы с несколькими СУБД);

· механизм передачи инструкций SQL на выполнение в СУБД;

· механизм работы с курсорами (для передачи результатов выполнения запросов из СУБД в приложение).

Этот перечень определенным образом напоминает аналогичный функциональный аппарат протокола ODBC.

Версия JDBC 2.0 содержит существенные отличия. Так, вследствие увеличения возможностей интерфейса было проведено его идеологическое разделение на две основные части: Core API (основные возможности) и Extensions API (так называемые расширения).

В [1] указаны следующие возможности JDBC:

· Пакетные операции. Программа на Java может осуществить обновление базы данных в пакетном режиме, т.е. одна функция JDBC может добавить в базу данных несколько записей, что положительно сказывается на производительности программ.

· Курсоры с произвольным доступом. В JDBC 2.0 существует средство, позволяющее перемещаться по результатам запроса произвольным образом.

· Обновляемые курсоры. В JDBC 2.0 курсоры, наряду с функцией возврата результата запроса, используются и при обновлении базы данных. Обновления производятся при добавлении или изменении одной из строк в результатах запроса.

· Организация связного пула. Несколько программ на языке Java могут пользоваться совместным доступом к базе данных, уменьшая затраты на подключения к базе данных и отключения от нее. Данный перечень можно продолжить (распределенные транзакции, поддержка JNDI и т.д.).

Версия JDBC 3.0 появилась совсем недавно и содержит такие новации, как объектно-реляционные расширения SQL и улучшенные механизмы обработки транзакций. Архитектура JDBC берет свое начало от ODBC и в существенной части повторяет ее, поэтому схема выполнения программы на Java с использованием протокола JDBC для доступа к данным полностью аналогична схеме на рис. 13.5 (слова ODBC заменяются на слова JDBC). В отличие от ODBC, драйверы JDBC подразделяются на четыре типа. Основные отличия между этими типами связаны с местонахождением API СУБД (на клиентской или серверной СУБД) и способом доступа к базе данных (через собственный API СУБД или через ODBC).

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...