Помощь клуба, oracle
Sep. 26th, 2005 06:23 pmЯ не уверен, что правильно понимаю подход, возможно нужно совсем по-другому делать, так что пишите и по этому поводу.
Есть старая программа. В ней есть процедура разбора внешнего файла, распихивание его инфы по разным таблицам. Есть в ней бага: при записи акции проверяем, есть ли в базе эмиттер акции, если ещё нет - создаём эмиттера. Бага в том, что при создании эмиттера (простой insert into) не проверяется, есть ли в базе страна эмиттера, и недавно всё полетело из-за каких-то иранских облигаций.
Что думал сделать я: процедуру create_emmetteur (sorry for my french), которая принимает некоторое количество параметров и пытается создать эмиттера. Если получилось - нормальный возврат, иначе - вылет по exception. Этот exception будет проанализирован внешней процедурой, которая сама решит, куда чего писать, и что делать дальше. Возвращать код я не хочу - во-первых, вся прога написана на exceptions, во-вторых, можно предположить появление других проверок с другими ответными действиями, так что простым да/нет можно не обойтись.
Проблема: exception определённый во внутренней процедуре не виден во внешней. Т.о. я не могу написать raise PAYS_INCONNU во внутренней проге и EXCEPTIONS WHEN PAYS_INCONNU во внешней. Приходится ловить по WHEN OTHERS. Работает, конечно, но некрасиво.
Была идея определить exception во внешней проге и передать параметром во внутреннюю - уродство.
Пока пришла в голову мысль отказаться от именованных exceptions и выкидывать обычное, с неким кодом, по которому потом проверять снаружи. Не очень нравится, нечитаемо.
Да, в oracle я чайник, у нас просто все dba спецы по db2, поэтому можете предполагать, что я не знаю базовых вещей. Я про существование exceptions узнал, разбирая код :-)
no subject
Date: 2005-09-26 04:32 pm (UTC)no subject
Date: 2005-09-26 04:36 pm (UTC)no subject
Date: 2005-09-27 07:45 am (UTC)Я когда Лёше Долганову по этому поводу позвонил, он именно к тебе меня направил :-)
no subject
Date: 2005-09-27 08:05 am (UTC)no subject
Date: 2005-09-27 08:45 am (UTC)no subject
Date: 2005-09-27 09:15 am (UTC)Короче, для "ремонта на лету" штука обоюдоострая. Но в стабильном виде (все отлажено, все работает) - это очень хорошая фича.
Я сейчас уже смутно помню, и боюсь сказать глупость, в последних разработках на Оракле, что я делала, пэкаджи не использовались по другим причинам. Поэтому не хочу тебя décourager, если создать в пэкадже только конкретные эксепшены, список которых стабилен и не будет меняться, то вполне симпатичное решение.
no subject
Date: 2005-09-27 09:34 am (UTC)no subject
Или всегда вставлять страну перед эмиттером, на всякий случай. В предположении, что она есть среди параметров.
no subject
Date: 2005-09-26 04:45 pm (UTC)no subject
Date: 2005-09-26 04:47 pm (UTC)no subject
Date: 2005-09-26 04:53 pm (UTC)Я видела код, в котором стояло WHEN OTHERS NULL, а хозяйка кода удивлялась, почему ее процедура не работает, хоть и не ругается !
no subject
Date: 2005-09-27 07:48 am (UTC)no subject
Date: 2005-09-26 05:00 pm (UTC)no subject
Date: 2005-09-27 07:51 am (UTC)no subject
Date: 2005-09-27 07:53 am (UTC)no subject
Date: 2005-09-27 04:40 am (UTC)Я только хочу опровергнуть утв "Проблема: exception определённый во внутренней процедуре не виден во внешней".
Если юзать пакет какой нить, то оттедова усе видать. Рабочий пример тут сварганил:
CREATE OR REPLACE PACKAGE exc_test_pkg
IS
exc_test_name exception;
PRAGMA EXCEPTION_INIT(exc_test_name, -20030);
END;
/
CREATE OR REPLACE procedure test_exc_server is
begin
dbms_output.put_line('test_exc_server');
raise exc_test_pkg.exc_test_name;
end;
/
CREATE OR REPLACE procedure test_exc_client is
begin
dbms_output.put_line('test_exc_client before test_exc_server exception');
test_exc_server;
dbms_output.put_line('test_exc_client after test_exc_server exception');
exception
when exc_test_pkg.exc_test_name then
dbms_output.put_line('exc_test_name raised, he-he');
end;
/
-------------------------------
А терь тестим:
conn user/password@tns_name; -- if you need it
set serveroutput on;
BEGIN
TEST_EXC_CLIENT;
COMMIT;
END;
/
---------------------------
My output result:
test_exc_client before test_exc_server exception
test_exc_server
exc_test_name raised, he-he
--=====================================================
Я думаю, ты сам догадался давно, прост решил вспомнить старое, тряхнуть этим, самым )
no subject
Date: 2005-09-27 07:56 am (UTC)no subject
Date: 2005-09-27 01:29 pm (UTC)Не грозит особо ничем :)
Date: 2005-09-28 12:44 am (UTC)Согласен, что пакеты - не идеальная хренька, особенно для горяченьких приклад, но для твоего конкретного случая - нормальное решение. Вроде :). Потом ногами не бить!!!!!
Сам я юзаю именованные, чтоб потом легче разбираться было, откуда ноги у бага растут. Залез по ссылке выше, просто копирую(мы сами писать не умеем :):
Associating a PL/SQL Exception with a Number: Pragma EXCEPTION_INIT
To handle error conditions (typically ORA- messages) that have no predefined name, you must use the OTHERS handler or the pragma EXCEPTION_INIT. A pragma is a compiler directive that is processed at compile time, not at run time.
In PL/SQL, the pragma EXCEPTION_INIT tells the compiler to associate an exception name with an Oracle error number. That lets you refer to any internal exception by name and to write a specific handler for it. When you see an error stack, or sequence of error messages, the one on top is the one that you can trap and handle.
You code the pragma EXCEPTION_INIT in the declarative part of a PL/SQL block, subprogram, or package using the syntax
PRAGMA EXCEPTION_INIT(exception_name, -Oracle_error_number);
where exception_name is the name of a previously declared exception and the number is a negative value corresponding to an ORA- error number. The pragma must appear somewhere after the exception declaration in the same declarative section, as shown in the following example:
DECLARE
deadlock_detected EXCEPTION;
PRAGMA EXCEPTION_INIT(deadlock_detected, -60);
BEGIN
... -- Some operation that causes an ORA-00060 error
EXCEPTION
WHEN deadlock_detected THEN
-- handle the error
END;
====================================================