Для подключения к серверу баз данных в SQL/92 предусмотрен оператор CONNECTTO. Следует заметить, что конструкции, предназначенные для управления подключениями и сессиями, относятся к наименее проработанным частям стандарта (хотя на практике они являются необходимыми, поскольку все современные серьезные СУБД выполнены в архитектуре "клиент-сервер"). Для управления подключением служат три оператора (CONNECT, SETCONNECTION и DISCONNECT), которые мы и рассмотрим в этом разделе.
8.1. Установление подключения
С выполнения этого оператора начинается сеанс взаимодействия с указанным сервером баз данных. Оператор описывается следующими синтаксическими правилами:
<connect statement> ::=
CONNECT TO <connection target>
<connection target> ::=
<SQL-server name>
[ AS <connection name> ]
[ USER <user name> ]
| DEFAULT
Пояснения:
8.2. Оператор выбора подключения
Оператор служит для выбора подключения из числа возможных. Синтаксис оператора следующий:
<set connection statement> ::=
SET CONNECTION <connection object>
<connection object> ::=
DEFAULT
|<connection name>
Пояснения:
Оператор DISCONNECT служит для отказа от подключения к SQL-серверу и имеет следующий синтаксис:
<disconnect statement> ::=
DISCONNECT <disconnect object>
<disconnect object> ::=
<connection object>
| ALL
| CURRENT
Пояснения:
Операторы этого набора служат для установки разнообразных умолчаний, действующих в пределах текущей SQL-сессии. Как и операторы управления подключениями, операторы управления сессиями, на наш взгляд, недостаточно тщательно проработаны в стандарте SQL/92.
9.1. Оператор установки имени каталога по умолчанию
Оператор позволяет установить имя каталога по умолчанию для расширения неквалифицированных имен схем, используемых в динамических операторах, подготавливаемых с помощью оператора немедленного выполнения, оператора подготовки, или в прямых операторах SQL. Оператор определяется следующим синтаксическим правилом:
<set catalog statement> ::=
SET CATALOG <value specification>
Пояснения:
9.2. Оператор установки имени схемы по умолчанию
Оператор позволяет установить имя схемы по умолчанию для расширения неквалифицированных имен, используемых в динамических операторах, подготавливаемых с помощью оператора немедленного выполнения, оператора подготовки, или в прямых операторах SQL. Оператор определяется следующим синтаксическим правилом:
<set schema statement> ::=
SET SCHEMA <value specification>
Пояснения:
9.3. Оператор установки имени набора символов по умолчанию
Оператор позволяет установить имя набора символов по умолчанию для применения в идентификаторах и строчных литеральных константах, используемых в динамических операторах, подготавливаемых с помощью оператора немедленного выполнения, оператора подготовки, или в прямых операторах SQL. Оператор определяется следующим синтаксическим правилом:
<set names statement> ::=
SET NAMES <value specification>
Пояснения:
9.4. Оператор установки идентификатора авторизации сессии
Оператор описывается следующим синтаксическим правилом:
<set session authorization identifier statement> ::=
SET SESSION AUTHORIZATION <value specification>
Пояснения:
В стандарте SQL/92 гораздо более полно и точно, чем в SQL/89, описаны разделы языка модулей и встроенного SQL. Однако по смыслу мало что изменилось, а изложение очень громоздко. Поэтому мы ограничимся кратким обсуждением отсутствующего в SQL/89 описания правил встраивания SQL в язык программирования Си (кроме того, в стандарте специфицированы правила связывания с языками Ада, Кобол, Фортран, MUMPS, Паскаль и ПЛ/I).
Синтаксис встраивания для языка Си определяется следующими правилами:
<embedded SQL C program> ::= /* См. синтаксические правила ниже */
<C variable definition> ::=
[ <C storage class> ]
[ <C class modifier> ]
<C variable specification>
<semicolon>
<C variable specification> ::=
<C numeric variable>
| <C character variable>
| <C derived variable>
<C storage class> ::=
auto
| extern
| static
<C class modifier> ::= const | volatile
<C numeric variable> ::=
{ long short float double }
<C host identifier> [ <C initial value> ]
[ { <comma> <C host identifier>
[ <C initial value> ] }... ]
<C character variable> ::=
char [ CHARACTER SET [ IS ] <character set specification> ]
<C host identifier> <C array specification>
[ <C initial value> ]
[ { <comma> <C host identifier>
<C array specification>
[ <C initial value> ] }... ]
<C array specification> ::=
<left bracket> <length> <right bracket>
<C host identifier> ::= /* См. синтаксические правила ниже */
<C derived variable> ::=
<C VARCHAR variable>
| <C bit variable>
<C VARCHAR variable> ::=
VARCHAR [ CHARACTER SET [ IS ]
<character set specification> ]
<C host identifier> <C array specification>
[ <C initial value> ]
[ { <comma> <C host identifier>
<C array specification>
[ <C initial value> ] }... ]
<C bit variable> ::=
BIT <C host identifier>
<C array specification> [ <C initial value> ]
[ { <comma> <C host identifier>
<C array specification>
[ <C initial value> ] }... ]
<C initial value> ::=
<equals operator> <character representation>...
Пояснения:
Описанный в стандарте SQL/89 набор операторов SQL предназначен для встраивания в программу на обычном языке программирования. Поэтому в этом наборе перемешаны операторы "истинного" реляционного языка запросов (например, оператор удаления из таблицы части строк, удовлетворяющих заданному значению) и операторы работы с курсорами, позволяющими обеспечить построчный доступ к таблице-результату запроса.
Понятно, что в диалоговом режиме набор операторов SQL и их синтаксис должен быть несколько другим. Весь вопрос состоит в том, как реализовывать такую диалоговую программу. Правила встраивания SQL/89 в программу на обычном языке программирования предусматривают, что вся информация, касающаяся операторов SQL, известна в статике (за исключением значений переменных, используемых в качестве констант в операторах SQL). Не предусмотрены стандартные средства компиляции с последующим выполнением операторов, которые становятся известными только во время выполнения (например, вводятся с терминала). Поэтому, опираясь только на стандарт SQL/89, невозможно реализовать диалоговый монитор взаимодействия с БД на языке SQL или другую прикладную программу, в которой текст операторов SQL возникает во время выполнения, т.е. фактически так или иначе стандарт необходимо было расширять.
Один из возможных путей расширения состоит в использовании специальной группы операторов, обеспечивающих динамическую компиляцию (во время выполнения прикладной программы) базового подмножества операторов SQL и поддерживающих их корректное выполнение. В стандарте SQL/92 появилась стандартная версия динамического SQL. Полное описание динамического SQL очень громоздко. Тем не менее, мы считаем полезным привести сводку операторов динамического SQL с небольшими пояснениями, чтобы ее можно использовать хотя бы в качестве эталона при сравнении различных реализаций.
11.1. Оператор выделения памяти под дескриптор
<allocate descriptor statement> ::=
LLOCATE DESCRIPTOR <descriptor name> [WITH MAX
<occurrences>]
<occurrences> ::= <simple value specification>
<descriptor name> ::=
(<scope option>] <simple value specification>
scope option> ::= GLOBAL | LOCAL
<simple value specification> ::=
parameter name>
(<embedded variable name> (<literal>
Пояснения:
Дескриптор - это динамически выделяемая часть памяти прикладной программы, служащая для принятия информации о результате или параметрах динамически подготовленного оператора SQL или задания параметров такого оператора. Смысл того, что для выделения памяти используется оператор SQL, а не просто стандартная функция alloc или какая-нибудь другая функция динамического запроса памяти, состоит в том, что прикладная программа не знает структуры дескриптора и даже его адреса. Это позволяет не привязывать SQL к особенностям какой-либо системы программирования или ОС. Весь обмен информацией между собственно прикладной программой и дескрипторами производятся также с помощью специальных операторов SQL (GET и SET, см. ниже).
Второй вопрос: зачем вообще выделять память под дескрипторы динамически? Это нужно потому, что в общем случае прикладная программа, использующая динамический SQL, не знает в статике число одновременно действующих динамических операторов SQL, описание которых может потребоваться. С этим же связано то, что имя дескриптора может задаваться как литеральной строкой символов, так и через строковую переменную включающего языка, т.е. его можно генерировать во время выполнения программы.
В операторе ALLOCATEDESCRIPTOR, помимо прочего, может указываться число описательных элементов, на которое он рассчитан. Если, например, при выделении памяти под дескриптор в разделе WITHMAX указано целое положительное число N, а потом дескриптор ис пользуется для описания M (M>N) элементов (например, M столбцов результата запроса), то это приводит к возникновению исключительной ситуации.
11.2. Оператор освобождения памяти из-под дескриптора
<deallocate descriptor statement> ::=
DEALLOCATE DESCRIPTOR <descriptor name>
Пояснения:
Выполнение этого оператора приводит к освобождению памяти из-под ранее выделенного дескриптора. После этого использование имени дескриптора незаконно в любом операторе, кроме ALLOCATEDESCRIPTOR.
11.3. Оператор получения информации из области дескриптора SQL
<get descriptor statement> ::=
GET DESCRIPTOR <descriptor name>
<get descriptor information>
<get descriptor information> ::=
<get count>
(VALUE <item number>
<get item information>
({<comma> <get item information>}...]
<get count> ::=
<simple target specification 1>
<equals operator> COUNT
<get item information> ::=
<simple target specification 2>
<equals operator> <descriptor item name>
<item number> ::= <simple value specification>
<simple target specification 1> ::= <simple target specification>
<simple target specification 2> ::= <simple target specification>
<descriptor item name> ::=
TYPE (LENGHT (OCTET_LENGHT (RETURNED_LENGHT (
RETURNED_OCTET_LENGHT (PRECISION (SCALE (
DATETIME_INTERVAL_CODE (DATATIME_INTERVAL_PRECISION
( NULLABLE
( INDICATOR (DATA (NAME (UNNAMED (COLLATION_CATALOG (
COLLATION_SCHEMA (COLLATION_NAME (CHARACTER_SET_CATALOG (
CHARACTER_SET_SCHEMA (CHARACTER_SET_NAME
<simple target specification> ::=
<parameter name> (<embedded variable name>
Пояснения:
Оператор GETDESCRIPTOR служит для выборки описательной информации, ранее размещенной в дескрипторе с помощью оператора DESCRIBE. За одно выполнение оператора можно получить либо число заполненных элементов дескриптора (COUNT), либо информацию, содержащуюся в одном из заполненных элементов.
11.4. Оператор установки дескриптора
<set descriptor statement> ::=
SET DESCRIPTOR <descriptor name>
<set descriptor information>
<set descriptor information> ::=
<set count>
(VALUE <item number> <set item information> [{<comma> <set
item information>}...]
<set count> ::= COUNT <equals operator> <simple value specification 1>
<set item information> ::=
<descriptor item name>
<equals operator>
<simple value specification 2>
<simple target specification 1> ::= <simple target specification>
<simple target specification 2> ::=<simple target specification>
<item number> ::= <simple value specification>
Пояснения:
Оператор SETDESCRIPTOR служит для заполнения элементов дескриптора с целью его использования в разделе USING. За одно выполнение оператора можно поместить значение в поле COUNT (число заполненных элементов), либо частично или полностью сформировать один элемент дескриптора.
11.5. Оператор подготовки
<prepare statement> ::=
PREPARE <SQL statement name> FROM <SQL statement variable>
<SQL statement variable> ::=
<simple target specification>
<preparable statement> ::=
<preparable SQL data statement>
| <preparable SQL schema statement>
| <preparable SQL transaction statement>
| <preparable SQL session statement>
| <preparable implementation-defined statement>
<preparable SQL data statement> ::=
<delete statement: searched>
| <dynamic single row select statement>
| <insert statement>
| <dynamic select statement>
| <update statement: searched>
| <preparable dynamic delete statement: positioned>
| <preparable dynamic update statement: positioned>
<preparable SQL schema statement> ::= <SQL schema statement>
<preparable SQL transaction statement> ::= <SQL transaction statement>
<preparable SQL session statement> ::= <SQL session statement>
<dynamic select statement> ::= <cursor specification>
<dynamic simple row select statement> ::= <query specification>
<SQL statement name> ::= <statement name> <extended statement name>
<extended statement name> ::=
[scope option] <simple value specification>
<cursor specification> ::=
<query expression> [<order by clause>] [<updatability clause>]
<updatability clause> ::=
FOR { READ ONLY | UPDATE [ OF <column name list> ] }
<query expression> ::=
<non-join query expression> <joined table>
<query specification> ::=
SELECT [<set quantifier>]
<select list> <table expression>
<set quantifier> ::= DISTINCT | ALL
Пояснения:
Оператор PREPARE вызывает компиляцию и построение плана выполнения заданного в текстовой форме оператора SQL. После успешного выполнения оператора PREPARE с подготовленным оператором связывается указанное (литерально или косвенно) имя этого оператора которое потом может быть использовано в операторах DESCRIBE, EXECUTE, OPENCURSOR, ALLOCATECURSOR и DEALLOCATEPREPARE. Эта связь сохраняется до явного выполнения оператора DEALLOCATEPREPARE.
11.6. Оператор отказа от подготовленного оператора
<deallocate prepared statement> ::= D
EALLOCATE PREPARE <SQL statement name>
Пояснения:
Выполнение этого оператора приводит к тому, что ранее подготовленный оператор SQL, связанный с указанным именем оператора, ликвидируется, и соответственно, имя оператора становится неопределенным. Если подготовленный оператор являлся оператором выборки и к моменту выполнения оператора DEALLOCATE существовал открытый курсор, связанный с именем подготовленного оператора, то оператор DEALLOCATE возвращает код ошибки. Если же для подготовленного оператора выборки существовал неоткрытый курсор, образованный с помощью оператора ALLOCATECURSOR, то этот курсор ликвидируется. Если такой курсор объявлялся оператором DECLARECURSOR, то такой курсор переходит в состояние, существовавшее до выполнения оператора PREPARE. Если с курсором был связан подготовленный оператор (динамический DELETE или UPDATE), то для этих операторов выполняется неявный оператор DEALLOCATE.
11.7. Оператор запроса описания подготовленного оператора
<describe statement> ::=
<describe input statement> <describe output statement>
<describe input statement> ::=
DESCRIBE INPUT <SQL statement name> <using descriptor>
<describe output statement> ::=
DESCRIBE [OUTPUT] <SQL statement name> <using descriptor>
<using clause> ::= <using arguments> <using descriptor>
<using arguments> ::=
{ USING | INTO } <argument> [{<comma> <argument>}...]
<argument> ::= <target specification>
<using descriptor> ::=
{ USING | INTO } SQL DESCRIPTOR <descriptor name>
<target specification> ::=
<parameter specification>
| <variable specification>
<parameter specification> ::=
<parameter name> [<indicator parameter>]
<indicator parameter> ::= [INDICATOR] <parameter name>
<variable specification> ::=
<embedded variable name> [<indicator variable>]
<indicator variable> ::=
[INDICATOR] <embedded variable name>
Пояснения:
При выполнении оператора DESCRIBE происходит заполнение указанного в операторе дескриптора информацией, описывающей либо результат ранее подготовленного оператора SQL (если это оператор выборки), либо количество и типы параметров подготовленного оператора. В <usingdescriptor> здесь полагается писать USINGSQLDESCRIPTOR.
11.8. Оператор выполнения подготовленного оператора
<execute statement> ::=
EXECUTE <SQL statement name> (<result using clause>]
(<parameter using clause>]
<result using clause> ::= <using clause>
<parameter using clause> ::= <using clause>
Пояснения:
Оператор EXECUTE может быть применен к любому ранее подготовленному оператору SQL, кроме <dynamicselectstatement>. Если это оператор <dynamicsinglerowselectstatement>, то оператор EXECUTE должен содержать раздел <resultusingclass> с ключевым словом INTO. В любом случае число фактических параметров, задаваемых через разделы using, должно соответствовать числу формальных параметров, определенных в подготовленном операторе SQL.
11.9. Оператор подготовки с немедленным выполнением
<execute immediate statement> ::=
EXECUTE IMMEDIATE <SQL statement variable>
Пояснения:
При выполнении оператора EXECUTEIMMEDIATE производится подготовка и немедленное выполнение заданного в текстовой форме оператора SQL. При этом подготавливаемый оператор не должен быть оператором выборки, не должен содержать формальных параметров и комментариев.
11.10. Оператор объявления курсора над динамически подготовленным оператором выборки
<dynamic declare cursor> ::=
DECLARE <cursor name> [INSENSITIVE] [SCROLL] CURSOR FOR
<statement name>
Пояснения:
Как определяется в стандарте SQL/92, для всех операторов DECLARECURSOR, курсоры фактически создаются при начале транзакции и уничтожаются при ее завершении. Заметим, что в этом операторе <cursorname> и <statementname> - прямо заданные идентификаторы.
11.11. Оператор определения курсора над динамически подготовленным оператором выборки
<allocate cursor statement> ::=
ALLOCATE <extended cursor name> [INSENSITIVE] [SCROLL]
CURSOR
FOR <extended statement name>
<extended cursor name> ::=
(<scope option>] <simple value specification>
Пояснения:
Курсоры, определяемые с помощью оператора ALLOCATECURSOR, фактически создаются при выполнении такого оператора и уничтожаются при выполнении оператора DEALLOCATEPREPARE или при конце транзакции. В этом операторе имена курсора и подготовленного оператора SQL могут задаваться не только в литеральной форме, но и через переменные.
Раздел <scopeoption> относится к области видимости имен: в пределах текущего модуля или в пределах текущей сессии.
11.12. Оператор открытия курсора, связанного с динамически подготовленным оператором выборки
<dynamic open statement> ::=
OPEN <dynamic cursor name> [<using clause>]
Пояснения:
По сути, оператор открытия курсора, связанного с динамически подготовленным оператором SQL, отличается от статического случая только возможным наличием раздела using, в котором задаются фактические параметры оператора выборки. Кроме того, имя курсора может задаваться через переменную.
11.13. Оператор чтения строки по курсору, связанному с динамически подготовленным оператором выборки
<dynamic fetch statement> ::= FETCH [[<fetch orientation>] FROM]
<dynamic cursor name> <using clause>
Пояснения:
По сути, оператор чтения по курсору, связанному с динамически подготовленным оператором SQL, отличается от статического случая только возможным наличием раздела using, в котором задается размещение значений текущей строки результирующей таблицы. Кроме того, имя курсора может задаваться через переменную.
11.14. Оператор закрытия курсора, связанного с динамически подготовленным оператором выборки
<dynamic close statement> ::= C
LOSE <dynamic cursor name>
Пояснения:
По сути, оператор закрытия курсора, связанного с динамически подготовленным оператором SQL, отличается от статического случая только тем, что имя курсора может задаваться через переменную.
11.15. Оператор позиционного удаления по курсору, связанному с динамически подготовленным оператором выборки
<dynamic delete statement: positioned> ::=
DELETE FROM <table name> WHERE CURRENT OF <dynamic cursor name>
Пояснения:
По сути, оператор позиционного удаления по курсору, связанному с динамически подготовленным оператором SQL, отличается от статического случая только тем, что имя курсора может задаваться через переменную.
11.16. Оператор позиционной модификации по курсору, связанному с динамически подготовленным оператором выборки
<dynamic update statement: positioned> ::=
UPDATE <table name> SET <set clause> [{<comma> <set clause>}...] WHERE CURRENT OF <dynamic cursor name>
Пояснения:
По сути, оператор позиционной модификации по курсору, связанному с динамически подготовленным оператором SQL, отличается от статического случая только тем, что имя курсора может задаваться через переменную.
11.17. Подготавливаемый оператор позиционного удаления
<preparable dynamic delete statement: positioned> ::=
DELETE [FROM <table name>] WHERE CURRENT OF <cursor name>
Пояснения:
Основной резон появления этого и следующего операторов состоит в том, что сочетание курсора, определенного на динамически подготовленном операторе выборки, и статически задаваемых операторов удаления и модификации по этому курсору, выглядит довольно нелепо. Поэтому в стандарте появились динамически подготавливаемые позиционные операторы удаления и вставки. Естественно, что выполняться они должны с помощью оператора EXECUTE.
11.18. Подготавливаемый оператор позиционной модификации
<preparable dynamic update statement: positioned> ::=
UPDATE [<table name>] SET <set clause> [{<comma> <set
clause>}...] WHERE CURRENT OF <cursor name>
Пояснения: см. предыдущий пункт.
Продолжение в статье Язык баз данных SQL/92 часть 6