Banners System

СИСТЕМЫ УПРАВЛЕНИЯ БАЗАМИ ДАННЫХ #05-06/96
<< ПРЕДЫДУЩАЯ СТАТЬЯ ] [ ОГЛАВЛЕНИЕ ] [ СЛЕДУЮЩАЯ СТАТЬЯ >>

Новый стандарт хранимых процедур в языке SQL1)

Э. Айзенберг

1. Введение
2. Многооператорные процедуры
3. Хранимые подпрограммы
4. Хранимые модули
5. Внешние подпрограммы
6. Заключение
7. Литература

1. Введение

SQL-92/PSM (Persistent Stored Modules - долгоживущие хранимые модули) [1] - это второе принятое дополнение к стандарту ANSI/ISO SQL-92 [2]. Это дополнение расширяет функциональные возможности SQL-92 в следующих трех широких направлениях.

  • Многооператорные процедуры (Multi-statement Procedures): группы операторов SQL могут выполняться совместно; предоставляются в распоряжение операторы управления логикой исполнения, локальные переменные и средства обработки условий.
  • Хранимые подпрограммы и модули (Stored routines and modules): процедуры, функции и модули могут храниться в SQL-сервере.
  • Внешние подпрограммы (External routines): функции и процедуры, написанные на включающих языках третьего поколения (3GL), могут вызываться из операторов SQL.
  • При проведении этой работы были использованы концепции и синтаксис современных языков программирования с блочной структурой, модифицированных необходимым образом для среды языка SQL.

    Во время подготовки этой статьи только что успешно завершилась редакционная сессия ISO, которая явилась завершающим шагом в принятии SQL-92/PSM как международного стандарта. Статья может содержать некоторые упущения или неточности, поскольку окончательная версия стандарта еще недоступна.

    Всюду в ней для ссылки на SQL-92/PSM используется сокращение PSM-96. Отметим, что во включенных в статью фрагментах кода не предусматривается обработка ошибок, и они необязательно решают какую-либо полезную задачу.

    2. Многооператорные процедуры

    Стандарт SQL-92 предусматривает возможность исполнения отдельных операторов SQL в программе, написанной на включающем языке, например C или КОБОЛЕ. Например, программа, которая вставляет некоторого студента в список и далее регистрирует его, может быть написана следующим образом:

    void main { 
            EXEC SQL INSERT INTO студенты 
                    VALUES {10610, 'Джон Портер', ...};
            /* проверить SQLSTATE на ошибки */ 
            EXEC SQL INSERT INTO 
                            регистрационные_записи 
                    VALUES {10610, 'CS101', ...} ; 
            /* проверить SQLSTATE на ошибки */ 
            }

    После исполнения каждого из операторов INSERT возвращается значение SQLSTATE, которое показывает, успешно или неудачно завершилось его исполнение.

    2.1. Составные операторы

    Составной оператор (BEGIN/END) позволяет сгруппировать вместе включенные в него операторы.

    void main { 
            EXEC SQL 
                    BEGIN 
                            INSERT INTO студенты 
                                    VALUES {10610, 'Джонс', ...};
                            INSERT INTO регистрационные_записи
                                    VALUES {10610, 'CS101', ...};
                    END;
            /* проверить SQLSTATE на ошибки */
            }

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

    2.1.1. Атомарность

    В приведенном выше примере может оказаться, что первый оператор вставки завершается успешно, а второй оператор вставки - неудачно, вследствие нарушения ограничения уникальности. Любая частично исполненная вторым оператором вставки работа будет аннулирована, поскольку в SQL все операторы DML2) рассматриваются как атомарные. Работа первого оператора не будет при этом аннулироваться, поскольку составной оператор не является атомарным оператором (точно так же, как и другие операторы управления логикой исполнения, которые будут кратко обсуждаться далее). В этой связи PSM-96 предусматривает вторую форму составного оператора, при которой он является атомарным.

    BEGIN ATOMIC 
            INSERT INTO студенты 
                    VALUES {10610, 'Джонс', ...};
            INSERT INTO регистрационные_записи
                    VALUES {10610, 'CS101', ...};
    END;

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

    Это - единственный оператор, где автор может сам выбирать атомарное или не атомарное поведение. Атомарный составной оператор может "обертывать" (wrap) любой другой управляющий оператор, тело подпрограммы или вызов подпрограммы для того, чтобы сделать их исполнение атомарным.

    2.1.2. Переменные

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

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

    BEGIN 
            DECLARE начало DATE ;
            SELECT дата_начала 
            INTO начало 
            FROM служащие 
            WHERE ...; 
    END;

    2.1.3. Курсоры

    Составные операторы допускают объявление курсоров. Как и в случае с переменными, эти локальные курсоры создаются, когда начинается исполнение составного оператора, и уничтожаются, когда его исполнение завершается.

    BEGIN 
            DECLARE курсор1 CURSOR FOR 
                    SELECT имя 
                    FROM студенты;
            OPEN курсор1; 
            FETCH курсор1 INTO коллекция_имен;
            CLOSE курсор1; 
    END;

    2.1.4. Указатели условий

    Каждый составной оператор может специфицировать множество указателей условий, и в каждой такой спецификации должно быть задано:

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

    2.1.4.1. Условия

    Значения SQLSTATE показывают, успешно или неудачно завершаются операторы SQL. Значение SQLSTATE содержит двухлитерное значение класса и трехлитерное значение подкласса.

    Класс
    Описание
    "00"
    Успешное завершение
    "01"
    Предупреждение
    "02"
    Не найдено
    "другой"
    Исключительная ситуация

    Имя условия может объявляться в составном операторе и по выбору пользователя может ассоциироваться со значением SQLSTATE.

    BEGIN 
            DECLARE зарегистрированный_студент
                    CONDITION;
            DECLARE нарушение_целостности 
                    CONDITION FOR SQLSTATE VALUE '23000';
            ... 
    END

    К числу условий, которые могут специфицироваться в указателе условия, относятся:

    Условие
    Описание
    SQLSTATE VALUE
    'xxyyy'
    Конкретное значение
    SQLSTATE
    Название условия
    Объявленное условие
    SQLEXCEPTION
    Класс SQLSTATE, иной чем '00', '01' или '02'
    SQLWARNING
    Класс SQLSTATE '01'
    NOT FOUND
    Класс SQLSTATE '02'

    2.1.4.2. Действие

    Действие, которое будет предпринимать указатель, специфицируется оператором SQL, и этот оператор может быть составным.

    2.1.4.3. Результат

    Результатом, который имеет указатель условия, если действие выполнено успешно, является одно из следующих:

    CONTINUE (продолжать)
    Продолжить исполнение непосредственно после оператора, при исполнении которого был вызван данный указатель
    EXIT (выход)
    Продолжить исполнение после составного оператора, который содержит данный указатель
    UNDO
    (аннулировать)
    Аннулируовать работу пре дыдущих операторов в со-ставном операторе и продолжить исполнение после того оператора, который содержит данный указатель

    Указатель UNDO может быть специфицирован только в составном операторе, для которого специфицировано также ATOMIC.

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

    BEGIN 
            DECLARE i INTEGER DEFAULT 1;
            DECLARE успех INTEGER DEFAULT 0;
            WHILE успех = 0 DO
                    BEGIN ATOMIC 
                            DECLARE неудачная_сериализация 
                                    CONDITION FOR SQLSTATE VALUE 
                                            '40001'; 
                            DECLARE UNDO HANDLER 
                                    FOR неудачная_сериализация 
                                    BEGIN 
                                            IF i > 3 THEN RESIGNAL;
                                            SET i = i + 1;
                                    END;
                            INSERT INTO студенты ...;
                            INSERT INTO 
                                    жилищное_строительство ...; 
                            SET успех = 1;
                    END; 
            END WHILE ; 
    END;

    Если ошибка сериализации имеет место во время исполнения одного из операторов вставки INSERT, то исполняется указатель условия. Аннулируется всякая работа, выполненная при вставках. Если i меньше или равно 3, то указатель условия увеличивает i, и исполнение продолжается после атомарного составного оператора. Оператор WHILE (пока) будет вызывать повторение вставок. Если i больше, чем 3, то вновь сигнализируется исключительная ситуация. Это означает, что исполнение всего этого составного оператора заканчивается, и некоторый указатель условия вне области этого примера будет обрабатывать такую исключительную ситуацию.

    2.1.4.4. Необрабатываемые условия

    Если указатель для обработки условия завершения или исключительной ситуации, которая имела место в некоторой лексической области, отсутствует, то такое условие называется необрабатываемым.

    Необрабатываемое условие завершения, например, такое как предупреждение, будет продолжать исполнение после того оператора, который вызвал условие завершения. Необрабатываемое условие исключительной ситуации вызовет повторную сигнализацию условия исключительной ситуации. Если это условие опять окажется необрабатываемым в текущем дереве исполнения, то это условие исключительной ситуации окончательно возвращается клиентскому приложению. Обработка условий более подробно обсуждалась в предыдущем томе SIGMOD Record [3].

    2.2. Операторы управления логикой исполнения

    PSM-96 предоставляет операторы управления логикой исполнения, которые можно видеть в современных языках программирования.

    Оператор ASSIGNMENT (присваивание) присваивает значение переменной или параметру.

    Оператор IF (если) исполняет список операторов, заданных во фразе THEN (тогда), если в результате вычисления условия получено TRUE ("истина"), а не FALSE ("ложь") или UNKNOWN ("неизвестно").

    IF штат_студента IN ('MA', 'NH') 
            THEN оператор; оператор; ... 
    ELSIF страна_студента = 'Соединенные Штаты' 
            THEN оператор; оператор; ... 
    ELSE оператор; оператор; ... 
    ENDIF;

    Оператор CASE (случай) имеет две разновидности. В первой из них единственное значение, указанное в начале оператора CASE, проверяется на равенство со значением, заданным для каждой ветви этого оператора.

    CASE штат_студента 
    WHEN 'MA' THEN оператор; оператор; ...
    WHEN 'NH' THEN оператор; оператор; ...
    ELSE оператор; оператор; ... 
    END CASE;

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

    CASE 
    WHEN штат_студента IN ('MA', 'NH') 
            THEN оператор; оператор; ... 
    WHEN страна_студента = 'Соединенные Штаты' 
            THEN оператор; оператор; ... 
    ELSE оператор; оператор; ... 
    END CASE;

    Если ни для одной из ветвей оператора CASE заданные условия не имеют значения "истина", то оператор CASE порождает исключительную ситуацию.

    PSM-96 предусматривает несколько типов оператора цикла:

    LOOP (цикл)
    Не выполняет никакой проверки на завершение
    WHILE (пока)
    Осуществляет проверку на завершение перед исполнением его операторов
    REPEAT (повторить)
    Осуществляет проверку на завершение после исполнения его операторов

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

    BEGIN DECLARE s CHAR VARYING (30);
            SET s = ( SELECT имя 
                    FROM студенты 
                    WHERE ...) || ' ';
            WHILE LENGTH (s) < 30
                    SET s = s || '.';
            END WHILE; 
    END;

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

    2.2.1. Оператор FOR

    Оператор FOR (для) отличается от такого оператора, используемого в языках программирования третьего поколения (3GL). Оператор FOR неявным образом открывает курсор, осуществляет выборку строк курсора и исполняет тело оператора FOR по одному разу для каждой строки, а затем закрывает курсор.

    BEGIN 
            DECLARE s CHAR VARYING (300) 
                    DEFAULT ' ';
            FOR x AS SELECT * 
                    FROM регистрационные_записи e 
                    WHERE e.студент = s_id 
            DO 
                    IF s <> ' ' 
                    THEN SET s = s || ', ';
                    END IF;
                    SET s = s || курс;
            END FOR; 
            ... 
    END;

    Пользователь имеет возможность специфицировать в операторе FOR имя курсора. Это имя курсора может использоваться для обновления или удаления строки курсора, но не для того, чтобы закрыть курсор или изменить позицию курсора.

    3. Хранимые подпрограммы

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

    EXEC SQL 
            SELECT имя 
            INTO :имя INDICATOR :nn_ind 
            FROM студенты 
            WHERE ... ;
    Эти операторы эквивалентны SQL-процедуре в клиентском модуле и вызову процедуры
     из включающего языка.
    {       /* Вызов в C программе */
    ... 
    имя_студента 
            (&SQLSTATE, имя, &nn_ind); 
    }
    MODULE ...      /* Клиентский SQL-модуль */
    PROCEDURE имя_студента 
            (SQLSTATE, nnparm, nnparm_ind);
            SELECT имя 
            INTO :nnparm INDICATOR :nnparm_ind 
            FROM студенты 
            WHERE ...;

    3.1. Хранимые процедуры

    PSM-96 позволяет хранить процедуры в базе данных как объекты схемы точно так же, как хранятся таблицы. Язык SQL дополнен новыми операторами DDL3), которые позволяют добавлять и удалять эти объекты.

    В клиентских SQL-процедурах могут использоваться следующие виды параметров: input (входной), output (выходной), input и output (входной и выходной) либо none (без параметров). Заключение о виде параметра делается на основе характера использования этого параметра в теле процедуры. В PSM-96 вид параметра может быть явным образом специфицирован автором данной процедуры.

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

    EXEC SQL 
            CREATE PROCEDURE удалить_курс 
                     (IN ид_студента CHAR (6), 
                            IN ид_курса CHAR (6), 
                            OUT строка_расшифровки CHAR (80))
                    BEGIN ATOMIC 
                            DELETE 
                            FROM регистрационные_записи 
                            WHERE студент = ид_студента 
                                    AND курс = ид_курса;
                    INSERT INTO расшифровка VALUES 
                            ( ид_студента, 
                                    CURRENT_DATE, 
                                    ид_курса || ' удален' );
                    SET строка_расшифровки =
                                    ид_курса || ' удален';
            END;
    EXEC SQL /* Приложение на включающем языке */
            CALL удалить_курс ( ... );

    После того как хранимая процедура определена, она может быть вызвана с использованием оператора CALL. Хранимая процедура и ее параметры описываются также в информационной схеме (Information Schema) - представлениях только для чтения, которые отражают метаданные рассматриваемой базы данных.

    3.2. Хранимые функции

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

    В описании функции должна специфицироваться фраза RETURNS (возвращает), указывающая тип значения, которое она будет возвращать. Функции могут иметь только параметры вида IN (входные), что предполагается по умолчанию.

    После того как функция определена, она может быть вызвана как часть любого выражения. Оператор RETURN (возвратить) завершает исполнение функции и предоставляет то значение, которое будет возвращать функция. Если функция завершается без исполнения оператора RETURN, то возникает исключительная ситуация.

    CREATE FUNCTION курсы (s_id) 
            RETURNS CHAR VARYING (80)
            BEGIN 
                    DECLARE s CHAR VARYING (80) 
                            DEFAULT '';
                    FOR x AS SELECT *
                                    FROM    регистрационные_записи 
                                    WHERE   e.студент = s_id
                    DO 
                            IF s <> '' 
                                    THEN SET s = s || ', ';
                            END IF;
                            SET s = s || курс ; 
                    END FOR;
                    RETURN s; 
            END;
    SELECT имя, курсы (ид_студента) 
    FROM студенты 
    WHERE ...;

    3.3. Привилегии

    Список привилегий для объектов SQL был расширен включением привилегии EXECUTE (исполнить) для подпрограмм.

    GRANT EXECUTE ON курсы TO админ;4)
    GRANT EXECUTE ON удалить_курс TO 
                    старший_админ WITH GRANT OPTION;

    Чтобы вызвать подпрограмму, пользователь должен обладать предоставленной ему привилегией EXECUTE на эту подпрограмму.

    3.4. Полиморфизм и имена

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

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

    3.4.1. Особые имена

    Для того чтобы различать две подпрограммы с одним и тем же именем в одной и той же схеме, каждой их таких подпрограмм дается альтернативное и уникальное имя, которое называется ее особым именем (specific name). Такое имя может быть явно специфицировано, когда создается подпрограмма. Если же оно не было специфицировано, оно будет выбираться автоматически. Теперь подпрограмма может идентифицироваться в операторах DROP (удалить), GRANT (предоставить привилегию) или REVOKE (лишить привилегии) несколькими способами:

    DROP FUNCTION курсы;
    DROP FUNCTION 
                    курсы (CHAR VARYING (80));
    GRANT EXECUTE 
            ON SPECIFIC FUNCTION курсы1000 
            TO PUBLIC;

    3.4.2. Вызов подпрограмм

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

    В PSM-96 можно использовать путь как атрибут схемы и модуля. Путь содержит список схем, которые будут исследоваться при поиске подпрограмм-кандидатов на вызов.

    PSM-96 определяет отношение предшествования на множестве сравнимых типов данных, которое используется для оценки того, какая подпрограмма является наиболее подходящей для конкретного вызова:

    CHARACTER 
            < CHARACTER VARYING
    SMALLINT 
            < INTEGER 
            < DECIMAL 
            < ...

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

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

    1. Если вызов осуществляется с помощью оператора CALL, то отыскиваются все процедуры с заданным именем. В противном случае отыскиваются все функции с заданным именем.

    2. Для дальнейшего анализа оставляются только те подпрограммы, по отношению к которым данный пользователь обладает привилегией на исполнение (EXECUTE).

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

    4. Если имя подпрограммы квалифицировано5), то для дальнейшего шага выбора оставляются только те подпрограммы, которые определены в указанной схеме. Если же имя подпрограммы не было квалифицировано, то оставляются только подпрограммы, существующие в схеме, которая включается в заданный путь.

    5. Для каждого аргумента, действуя слева направо, поступаем следующим образом6):

    a) для каждой пары подпрограмм:
    Если один из параметров в этой позиции имеет более высокое предшествование по сравнению с другим параметром в той же позиции, удаляем из числа претендентов подпрограмму с более высоким предшествованием.

    6. Если осталось более одной подпрограммы, используется та, которая принадлежит схеме, появляющейся раньше в SQL-пути.

    3.5. Недетерминированность и побочные эффекты

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

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

    CREATE FUNCTION добавить_курс ( ... ) 
                    RETURNS INTEGER; 
            BEGIN 
                    INSERT INTO регистрационные_записи...;
                    RETURN ( SELECT COUNT (*) 
                            FROM регистрационные_записи ...);
            END;
    UPDATE студенты -- недопустимый оператор 
                                                    -- обновления 
    SET ... 
    WHERE n_курсы = добавить_курс ( ... );
    

    4. Хранимые модули

    Клиентские модули в SQL-92 имеют следующий вид:

    MODULE администрация 
    LANGUAGE C 
    AUTHORIZATION админ
    DECLARE LOCAL TEMPORARY TABLE t1 
            ( ... );
    PROCEDURE нанять_учителя ( ... );
            BEGIN ... END;
    ... 

    Модули некоторой формы могут храниться в базе данных в PSM-96.

    EXEC SQL 
            CREATE MODULE
                    DECLARE LOCAL TEMPORARY TABLE t1 
                            ...;
                    PROCEDURE нанять_учителя ( ... )
                            BEGIN ... END;
                    ... 
            END MODULE;

    Этот модуль не требует какого-либо предложения языка, поскольку все содержащиеся в нем подпрограммы могут быть вызваны только средствами SQL. Идентификатор полномочий для модуля - это имя владельца той схемы, которая содержит данный модуль, и поэтому его не требуется специфицировать.

    Каждая подпрограмма в модуле может иметь SQL-тело либо внешнее тело. Имена, используемые для обращения к подпрограммам, представляют собой имена этих подпрограмм, которые они имели бы, если бы они были созданы вне модуля. Если бы модуль администрация был в схеме cat1.админ, то к подпрограмме нанять_учителя можно было бы обращаться как к cat1.админ.нанять_учителя.

    Возможности оператора DROP (удалить) были расширены с тем, чтобы он мог удалять модули. Это действие уничтожает все подпрограммы, содержащиеся в данном модуле. Содержащиеся в модуле подпрограммы не могут быть удалены индивидуально.

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

    Хранимый модуль может содержать объявленные в нем локальные временные таблицы, как это делается в клиентском модуле. Хранимый модуль не может, однако, содержать объявлений курсоров, так как при завершении работы над PSM-96 были обнаружены некоторые связанные с этим проблемы.

    5. Внешние подпрограммы

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

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

    Автор может специфицировать два способа для этого типа отображения.

    5.1. Стиль параметров GENERAL

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

    CREATE FUNCTION звучание 
            (CHAR VARYING (30))
                    RETURNS CHAR (10) 
            LANGUAGE C 
            EXTERNAL NAME звучание1         
            PARAMETER STYLE GENERAL;
    char звучание1 [11] 
                            (char входная_строка [31]) { 
            ... 
            }
    SELECT  * 
    FROM    студенты 
    WHERE   звучание (имя) 
            = звучание ('Джонстон');

    Если функция звучание вызывается с неопределенным значением в качестве аргумента, то возникнет исключительная ситуация.

    5.2. Стиль параметров SQL

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

    CREATE FUNCTION звучание 
                                            (CHAR VARYING (30)) 
                                            RETURNS CHAR (10) 
            LANGUAGE C 
            EXTERNAL NAME звучание2 
            PARAMETER STYLE SQL;
    void звучание2 
                            (char входная_строка [31], 
                            char выходная_строка [11], 
                            long * индикатор_вх_строки, 
                            long * индикатор_вых_строки, 
                            char исключительная_ситуация [6], 
                            char имя_подпрограммы [120], 
                            char особое_имя [120], 
                            char сообщение [81]) { 
    ... 
    }

    Параметры функции звучание2 имеют следующий смысл:

    Параметр
    Режим
    Описание
    вх_строка
    in
    Входной параметр для SQL-функции
    вых_строка
    out
    Возвращаемое значение SQL-функции
    индикатор_вх_строки
    in
    Индикатор для параметра вх_строка
    (отрицателен для неопределенного значения, неотрицателен - в противном случае)
    индикатор_вых_строки
    out
    Индикатор для параметра вых_строка
    исключительная_ситуация
    in/out
    Значение SQLSTATE, которое характеризует успешное или неудачное исполнение подпрограммы
    имя_подпрограммы
    in
    Имя подпрограммы
    особое_имя
    in
    Особое имя для подпрограммы
    сообщение
    in/out
    Текст сообщения, который должен быть помещен в диагностическую область

    PSM-96 умалчивает, каким образом внешняя подпрограмма связывается с SQL-реализацией. Умалчивается также, исполняется ли такая подпрограмма в том же самом процессе или адресном пространстве, что и SQL-реализация.

    5.3. Недетерминированность и побочные эффекты

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

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

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

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

    6. Заключение

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

    PSM-96 получит дальнейшее развитие в разрабатываемом стандарте SQL3. Обсуждаются, в частности, возможности, подобные именованным параметрам и параметрам по умолчанию. SQL3/PSM будет служить основой для определения методов в абстрактных типах данных (ADT) SQL3.


    7. Литература

    [1] ISO/IEC 9075-4:1996, Information Technology - Database Language - SQL - Part 4: Persistent Stored Modules, должен быть опубликован позднее в 1996 году. Этот документ будет также известен как ANSI/IEC 9075-4: 1996, Information Technology - Database Language - SQL - Part 4: Persistent Stored Modules.

    [2] ISO/IEC 9075:1992, Information Technology - Database Language - SQL, 1992. Этот документ также известен как ANS X3.135-1992, Database Language SQL, 1992.

    [3] Richie, J. Condition Handling in SQL Persistent Stored Modules. - SIGMOD Record 24(3), p. 98-103, Sept. 1995.


    Эндрю Айзенберг
    Sybase, Burlington, MA 01803
    andrew.eisenberg@sybase.com

    1) Andrew Eisenberg. New Standard for Stored Procedures in SQL. SIGMOD Record, V. 25, # 4, December 1996.

    2) Здесь DML - Data Manipulation Language (язык манипулирования данными). Имеется в виду подмножество операторов языка SQL, выполняющих функции манипулирования данными. - Прим. пер.

    3) Здесь DDL - Data Definition Language (язык определения данных). Имеется в виду подмножество операторов языка SQL, выполняющих функции определения данных. - Прим. пер.

    4) В оригинале в этом операторе ошибочно указано другое имя функции. - Прим. пер.

    5) Имя подпрограммы может быть квалифицированным (уточненным, qualified) путем задания имени схемы. - Прим. пер.

    6) Неясно, для чего автор использует здесь в п. 5 столь странную структуризацию текста. - Прим. пер.


    © Пер. с англ. М.Р. Когаловского.

    Переведено и опубликовано с разрешения АСМ.

    © 1996 АСМ, Inc&


    Ваше имя:  E-mail: 
    Оценка интересности и/или полезности статьи:
    интересно и/или полезно
    мало интересно или полезно
    вредная статья

    Стиль изложения
    читается легко
    несколько трудна для чтения
    очень трудно читать
    Ваш комментарий:


     

    << ПРЕДЫДУЩАЯ СТАТЬЯ ] [ ОГЛАВЛЕНИЕ ] [ СЛЕДУЮЩАЯ СТАТЬЯ >>
    Banners System