×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

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

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

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

4.3.8. Обработка ошибок

4.3.8.1. Настройка функций обратного вызова
4.3.8.2. sqlca
4.3.8.3. SQLSTATE и SQLCODE

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

  • Функции обратного вызова могут быть настроены для обработки предупреждений и условий ошибок с помощью WHENEVER команды.
  • Подробную информацию об ошибке или предупреждении можно получить из sqlca переменной.

4.3.8.1. Настройка функций обратного вызова #

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

EXEC SQL WHENEVER условие действие;

условие может быть одним из следующих вариантов:

SQLERROR #

Указанное действие вызывается при возникновении любой ошибки в процессе выполнения оператора SQL.

SQLWARNING #

Указанное действие вызывается при возникновении любого предупреждения в процессе выполнения оператора SQL.

NOT FOUND #

Указанное действие выполняется всякий раз, когда оператор SQL выбирает или затрагивает ноль строк. (Данное условие не является ошибкой, но может потребоваться его специальная обработка.)

действие может быть одним из следующих вариантов:

CONTINUE #

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

GOTO label
GO TO label #

Перейти к указанной метке (используя оператор C goto statement).

SQLPRINT #

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

STOP #

Вызов exit(1), что приведет к завершению программы.

DO BREAK #

Выполнить оператор C break. Это следует использовать только в циклах или операторах switch.

DO CONTINUE #

Выполнить оператор C continue. Это следует использовать только в операторах циклов. при выполнении приведет к передаче управления в начало цикла.

CALL имя (args)
DO имя (args) #

Вызывает указанные функции C с заданными аргументами. (Данное использование отличается от смысла CALL и DO в обычном синтаксисе PostgreSQL.)

Стандарт SQL предусматривает только действия CONTINUE и GOTO (и GO TO).

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

EXEC SQL WHENEVER SQLWARNING SQLPRINT;
EXEC SQL WHENEVER SQLERROR STOP;

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

/*
 * WRONG
 */
int main(int argc, char *argv[])
{
    ...
    if (verbose) {
        EXEC SQL WHENEVER SQLWARNING SQLPRINT;
    }
    ...
    EXEC SQL SELECT ...;
    ...
}

/*
 * WRONG
 */
int main(int argc, char *argv[])
{
    ...
    set_error_handler();
    ...
    EXEC SQL SELECT ...;
    ...
}

static void set_error_handler(void)
{
    EXEC SQL WHENEVER SQLERROR STOP;
}

4.3.8.2. sqlca #

Для более расширенной обработки ошибок интерфейс внедренного SQL предоставляет глобальную переменную с именем sqlca (область взаимодействия SQL) имеет следующую структуру:

struct
{
    char sqlcaid[8];
    long sqlabc;
    long sqlcode;
    struct
    {
        int sqlerrml;
        char sqlerrmc[SQLERRMC_LEN];
    } sqlerrm;
    char sqlerrp[8];
    long sqlerrd[6];
    char sqlwarn[8];
    char sqlstate[5];
} sqlca;

(В многопоточной программе каждый поток автоматически получает собственный экземпляр sqlca. Это работает аналогично обработке стандартной глобальной переменной языка C errno.)

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

Если при выполнении последнего SQL оператора ошибок не возникло, sqlca.sqlcode будет равен 0, а параметр sqlca.sqlstate будет иметь значение "00000". Если возникло предупреждение или ошибка, то параметр sqlca.sqlcode будет отрицательным, а параметр sqlca.sqlstate будет отличаться от "00000". Положительное значение sqlca.sqlcode указывает на отсутствие критических ошибок, например, когда последний запрос вернул ноль строк. sqlcode и sqlstate представляют собой две различные схемы кодов ошибок; подробности приведены ниже.

Если последняя инструкция SQL была выполнена успешно, то элемент sqlca.sqlerrd[1] содержит тип oid обработанной строки, если это применимо, а элемент sqlca.sqlerrd[2] содержит количество обработанных или возвращенных строк, если это применимо для данной команды.

В случае ошибки или предупреждения поле sqlca.sqlerrm.sqlerrmc будет содержать строку, описывающую ошибку. Поле sqlca.sqlerrm.sqlerrml содержит длину сообщения об ошибке, хранящегося в sqlca.sqlerrm.sqlerrmc (результат функции strlen(), что не представляет существенного интереса для программиста на языке C). Обратите внимание, что некоторые сообщения слишком длинны, чтобы поместиться в поле фиксированного размера sqlerrmc array; они будут усечены.

