Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Сгенерить низкоуровневую ошибку на базе программно возможно?! / 9 сообщений из 9, страница 1 из 1
20.10.2014, 17:00
    #38782088
medoed
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
Добрый день, уважаемые знатоки!
В триггере вставляю данные и проверяю на уникальность (коряво, но по другому при текущей архитектуре никак):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE OR REPLACE TRIGGER DOC_ARGUMENTT.CONTROL_I 
  AFTER INSERT ON DOCUMENT.DOC_ARGUMENTT
  REFERENCING  NEW AS N FOR EACH ROW
    BEGIN ATOMIC 
                         DECLARE errMSG        varchar(250);
                         -- пробуем вставить запись в нашу таблицу, если будет ругачка значит нарушение уникальности (вторая запись)
                         INSERT INTO DOCUMENT.CONTROL (ID_DOCUMENT,NUMDOC,ID_TYP)  -- есть уникальный индекс на 3-ри поля
                         values (N.ID_DOCUMENT,N.NUMDOC, (select id from TYPE.DOCUMENTT as TYP where TYP.ID = N.ID_DOCUMENT )
                                  ); 
      END;



Можно ли как то перехватить ошибку и выдать уже нормальное предупреждение:
что типа: Нарушение уникальности при вставку в таблицу: DOCUMENT.DOC_ARGUMENTT

Я подобную задачу помню пытался сделать на MSSQL-2008, не получилось- типо слишком низкоуровневая ошибка!
Осилит ли такое DB2? (Windows, DB2-9.7).
...
Рейтинг: 0 / 0
20.10.2014, 18:00
    #38782142
CawaSPb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
medoed,

Можно, если использовать не Inlined, а Compiled compound SQL.

Для триггеров, процедур и функций это определяется использованием BEGIN ... END вместо BEGIN ATOMIC ... END.
В Compiled коде можно использовать хэндлеры для перехвата событий.

Но надо при этом помнить, что такой триггер (возможность использовать compiled триггеры появилась возможность в 9-ке (9.7?)) будет работать совершенно по-другому и в значительной части ситуаций существенно медленнее.
Связано это с тем, что вместо просто выполнения общего плана запроса (с интегрированным туда кодом триггера) будут делаться реальные вызовы в Procedure Virtual Machine (PVM) для исполнения кода триггера.

Для приведённого триггера без превращения его в Compiled можно было бы использовать IF с предварительной проверкой селектом и вызовом ф-и RAISE_ERROR(...) или используя statement SIGNAL .

А ещё лучше - просто statement MERGE с интегрированным SIGNAL на WHEN MATCHED (см. последний пример).
...
Рейтинг: 0 / 0
20.10.2014, 18:33
    #38782180
medoed
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
CawaSPbmedoed,
Для приведённого триггера без превращения его в Compiled можно было бы использовать IF с предварительной проверкой селектом и вызовом ф-и RAISE_ERROR(...) или используя statement SIGNAL .

А ещё лучше - просто statement MERGE с интегрированным SIGNAL на WHEN MATCHED (см. последний пример).
Нет, это невозможно (предварительный select)!
Вы не предусмотрели одновременную вставку, в триггере нельзя сделать select с with ur.
Поэтому проверку перед вставкой не реализовать (есть две одинаковы незакоммиченные записи)!
...
Рейтинг: 0 / 0
20.10.2014, 20:02
    #38782231
CawaSPb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
medoed,

Ну, не то, чтобы уж совсем не подходит.
Встаёт вопрос сериализации доступа к изменению данных таблицы, который можно реализовать различными способами, не только чтением в режиме RR . Но, действительно, вариант не к месту.

MERGE в данном случае - как раз тот инструмент, который идеально подходит к задаче.
...
Рейтинг: 0 / 0
21.10.2014, 10:19
    #38782509
medoed
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
CawaSPbmedoed,

Ну, не то, чтобы уж совсем не подходит.
Встаёт вопрос сериализации доступа к изменению данных таблицы, который можно реализовать различными способами, не только чтением в режиме RR . Но, действительно, вариант не к месту.

MERGE в данном случае - как раз тот инструмент, который идеально подходит к задаче.
Вы сами верите, в то что написали? Чем мне поможет merge при одновременной вставке да еще и в триггере!?
Я так понял все же первоначальный ответ на мой вопрос - отрицателен!
И даже Марк Баринштейн мне не в силах помочь, я прав Марк?
...
Рейтинг: 0 / 0
21.10.2014, 17:58
    #38783328
