powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Не работают @@transtate и @@error - как поймать ошибку?
12 сообщений из 12, страница 1 из 1
Не работают @@transtate и @@error - как поймать ошибку?
    #39539147
Lysyi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Adaptive Server Enterprise/12.5.4/EBF 15447 ESD#8/P/x86_64/Enterprise Linux/ase1254/2105/64-bit/OPT/Sat Mar 22 04:13:57 2008

Просветите, пожалуйста: как распознать факт наличия ошибки (exception).
Почему-то @@transtate и @@error не показывают этого факта (раньше вроде работало...)

Вот такой код запускается через isql:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 begin tran

   exec SLIVFreeRest_fal

 if ((@@transtate <> 0) or
     (@@error <> 0)) begin
    rollback
    print "ERROR!!! В процедуре NewDate шаг 7/12"
 end else begin
    commit
    print "OK... По выполнению процедуры NewDate шаг 7/12"
 end



Внутри ХП SLIVFreeRest_fal происходит exception, но в этом вызывающем коде после завершения ХП
@@transtate = 0 и @@error = 0
Так что в любом случае происходит выполнение commit-a
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39539263
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lysyi,

Факт ошибки: @@error != 0

@@transtate в ловле исключений не поможет.

А в остальном - смотри на свою хранимую процедуру, действительно ли она посылает исключение? Уверен? Точно-точно?

А в скрипте который отдается в isql есть строка go?
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39539600
Lysyi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,
Насчёт исключения - да я уверен, это исключение пишется в вывод в файл, вот так это выглядит:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
...
Msg 582, Level 16, State 3:
Server 'mars2nz', Procedure 'SLIVFreeRest_fal', Line 197:
Cursor 'fr_cur' was closed implicitly because the current cursor position was
deleted due to an update or a delete. The cursor scan position could not be
recovered. This happens for cursors which reference more than one table.
Msg 559, Level 16, State 1:
Server 'mars2nz', Procedure 'SLIVFreeRest_fal', Line 200:
Attempt to use a cursor 'fr_cur' which is not open. Use the system stored
procedure sp_cursorinfo for more information.
 AllCount    PerfomCount OtlupCount  
 ----------- ----------- ----------- 
           1           1           0 

(1 row affected)
OK... По выполнению процедуры NewDate шаг 7/12
...


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


Насчёт @@error - здесь же фиксируется результат выполнения последнего оператора. После оператора, вызвавшего исключение выполняются другие операторы, которые сбрасывают @@error в ноль.
Да что говорить, наверное сам вызов exec SLIVFreeRest_fal и сбрасывает @@error
Я тут больше на @@transtate надеялся - исключение же внутри транзакции происходит


Насчёт go - да, в скрипте go есть. Из скрипта вызывается много процедур, каждая в своём пакете (go). Но вот конкретный приведённый код, он внутри одной из этих процедур (NewDate) и в процедуре никаких go, конечно, нету
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39539718
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LysyiНасчёт исключения - да я уверен, это исключение пишется в вывод в файл, вот так это выглядит:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
...
Msg 582, Level 16, State 3:
Server 'mars2nz', Procedure 'SLIVFreeRest_fal', Line 197:
Cursor 'fr_cur' was closed implicitly because the current cursor position was
deleted due to an update or a delete. The cursor scan position could not be
recovered. This happens for cursors which reference more than one table.
Msg 559, Level 16, State 1:
Server 'mars2nz', Procedure 'SLIVFreeRest_fal', Line 200:
Attempt to use a cursor 'fr_cur' which is not open. Use the system stored
procedure sp_cursorinfo for more information.


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

У сервера есть собственное понятие что такое fatal и nonfatal error. Те ошибки что считаются сервером за nonfatal - не обрывают хранимую процедуру и не будут отловлены твоим кодом (но попадут в лог isql).

В данном случае (авто-закрытие курсора и попытка чтения из закрытого курсора), это не исключение приводящее к прерыванию процедуры, а предупреждение которое можно игнорировать без особых проблем для самой базы данных (в смысле не нарушается целостность заявленная через unique/check/foreign key/etc). Проблемы с курсором - не приводят к остановке хранимой процедуры.

Чтобы обрывать ХП и отлавливать это через @@error как ты показывал в первом посте надо или совершать "страшные" ошибки (которые fatal с точки зрения сервера) или кидать исключения вручную при помощи команды raiserror.