В случае предупреждения параметр sqlca.sqlwarn[2] устанавливается в значение W. (Во всех остальных случаях ему присваивается значение, отличное от W.) Если параметр sqlca.sqlwarn[1] принимает значение W, это означает, что значение было усечено при сохранении в главную переменную. sqlca.sqlwarn[0] имеет значение W если какой-либо из других элементов установлен для индикации предупреждения.

Поля sqlcaid, sqlabc, sqlerrp, а остальные элементы массива sqlerrd и sqlwarn в настоящее время не содержат полезной информации.

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

Ниже приведен пример, сочетающий использование WHENEVER и sqlca, выводя содержимое sqlca при возникновении ошибки. Это может быть полезно для отладки или прототипирования приложений перед установкой более «дружественного к пользователю интерфейса» обработчик ошибок.

EXEC SQL WHENEVER SQLERROR CALL print_sqlca();

void
print_sqlca()
{
    fprintf(stderr, "==== sqlca ====\n");
    fprintf(stderr, "sqlcode: %ld\n", sqlca.sqlcode);
    fprintf(stderr, "sqlerrm.sqlerrml: %d\n", sqlca.sqlerrm.sqlerrml);
    fprintf(stderr, "sqlerrm.sqlerrmc: %s\n", sqlca.sqlerrm.sqlerrmc);
    fprintf(stderr, "sqlerrd: %ld %ld %ld %ld %ld %ld\n", sqlca.sqlerrd[0],sqlca.sqlerrd[1],sqlca.sqlerrd[2],
                                                          sqlca.sqlerrd[3],sqlca.sqlerrd[4],sqlca.sqlerrd[5]);
    fprintf(stderr, "sqlwarn: %d %d %d %d %d %d %d %d\n", sqlca.sqlwarn[0], sqlca.sqlwarn[1], sqlca.sqlwarn[2],
                                                          sqlca.sqlwarn[3], sqlca.sqlwarn[4], sqlca.sqlwarn[5],
                                                          sqlca.sqlwarn[6], sqlca.sqlwarn[7]);
    fprintf(stderr, "sqlstate: %5s\n", sqlca.sqlstate);
    fprintf(stderr, "===============\n");
}

Результат может выглядеть следующим образом (здесь приведена ошибка, вызванная опечаткой в имени таблицы):

==== sqlca ====
sqlcode: -400
sqlerrm.sqlerrml: 49
sqlerrm.sqlerrmc: отношение "pg_databasep" не существует на строке 38
sqlerrd: 0 0 0 0 0 0
sqlwarn: 0 0 0 0 0 0 0 0
sqlstate: 42P01
===============

4.3.8.3. SQLSTATE и SQLCODE #

Поля sqlca.sqlstate и sqlca.sqlcode — это две разные схемы, предоставляющие коды ошибок. Обе они основаны на стандарте SQL, однако SQLCODE был признан устаревшим в редакции стандарта SQL-92 и исключен из последующих редакций. В связи с этим при разработке новых приложений настоятельно рекомендуется использовать SQLSTATE.

SQLSTATE представляет собой массив из пяти символов типа данных char. Данные пять символов содержат цифры или заглавные буквы, которые представляют коды различных условий ошибок и предупреждений. SQLSTATE имеет иерархическую схему: первые два символа обозначают общий класс состояния, а последние три символа указывают на подкласс общего состояния. Состояние успешного выполнения обозначается кодом 00000. Параметры SQLSTATE в большинстве случаев определены в стандарте SQL. Digital Q.DataBase сервер изначально поддерживает SQLSTATE коды ошибок; следовательно, высокая степень согласованности может быть достигнута путем использования данной схемы кодов ошибок во всех приложениях. Для получения дополнительной информации см. Приложение 8.1.