anton.k
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
medoedВы сами верите, в то что написали? Чем мне поможет merge при одновременной вставке да еще и в триггере!?
Я думаю вы правы, без повышения уровня изоляции MERGE в этом случае не поможет, поскольку MERGE - операция не атомарная и в промежутке между OUTER JOIN'ом и UPSERT'ом данные в целевой таблице могут измениться, так что при попытке добавить запись с уже существующим уникальным ключом UPSERT может закончится все той же SQL0803N, которую вы и пытается отловить.

medoedЯ так понял все же первоначальный ответ на мой вопрос - отрицателен!
Ну, не совсем :) Вам уже пояснили, что вместо инлайн триггера вы можете использовать компилируемый, который поддерживает объявление обработчиков исключений, если только по каким-то причинам компилируемые триггеры вам не подходят (например, скорость выполенния триггера является критическим фактором в работе вашего приложения).

Например так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
create table emp (id int not null primary key, name varchar(10) not null) organize by row
DB20000I  The SQL command completed successfully.

create table emp_hist(name varchar(10) not null, operation varchar(10) not null) organize by row
DB20000I  The SQL command completed successfully.

alter table emp_hist add unique (name, operation)
DB20000I  The SQL command completed successfully.

create or replace trigger emp_after_trig 
after insert on emp
referencing new as n for each row
begin 
  declare exit handler for sqlstate value '23505'
    signal sqlstate '75000' 
       set message_text = 'Unique key violation: emp_hist';--

  insert into emp_hist values (n.name, 'insert');--
end
DB20000I  The SQL command completed successfully.

insert into emp values (1, 'Joe')
DB20000I  The SQL command completed successfully.

insert into emp values (2, 'Joe')
DB21034E  The command was processed as an SQL statement because it was not a 
valid Command Line Processor command.  During SQL processing it returned:
SQL0438N  Application raised error or warning with diagnostic text: "Unique 
key violation: emp_hist".  SQLSTATE=75000



Кстати, не занудства ради, а во имя математичекой точности, небольшое уточнение по поводу PVM:
CawaSPb ...реальные вызовы в Procedure Virtual Machine (PVM) для исполнения кода триггера.

PVM - это акроним от PSM Virtual Machine, а что такое PSM - все итак прекрасно знают :) А переключение контекста между классическим DB2 рантаймом и PVM происходит, да, что привносит дополнительные накладные расходы и существенно влияет на производительность выполнения запросов, как уже справедливо заметил уважаемый CawaSPb.
...
Рейтинг: 0 / 0
22.10.2014, 10:14
    #38783707
medoed
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
>>anton.k
Спасибо за грамотный ответ. Код триггера попробую использовать!
Мне просто непонятно было, почему CawaSpb такие нелепые советы давал по контролю в триггере задвоений предварительным селектом?! Как к админу к нему претензий нет, но советы по предварительным селектов и merge в триггере - ни о чем!
Перед Антоном снимаю шляпу!
...
Рейтинг: 0 / 0
22.10.2014, 17:53
    #38784483
может_так
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
medoed,

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CREATE OR REPLACE TRIGGER trg_1 AFTER INSERT
ON ...... FOR EACH STATEMENT
CALL my_procedure
@
...
PROCEDURE my_procedure
IS
    check_result boolean;
BEGIN
    ...
    LOOP
        --checking--
        IF NOT check_result THEN
            ...
            raise_application_error( -20000, 'Your message'); 
        END IF;
    END LOOP;
END;



p.s. это делалось на 9.7.5 при включенной совместимости с ora
...
Рейтинг: 0 / 0
22.10.2014, 18:48
    #38784536
medoed
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сгенерить низкоуровневую ошибку на базе программно возможно?!
может_такmedoed,

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

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CREATE OR REPLACE TRIGGER trg_1 AFTER INSERT
ON ...... FOR EACH STATEMENT
CALL my_procedure
@
...
PROCEDURE my_procedure
IS
    check_result boolean;
BEGIN
    ...
    LOOP
        --checking--
        IF NOT check_result THEN
            ...
            raise_application_error( -20000, 'Your message'); 
        END IF;
    END LOOP;
END;



p.s. это делалось на 9.7.5 при включенной совместимости с ora

Ну мне в триггере хотелось просто проверять. А писать процедуру для проверки возможно наверное, но громоздо это и не уверен что уровень изоляции там не проигнорится. Мне ответ Антона по душе, возможно завтра попробую...
...
Рейтинг: 0 / 0
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Сгенерить низкоуровневую ошибку на базе программно возможно?! / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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