Подробнее про ошибки читать тут:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc38151.1510/html/iqrefbb/iqrefbb638.htm


LysyiЯ тут больше на @@transtate надеялся - исключение же внутри транзакции происходит@@transtate=0 - ошибок нет. @@transtate=1 коммит отработал успешно.
А ошибки транзакции ( @@transtate=2 или 3), будут только если команды insert/update/delete были прерваны по какой-то причине. Нарушение уникальности в индексе например (может быть и 2 и 3). А чтобы устойчиво получать 3-ку, надо например запускать долгоиграющую команду типа удалить все записи из таблицы с миллиардом строк, а пока она выполняется зайти как администратор и отменить команду - тогда юзер отдавший команду почти наверняка получит @@transtate=3
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39539746
Lysyi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я со всем заранее согласен и благодарен за участие, но вопрос остаётся: как поймать ошибку, произошедшую где-то в глубине вызванной процедуры в SQL-коде, вызвавшей эту процедуру.
Готов на всё - скажите только что делать.

Реакция системы на ошибку определяется её уровнем серьёзности. Не удачный, конечно, пример с курсором, но это субъективно. Объективно в данном случае Level 16, то есть это самая обычная ошибка (raiserror тоже даёт Level 16), недостаточная для того, чтобы оборвать выполнение, но достаточная для того, чтобы вызвать исключение. При вызове этой ХП из кода приложения (если begin tran / commit / rollback делает приложение), Exception прекрасно ловится и происходит откат. А если вызывать из SQL-кода, то ошибки(исключения) не видно. Наверное так же быть не должно, должен же быть способ...

Проверил: вставил в начале SLIVFreeRest_fal raiserror - результат тот же: после exec сразу @@transtate = 0 и @@error = 0, хотя мой текст из raiserror исправно печатается в лог.
То же самое было у меня с другой ХП, в которой ошибка была при выполнении update (просто я её уже исправил, поэтому затруднительно её здесь привести). Ну, строго говоря, там не было нарушения уникальности в индексе, но там было вполне аналогичное нарушение: срабатывала проверка в тргигере и процесс прерывался через
ROLLBACK TRIGGER WITH RAISERROR ...
RETURN
Результат тот же: после exec сразу @@transtate = 0 и @@error = 0

Ну я, конечно смоделирую нарушение уникальности в индексе (проверить), но думаю, будет то же самое - во всех этих случаях генерируется исключение с Level = 16
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39541061
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LysyiЯ со всем заранее согласен и благодарен за участие, но вопрос остаётся: как поймать ошибку, произошедшую где-то в глубине вызванной процедуры в SQL-коде, вызвавшей эту процедуру.
Готов на всё - скажите только что делать.


Всё очень просто. И одновременно очень сложно.
После КАЖДОГО оператора КАЖДОЙ процедуры нужно проверять @@error и @@rowcount на наличие ошибок и неожидаемого поведения. Если ошибка обнаружена, её надо соотв. образом обрабатывать.

P.S. напомню, что именно исключений в ASE нет. Есть только ошибки.
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39541063
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LysyiРеакция системы на ошибку определяется её уровнем серьёзности. Не удачный, конечно, пример с курсором, но это субъективно. Объективно в данном случае Level 16, то есть это самая обычная ошибка (raiserror тоже даёт Level 16), недостаточная для того, чтобы оборвать выполнение, но достаточная для того, чтобы вызвать исключение. При вызове этой ХП из кода приложения (если begin tran / commit / rollback делает приложение), Exception прекрасно ловится и происходит откат. А если вызывать из SQL-кода, то ошибки(исключения) не видно. Наверное так же быть не должно, должен же быть способ...


Ещё раз, о каких исключениях ты всё время ведёшь речь?
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39541191
antand
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivПосле КАЖДОГО оператора КАЖДОЙ процедуры нужно проверять @@error и @@rowcount на наличие ошибок и неожидаемого поведения. Если ошибка обнаружена, её надо соотв. образом обрабатывать.

P.S. напомню, что именно исключений в ASE нет. Есть только ошибки.