SQLCODE, устаревшая схема кодов ошибок, представляет собой простое целое число. Значение 0 указывает на успешное выполнение, положительное значение указывает на успех с дополнительной информацией, а отрицательное значение указывает на ошибку. Стандарт SQL определяет только положительное значение +100, которое указывает на то, что последняя команда вернула или обработала ноль строк; конкретные отрицательные значения в стандарте не определены. Следовательно, данная схема обеспечивает лишь слабую переносимость и не обладает иерархической системой назначения кодов. Исторически сложилось так, что процессор внедренного SQL для Digital Q.DataBase назначал определенные специфические SQLCODE значения для внутреннего использования, которые приведены ниже вместе с их значениями типа numeric и символьными именами. Помните, что они не являются переносимыми на другие реализации SQL. Чтобы упростить перенос приложений на SQLSTATE схему, соответствующие параметры SQLSTATE также указаны в списке. Однако между этими двумя схемами нет однозначного или взаимно-однозначного соответствия (на самом деле это отношение «многие ко многим»), поэтому в каждом конкретном случае следует обращаться к глобальному SQLSTATE списку в Приложение 8.1 для уточнения деталей.

Ниже приведены назначенные SQLCODE значения:

0 (ECPG_NO_ERROR) #

Указывает на отсутствие ошибки (SQLSTATE 00000).

100 (ECPG_NOT_FOUND) #

Это штатная ситуация, указывающая на то, что последняя команда извлекла или обработала ноль строк, либо достигнут конец курсор. (SQLSTATE 02000)

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

while (1)
{
    EXEC SQL FETCH ... ;
    if (sqlca.sqlcode == ECPG_NOT_FOUND)
        break;
}

Однако WHENEVER NOT FOUND DO BREAK фактически выполняет это действие внутренне, поэтому обычно нет преимуществ в явном написании данного кода.

-12 (ECPG_OUT_OF_MEMORY) #

Указывает на исчерпание виртуальной памяти. Значение тип numeric определено как -ENOMEM. (SQLSTATE YE001)

-200 (ECPG_UNSUPPORTED) #

Указывает на то, что препроцессор ECPG сформировал конструкцию, которую библиотека не может распознать. Возможно, вы используете несовместимые версии препроцессора и библиотеки. (SQLSTATE YE002)

-201 (ECPG_TOO_MANY_ARGUMENTS) #

Это означает, что в команде было указано больше главных переменных, чем ожидалось данной командой. (SQLSTATE 07001 или 07002)

-202 (ECPG_TOO_FEW_ARGUMENTS) #

Это означает, что в команде было указано меньше главных переменных, чем ожидалось данной командой. (SQLSTATE 07001 или 07002)

-203 (ECPG_TOO_MANY_MATCHES) #

Это означает, что запрос вернул несколько строк, но оператор был рассчитан на хранение только одной строки результата (например, потому что указанные переменные не являются массивами). (SQLSTATE 21000)

-204 (ECPG_INT_FORMAT) #

Главная переменная имеет тип int а данные в базе данных имеют другой тип и содержат значение, которое не может быть интерпретировано как тип int. Библиотека использует функцию strtol() для данного преобразования. (SQLSTATE 42804)

-205 (ECPG_UINT_FORMAT) #

Главная переменная имеет тип unsigned int и данные в базе данных имеют другой тип и содержат значение, которое не может быть интерпретировано как тип unsigned int. Библиотека использует функцию strtoul() для данного преобразования (SQLSTATE 42804)

-206 (ECPG_FLOAT_FORMAT) #

Главная переменная имеет тип float и значение в базе данных относится к другому типу и содержит значение, которое не может быть интерпретировано как тип float. Библиотека использует функцию strtod() для данного преобразования. (SQLSTATE 42804)

-207 (ECPG_NUMERIC_FORMAT) #

Главная переменная имеет тип тип numeric и значение в базе данных относится к другому типу и содержит значение, которое не может быть интерпретировано как тип тип numeric значение. (SQLSTATE 42804)

-208 (ECPG_INTERVAL_FORMAT) #

Главная переменная имеет тип тип данных interval и значение в базе данных относится к другому типу и содержит значение, которое не может быть интерпретировано как тип тип данных interval значение. (SQLSTATE 42804)

-209 (ECPG_DATE_FORMAT) #

Главная переменная имеет тип date а данные в база данных имеет другой тип и содержит значение, которое не может быть интерпретировано как тип date значение. (SQLSTATE 42804)

-210 (ECPG_TIMESTAMP_FORMAT) #

