|
|
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Подскажите, плс, есть ли способ сообщать клиентскому приложению информацию об ошибке в стиле RAISE_APPLICATION_ERROR, но при этом без автоматического роллбека? Я пишу клиента на С++, который использует в процессе работы различные процедурки и триггеры, которые кидают ошибки через RAISE_ интерфейс. Но я хотел бы (хотя и не уверен, надо ли это мне так уж сильно), чтоб контроль за транзакцией осуществлялся клиентом, а не серверной СП. Готов к "методологическому" ответу. Типа, почему именно так лучше делать/не делать. Если кто сталкивался с проблемами при работе с 3-х звенкой - you are welcome. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 13:28 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Я в таких случаях операции на сервере офрмляю в виде хранимых функций, которые в случае успешного окончания возвращают NULL, иначе - текст сообщения об ошибке. А клиентская программа анализирует возвращенное значение и делает соответствующие телодвижения ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 13:38 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Это конечно выход, но если ошибку надо кинуть из процедуры, которая сама вызвана из процедуры, которая ... короче из глубины стека, то вручную раскручивать ошибку ломливо, особенно когда предлагается такой механизм как исключение. Возможно, в большинстве практических случаев сообщения об ошибке + булевский флаг успешности операции - это "за глаза", но ... Кстати, может есть какие пакаджи или еще что-нить (новые функции в новых версиях оракла [я работаю на 8]), которые реализовывали механизм исключений, но без обязательного роллбека? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 13:52 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Уточните задачу. Какой роллбэк Вы хотите подавить? Если операция DML падает с исключением, то оракул сам сделает ей откат. Процедура на PL/SQL тоже с точки зрения оракула выглядит как одна DML команда, обрабатывается так же. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 13:59 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Я хочу подавить роллбек, выдаваемый RAISE_APPLICATION_ERROR. Я хочу сам контролировать когда мне откатиться и куда. Например я хочу откатываться только до последнего SAVEPOINT, а не до начала всей транзакции. Или даже так - сторед процедура обнаружила неверный ввод - она кидает исключение, при этом до реальной работы с данными в таблице еще не дошло - то есть откатывать физически нечего. Однако я пока не уверен, что то чего я хочу это правильно. Ваши мнения очень бы мне пригодились... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 14:08 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Если нужно к черту - так и ступай к черту (Н. В. Гоголь). Надо откатиться до savepoint - устанавливай его смело, лови exception, rollback to savepoint, снова взводи, если надо, чтобы другие процедуры попользовались... Короче, свобода полная. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 14:52 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Да, я ловлю эксепшн, но роллбек-то уже сделан. Откат к savepoint не пройдет. Или не так? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 15:19 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Если ловится exception, откат дан только команде, его вызвавшей. При этом, к примеру, остальные DML в цикле продолжают себя нормально чувствовать. Кто запрещает сделать нужный откат в обработчике ошибок? rrrrrrr loop begin insert into xxxxx exception when others then - откат только вставки с нарушением чего-то там. yyyyyyy; end; end loop; В этом примере цикл продолжит работать, откатятся только операции с ошибками (и скорее всего в базу попадут неправильные данные). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 16:07 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
А если я ловлю этот эксепшн не PL|SQL, а в клиенте на VB? Эффект тот же? Отката не будет? вот такой код СП CREATE OR REPLACE PROCEDURE SP_TEST() BEGIN INSERT INTO xxx --проходит нормально RAISE_APPLICATION_ERROR (code, msg); END; Если я вызову эту сторед процедуру из VB, поймаю эксепшн (работа через ADO) и закоммичу сессию - инсерт сохранит результат работы или откатиться? Я проверил - данные теряются. Значит, для моего случая (см. начало треда), ваше предложение не верно. Наверное когда эксепшн покидает инстанс идет роллбек. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 16:35 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
RTFM, please, иногда. Блок PL/SQL считается завершенным успешно (и не откатывается), если он не вызвал необработанного исключения или это исключение было обработано внутри блока. В случае передачи исключения охватывающему блоку или вызывающей среде блок считается выполненным с ошибкой, и все действия, которые он проводил подлежат откату. P.S. Документацию надо не только читать, но и почитывать. Узнаете много интересного о том, что, как Вам казалось, знаете... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.03.2003, 17:34 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Отвечаю. Если б я прочел ранее - вопрос бы не возник. Просто не всегда есть время прочесть. А форум для того и есть, чтоб вопросы задавать. Я честно сначала сделал поиск по нему, чтоб найти нужный ответ в предыдущих тредах - не нашлось. RTFM - это конечно хороший ответ, но зачем тогда форум? В принципе, вовсе не обязательно давать ответ в тексте собственного письма, если достаточно !!! ссылки на доку. Но ссылки не всегда достаточно. Это - лирика. Что касается ответа на "В случае передачи исключения охватывающему блоку или вызывающей среде блок считается выполненным с ошибкой, и все действия, которые он проводил подлежат откату", то про охватывающий блок, в случае RAISE_APPLICATION_ERROR ваш ответ неверен (если я правильно его понял). Если эксепшн будет пойман где-то выше по стеку и обработан - автоматического отката не будет (то есть обработан в охватывающем блоке). А вот для среды - все верно. И еще, я задавал, собственно говоря, другой вопрос - буду признателен за ответ на него. Возможно, кто-то знает как это делается в других БД. ЗЫ: Будем терпиливы к коллегам :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.03.2003, 11:02 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Я все сказал верно - Вы просто неправильно понимаете определение блока PL/SQL. В примере с циклом, который я приводил, я не зря поставил begin ... end внутри цикла. Таким образом я создал еще один блок со своим собственным перехватчиком ошибок. Если бы я его не создавал, то при первой же ошибке произошел бы выход из цикла, и все команды без исключения внутри него откатились бы. Совершенно аналогичная ситуация и с вызовами процедур/функций. Каждая вызванная процедура - вложенный блок в вызывающей. Если в вызванной процедуре исключение не ловится, то все действия этой процедуры откатываются, и обработка ошибки поручается вызвавшей процедуре. Здесь абсолютно не важно, кому поручена обработка - рантайму, программе на java, VB или вызвавшей PL/SQL процедуре. raise_application_error - это просто способ сообщить вызвавшему блоку, что вложенный блок завершился аварийно, но при этом совершить какие-либо полезные действия, которые надо закоммитить, чтобы не окатились при обработке ошибки. С тем же успехом Вы можете вместо RAE использовать оператор raise. Но RAE дает возможность замаскировать пользовательскую ошибку под оракловскую ("сдохла Гектором, будучи по существу Эммой"). С "методологической точки" зрения RAE всегда вызовет откат по причине, описанной выше. Поэтому полный контроль за транзакцией может быть выполнен только при отсутствии исключений, то есть передачи флагов, как сразу Вам преложили. P.S. Не обижайтесь на RTFM и на то, что в ходе обсуждения "методологического" вопроса выяснились некоторые проблемы чисто технического свойства, без которых методология сильно хромает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.03.2003, 11:33 |
|
||
|
RAISE_APPLICATION_ERROR
|
|||
|---|---|---|---|
|
#18+
Я заметил скобки begin end. И что это отдельный блок - понял А вот с этим не согласен : "Совершенно аналогичная ситуация и с вызовами процедур/функций. Каждая вызванная процедура - вложенный блок в вызывающей. Если в вызванной процедуре исключение не ловится, то все действия этой процедуры откатываются, и обработка ошибки поручается вызвавшей процедуре" Вот пример (псеводкод, но я проверял на PLSQL): Proc INNER begin insert into log(message) values('hi from inner'); raise_application_error(code, msg); end; Proc OUTER begin INNER; end; declare begin OUTER; exception when others then dbms_output.put_line('exception'); end; По вашим словам insert не пройдет - но на практике это не так. Я что-то упустил? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.03.2003, 11:47 |
|
||
|
|

start [/forum/topic.php?fid=52&tid=1991390]: |
0ms |
get settings: |
8ms |
get forum list: |
20ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
157ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
| others: | 239ms |
| total: | 495ms |

| 0 / 0 |