Поддержу. Хоть и в ASA, но постоянно применял такую практику внутри процедур, для каждого оператора, который может привести к ошибке, с точки зрения бизнес-логики - обязательно, с точки зрения сервера или базы выборочно, по ситуации. Зато на выходе из процедуры по коду возврата и сообщению четко понимаешь что происходит. Помогает как для разработчика так и для культурного оповещения пользователю, администратору и т.д.
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39541275
Lysyi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivЕщё раз, о каких исключениях ты всё время ведёшь речь?

Ну раз нет в Sybase исключений, то получается, что ни о каких...

Вообще я имел в виду, что когда приложение вызывает SQL-код и в этом SQL-коде происходит хоть какая-то ошибка с уровнем серьёзности выше 10 (кажется 10, точно не помню), то приложение создаёт объект класса Exception (TException и т.п.). Факт возникновения такого объекта ловится в блоке try и управление передаётся коду, отвечающему за обработку ошибки (откат транзакции, вывод сообщения и т.п.). Проверять @@error после каждого оператора не нужно. Это работает и с Sybase, т.е. строго, наверное, нельзя говорить, что в Sybase исключений совсем нет.

Ну ещё я имел в виду, что в MS SQL есть исключения и даже блок try в TSQL предусмотрен. Вроде СУБДы из одного корня растут.

Так-то что... Спасибо, коллеги, понятно. На нет и суда нет :(

Но вообще, конечно, странно!
После каждого оператора @@error проверять это как-то несовременно что-ли. У меня тут километры кода - всё перелопатить нереально. Но главное даже не это: потенциально ошибка может произойти где угодно (даже то, что быть не может очень даже может быть). Странно, что нету способа отловить любую ошибку, где бы она внутри транзакции не произошла
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39541337
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LysyiСтранно, что нету способа отловить любую ошибку, где бы она внутри транзакции не произошлаНу почему же нет?
Есть. Только не в TSQL :)
Нужно будет отказаться от isql. И заменит его собственной скрипто-запускалкой.
Просто создаешь глобальный флаг "была ошибка", и в колбеках устанавливаешь его.

Что-то в духе
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
use Sybase::CTlib;
our $error_happened = 0;
sub srv_cb {
	($serr_dbh, $serr_number, $serr_severity, $serr_state, $serr_line, $serr_server, $serr_proc, $serr_msg) = @_;
	if($serr_severity >10) {
		log $serr_msg;
		$error_happened++;
	}
	return CS_SUCCEED;
}
my $dbh = new Sybase::CTlib $db_login, $db_pw, $db_server, 'my_isql' or die;
ct_callback(CS_SERVERMSG_CB, \&srv_cb);
$dbh->ct_execute($my_sql);
do{ $rc = $dbh->ct_results($restype); die if($rc==CS_FAIL); } while($rc==CS_SUCCEED);
if($error_happened > 0) {
   ... where were some errors...
}



Ну а если пишешь на Си, то можно вместо колбеков использовать ct_diag() в нужных местах.
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39542773
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lysyi Проверять @@error после каждого оператора не нужно. Это работает и с Sybase, т.е. строго, наверное, нельзя говорить, что в Sybase исключений совсем нет.


Нужно. Именно потому, что исключений нет.
Но есть и ещё один аспект , например, у тебя такой код:

Код: sql
1.
select @id = user_id from USERS u where u.name = :USER_NAME



Ты его выполняешь, и как ты думаешь, что будет в переменной @@error , если пользователя с таким name не будет в твоей БД?

Вот.

LysyiНу ещё я имел в виду, что в MS SQL есть исключения и даже блок try в TSQL предусмотрен.


Да, по ошибкам БД тебе вылетит исключение, по raiserror тоже, но что тебе прилетит в вышеуказанном случае ?
Опять, ничего. Это не системная ошибка уровня БД, это ошибка в логике приложения уже.

LysyiПосле каждого оператора @@error проверять это как-то несовременно что-ли. У меня тут километры кода - всё перелопатить нереально. Но главное даже не это: потенциально ошибка может произойти где угодно (даже то, что быть не может очень даже может быть). Странно, что нету способа отловить любую ошибку, где бы она внутри транзакции не произошла

Ну, вот так вот, других рецептов нет (в смысле не существует).
...
Рейтинг: 0 / 0
Не работают @@transtate и @@error - как поймать ошибку?
    #39543874
Lysyi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Еще раз спасибо, коллеги.
Ну что же: на нет и суда нет...
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Не работают @@transtate и @@error - как поймать ошибку?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]