Главная переменная имеет тип timestamp и элемент данных в базе данных относится к другому типу и содержит значение, которое не может быть интерпретировано как timestamp значение. (SQLSTATE 42804)

-211 (ECPG_CONVERT_BOOL) #

Это означает, что главная переменная имеет тип bool и значение в базе данных не является ни 't' ни 'f'. (SQLSTATE 42804)

-212 (ECPG_EMPTY) #

Оператор, отправленный на Digital Q.DataBase сервер, оказался пустым. (Обычно это не может произойти в программе с внедренным SQL, поэтому это может указывать на внутреннюю ошибку.) (SQLSTATE YE002)

-213 (ECPG_MISSING_INDICATOR) #

Было возвращено значение NULL, но индикаторная переменная NULL не была указана. (SQLSTATE 22002)

-214 (ECPG_NO_ARRAY) #

Обычная переменная была использована там, где требуется массив. (SQLSTATE 42804)

-215 (ECPG_DATA_NOT_ARRAY) #

База данных вернула простую переменную вместо ожидаемого значения массива. (SQLSTATE 42804)

-216 (ECPG_ARRAY_INSERT) #

Не удалось вставить значение в массив. (SQLSTATE 42804)

-220 (ECPG_NO_CONN) #

Программа попыталась обратиться к несуществующему соединению. (SQLSTATE 08003)

-221 (ECPG_NOT_CONN) #

Программа попыталась обратиться к соединению, которое существует, но не открыто. (Это внутренняя ошибка.) (SQLSTATE YE002)

-230 (ECPG_INVALID_STMT) #

Оператор, который вы пытаетесь использовать, не был подготовлен. (SQLSTATE 26000)

-239 (ECPG_INFORMIX_DUPLICATE_KEY) #

Ошибка дублирования ключа, нарушение ограничения уникальности (режим совместимости с Informix). (SQLSTATE 23505)

-240 (ECPG_UNKNOWN_DESCRIPTOR) #

Указанный дескриптор не найден. Оператор, который вы пытаетесь использовать, не был подготовлен. (SQLSTATE 33000)

-241 (ECPG_INVALID_DESCRIPTOR_INDEX) #

Указанный индекс дескриптора находится вне диапазона. (SQLSTATE 07009)

-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM) #

Был запрошен недопустимый элемент дескриптора. (Это внутренняя ошибка.) (SQLSTATE YE002)

-243 (ECPG_VAR_NOT_NUMERIC) #

Во время выполнения динамического оператора база данных вернула числовое значение, в то время как главная переменная не имела тип numeric. (SQLSTATE 07006)

-244 (ECPG_VAR_NOT_CHAR) #

Во время выполнения динамического оператора база данных вернула нечисловое значение, в то время как главная переменная имела тип numeric. (SQLSTATE 07006)

-284 (ECPG_INFORMIX_SUBSELECT_NOT_ONE) #

Результат подзапроса содержит более одной строки (в режиме совместимости с Informix). (SQLSTATE 21000)

-400 (ECPG_PGSQL) #

Произошла ошибка на стороне Digital Q.DataBase сервера. Сообщение содержит текст ошибки от Digital Q.DataBase сервера.

-401 (ECPG_TRANS) #

Сервер Digital Q.DataBase сообщил, что невозможно начать, зафиксировать или откатить транзакцию. (SQLSTATE 08007)

-402 (ECPG_CONNECT) #

Попытка установки соединения с базой данных не удалась. (SQLSTATE 08001)

-403 (ECPG_DUPLICATE_KEY) #

Ошибка дублирования ключа, нарушение ограничения уникальности. (SQLSTATE 23505)

-404 (ECPG_SUBSELECT_NOT_ONE) #

Результат подзапроса содержит более одной строки. (SQLSTATE 21000)

-602 (ECPG_WARNING_UNKNOWN_PORTAL) #

Указано недопустимое имя курсора. (SQLSTATE 34000)

-603 (ECPG_WARNING_IN_TRANSACTION) #

Транзакция уже выполняется. (SQLSTATE 25001)

-604 (ECPG_WARNING_NO_TRANSACTION) #

Активная транзакция отсутствует. (SQLSTATE 25P01)

-605 (ECPG_WARNING_PORTAL_EXISTS) #

Указано имя уже существующего курсора. (SQLSTATE 42P03)

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению