Личный кабинет
Укажите e-mail, на который будет выслан код восстановления пароля.
На указанный вами адрес e-mail был выслан код подтверждения аккаунта. Введите полученный код для продолжения:
Введите новый пароль два раза:
SQLSTATE
SQLCODE
В этом разделе описывается, как можно обрабатывать исключительные условия и предупреждения в программе со встраиваемым SQL. Для этого предназначены два средства, которые могут дополнять друг друга.
WHENEVER
sqlca
Один простой метод перехвата ошибок и предупреждений заключается в назначении определённого действия, которое будет выполняться при некотором условии. В общем виде:
EXEC SQL WHENEVER условие действие;
условие
действие
Здесь условие может быть следующим:
SQLERROR
Указанное действие вызывается, когда при выполнении оператора SQL происходит ошибка.
SQLWARNING
Указанное действие вызывается, когда при выполнении оператора SQL выдаётся предупреждение.
NOT FOUND
Указанное действие вызывается, когда оператор SQL получает или обрабатывает ноль строк. (Это обстоятельство не считается ошибкой, но бывает полезно отследить его.)
действие может быть следующим:
CONTINUE
Это фактически означает, что условие игнорируется. Это поведение по умолчанию.
GOTO метка
метка
GO TO метка
Перейти к указанной метке (используя оператор goto языка C).
goto
SQLPRINT
Вывести сообщение в устройство стандартного вывода. Это полезно для простых программ или при разработке прототипов. Содержание этого сообщения не настраивается.
STOP
Вызвать exit(1), что приведёт к завершению программы.
exit(1)
DO BREAK
Выполнить оператор break языка C. Этот вариант следует использовать только в циклах или операторах switch.
break
switch
DO CONTINUE
Выполнить оператор continue языка C. Этот вариант следует использовать только в циклах. Данный оператор передаёт управление в начало цикла.
continue
CALL имя (аргументы)
имя
аргументы
DO имя (аргументы)
Вызвать указанные функции C с заданными аргументами. (Эти вызовы имеют смысловые отличия от CALL и DO в обычной грамматике Postgres Pro.)
CALL
DO
В стандарте SQL описаны только действия CONTINUE и GOTO (и GO TO).
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 не дадут желаемого эффекта:
EXEC SQL WHENEVER
/* * НЕПРАВИЛЬНО */ int main(int argc, char *argv[]) { ... if (verbose) { EXEC SQL WHENEVER SQLWARNING SQLPRINT; } ... EXEC SQL SELECT ...; ... }
/* * НЕПРАВИЛЬНО */ int main(int argc, char *argv[]) { ... set_error_handler(); ... EXEC SQL SELECT ...; ... } static void set_error_handler(void) { EXEC SQL WHENEVER SQLERROR STOP; }
Для более гибкой обработки ошибок в интерфейсе встраиваемого SQL представлена глобальная переменная с именем sqlca (SQL Communication Area, Область сведений 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.)
errno
Структура sqlca покрывает и предупреждения, и ошибки. Если в процессе выполнения оператора выдаётся несколько предупреждений или ошибок, sqlca будет содержать сведения только о последнем(ей) из них.
Если последний оператор SQL выполняется без ошибки, sqlca.sqlcode будет содержать 0, а sqlca.sqlstate — "00000". Если выдаётся предупреждение или ошибка, в sqlca.sqlcode будет содержаться отрицательное число, а sqlca.sqlstate будет отличаться от "00000". Положительное значение sqlca.sqlcode устанавливается при нейтральном событии, например, когда последний запрос возвращает ноль строк. Поля sqlcode и sqlstate представляют две различные схемы кодов ошибок; подробнее они описаны ниже.
sqlca.sqlcode
sqlca.sqlstate
"00000"
sqlcode
sqlstate
Если последний оператор SQL был успешным, в sqlca.sqlerrd[1] содержится OID обработанной строки (если это уместно), а в sqlca.sqlerrd[2] количество обработанных или возвращённых строк (если это уместно для команды).
sqlca.sqlerrd[1]
sqlca.sqlerrd[2]
В случае ошибки или предупреждения sqlca.sqlerrm.sqlerrmc будет содержать строку, описывающую ошибку. Поле sqlca.sqlerrm.sqlerrml содержит длину сообщения об ошибке, которое хранится в sqlca.sqlerrm.sqlerrmc (результат функции strlen(), который не очень интересен для программиста C). Заметьте, что некоторые сообщения могут не умещаться в массив sqlerrmc фиксированного размера; они будут обрезаться.
sqlca.sqlerrm.sqlerrmc
sqlca.sqlerrm.sqlerrml
strlen()
sqlerrmc
В случае предупреждения, в sqlca.sqlwarn[2] записывается символ W. (Во всех других случаях значение будет отличным от W.) Символ W в sqlca.sqlwarn[1] показывает, что значение было обрезано при сохранении в переменной среды. W в sqlca.sqlwarn[0] устанавливается, если предупреждение отмечается в каком-либо другом элементе массива.
sqlca.sqlwarn[2]
W
sqlca.sqlwarn[1]
sqlca.sqlwarn[0]
Поля sqlcaid, sqlabc, sqlerrp и остальные элементы sqlerrd и sqlwarn в настоящее время не содержат полезной информации.
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: relation "pg_databasep" does not exist on line 38 sqlerrd: 0 0 0 0 0 0 sqlwarn: 0 0 0 0 0 0 0 0 sqlstate: 42P01 ===============
Поля sqlca.sqlstate и sqlca.sqlcode отражают две различные схемы, представляющие коды ошибок. Обе схемы пришли из стандарта SQL, но схема SQLCODE была признана устаревшей в редакции SQL-92 и исключена в последующих редакциях. Поэтому в новых приложениях настоятельно рекомендуется использовать SQLSTATE.
SQLSTATE задаётся в массиве из пяти символов. Эти пять символов содержат цифры или буквы в верхнем регистре, представляющие коды различных условий ошибок и предупреждений. SQLSTATE определяется по иерархической схеме: первые два символа обозначают общий класс условия, а следующие три — подкласс общего условия. Успешное состояние обозначается кодом 00000. По большей части коды SQLSTATE определены в стандарте SQL. Сервер Postgres Pro поддерживает коды ошибок SQLSTATE естественным образом; поэтому используя во всех приложениях именно эту схему кодов ошибок, можно добиться высокой степени согласованности. За дальнейшими сведениями обратитесь к Приложению A.
00000
SQLCODE — устаревшая схема, в которой коды ошибок представлены просто целыми числами. Значение 0 обозначает успешное завершение, положительное значение — успешное завершение с дополнительной информацией, а отрицательное говорит об ошибке. В стандарте SQL определено только положительное значение +100, показывающее, что последняя команда вернула или затронула ноль строк, но отрицательные значения не определены. Таким образом, с этой схемой нельзя рассчитывать на переносимость и она не имеет иерархической структуры. Исторически сложилось, что процессор встраиваемого SQL для Postgres Pro назначает некоторые определённые значения SQLCODE для собственного использования; они перечислены ниже с числовыми значениями и символьными именами. Помните, что эти коды несовместимы с другими реализациями SQL. Поэтому для упрощения перевода приложений на схему SQLSTATE вместе с этими кодами перечисляются соответствующие значения SQLSTATE. Однако однозначного соответствия один-к-одному или один-ко-многим между этими двумя схемами не существует (на самом деле это соответствие многие-ко-многим), поэтому следует свериться со списком SQLSTATE в Приложении A в каждом случае.
SQLCODE может принимать следующие значения:
ECPG_NO_ERROR
Показывает, что ошибки нет. (SQLSTATE 00000)
ECPG_NOT_FOUND
Это нейтральное условие, показывающее, что последняя команда вернула или обработала ноль строк, либо курсор достиг конца. (SQLSTATE 02000)
Выбирая данные из курсора в цикле, можно проверять этот код, чтобы понять, когда нужно прервать цикл, следующим образом:
while (1) { EXEC SQL FETCH ... ; if (sqlca.sqlcode == ECPG_NOT_FOUND) break; }
Но WHENEVER NOT FOUND DO BREAK внутри по сути делает это же, поэтому такое явное условие обычно ничем не лучше.
WHENEVER NOT FOUND DO BREAK
ECPG_OUT_OF_MEMORY
Указывает, что закончилась виртуальная память. Числовое значение определено как -ENOMEM. (SQLSTATE YE001)
-ENOMEM
ECPG_UNSUPPORTED
Указывает, что препроцессор сгенерировал код, который не понимает библиотека. Возможно, вы используете несовместимые версии препроцессора и библиотеки. (SQLSTATE YE002)
ECPG_TOO_MANY_ARGUMENTS
Это означает, что в команде было указано больше переменных среды, чем она ожидает. (SQLSTATE 07001 или 07002)
ECPG_TOO_FEW_ARGUMENTS
Это означает, что в команде было указано меньше переменных среды, чем она ожидает. (SQLSTATE 07001 или 07002)
ECPG_TOO_MANY_MATCHES
Это означает, что запрос вернул несколько строк, но оператор был подготовлен только для одной строки результата (например, потому что переданные переменные — не массивы). (SQLSTATE 21000)
ECPG_INT_FORMAT
Переменная среды типа int и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать в int. Для этого преобразования библиотека использует функцию strtol(). (SQLSTATE 42804)
int
strtol()
ECPG_UINT_FORMAT
Переменная среды типа unsigned int и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать в unsigned int. Для этого преобразования библиотека использует функцию strtoul(). (SQLSTATE 42804)
unsigned int
strtoul()
ECPG_FLOAT_FORMAT
Переменная среды типа float и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать во float. Для этого преобразования библиотека использует функцию strtod(). (SQLSTATE 42804)
float
strtod()
ECPG_NUMERIC_FORMAT
Переменная среды типа numeric и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать в numeric. (SQLSTATE 42804)
numeric
ECPG_INTERVAL_FORMAT
Переменная среды типа interval и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать в interval. (SQLSTATE 42804)
interval
ECPG_DATE_FORMAT
Переменная среды типа date и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать в date. (SQLSTATE 42804)
date
ECPG_TIMESTAMP_FORMAT
Переменная среды типа timestamp и данные в базе имеют разные типы, и в этих данных содержится значение, которое нельзя преобразовать в timestamp. (SQLSTATE 42804)
timestamp
ECPG_CONVERT_BOOL
Это означает, что переменная среды имеет тип bool, а значение в базе данных отличается от 't' или 'f'. (SQLSTATE 42804)
bool
't'
'f'
ECPG_EMPTY
Серверу Postgres Pro был передан пустой оператор. (Этого обычно не должно происходить в программе со встраиваемым SQL, так что это может указывать на внутреннюю ошибку.) (SQLSTATE YE002)
ECPG_MISSING_INDICATOR
Возвращено значение NULL, но переменная-индикатор NULL не задана. (SQLSTATE 22002)
ECPG_NO_ARRAY
Там, где требуется массив, была передана обычная переменная. (SQLSTATE 42804)
ECPG_DATA_NOT_ARRAY
База данных возвратила обычную переменную там, где требуется значение-массив. (SQLSTATE 42804)
ECPG_ARRAY_INSERT
Не удалось вставить значение в массив. (SQLSTATE 42804)
ECPG_NO_CONN
Программа попыталась использовать несуществующее подключение. (SQLSTATE 08003)
ECPG_NOT_CONN
Программа попыталась использовать подключение, которое существует, но не было открыто. (Это внутренняя ошибка.) (SQLSTATE YE002)
ECPG_INVALID_STMT
Оператор, который вы пытаетесь выполнить, не был подготовлен. (SQLSTATE 26000)
ECPG_INFORMIX_DUPLICATE_KEY
Ошибка повторяющегося ключа, нарушение ограничения уникальности (режим совместимости с Informix). (SQLSTATE 23505)
ECPG_UNKNOWN_DESCRIPTOR
Указанный дескриптор не найден. Оператор, который вы пытаетесь использовать, не был подготовлен. (SQLSTATE 33000)
ECPG_INVALID_DESCRIPTOR_INDEX
Указанный индекс дескриптора вне диапазона. (SQLSTATE 07009)
ECPG_UNKNOWN_DESCRIPTOR_ITEM
Запрошен неверный элемент дескриптора. (Это внутренняя ошибка.) (SQLSTATE YE002)
ECPG_VAR_NOT_NUMERIC
При выполнении динамического оператора база данных возвратила числовое значение, тогда как переменная среды — не числовая. (SQLSTATE 07006)
ECPG_VAR_NOT_CHAR
При выполнении динамического оператора база данных возвратила не числовое значение, тогда как переменная среды — числовая. (SQLSTATE 07006)
ECPG_INFORMIX_SUBSELECT_NOT_ONE
Результат подзапроса представлен не одной строкой (режим совместимости с Informix). (SQLSTATE 21000)
ECPG_PGSQL
Ошибка произошла на стороне сервера Postgres Pro. В тексте ошибки содержится сообщение об ошибке от сервера Postgres Pro.
ECPG_TRANS
Сервер Postgres Pro сообщает, что клиент не может запускать, фиксировать или отменять транзакцию. (SQLSTATE 08007)
ECPG_CONNECT
Попытка подключения к базе данных была неудачной. (SQLSTATE 08001)
ECPG_DUPLICATE_KEY
Ошибка повторяющегося ключа, нарушение ограничения уникальности. (SQLSTATE 23505)
ECPG_SUBSELECT_NOT_ONE
Результат подзапроса представлен не одной строкой. (SQLSTATE 21000)
ECPG_WARNING_UNKNOWN_PORTAL
Указано неверное имя курсора. (SQLSTATE 34000)
ECPG_WARNING_IN_TRANSACTION
Транзакция в процессе выполнения. (SQLSTATE 25001)
ECPG_WARNING_NO_TRANSACTION
Нет активной (выполняющейся) транзакции. (SQLSTATE 25P01)
ECPG_WARNING_PORTAL_EXISTS
Было указано имя существующего курсора. (SQLSTATE 42P03)
Соглашаюсь с условиями обработки персональных данных