powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Сгенерить низкоуровневую ошибку на базе программно возможно?!
9 сообщений из 9, страница 1 из 1
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #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
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #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
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #38782180
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CawaSPbmedoed,
Для приведённого триггера без превращения его в Compiled можно было бы использовать IF с предварительной проверкой селектом и вызовом ф-и RAISE_ERROR(...) или используя statement SIGNAL .

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

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

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

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

MERGE в данном случае - как раз тот инструмент, который идеально подходит к задаче.
Вы сами верите, в то что написали? Чем мне поможет merge при одновременной вставке да еще и в триггере!?
Я так понял все же первоначальный ответ на мой вопрос - отрицателен!
И даже Марк Баринштейн мне не в силах помочь, я прав Марк?
...
Рейтинг: 0 / 0
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #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
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #38783707
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>>anton.k
Спасибо за грамотный ответ. Код триггера попробую использовать!
Мне просто непонятно было, почему CawaSpb такие нелепые советы давал по контролю в триггере задвоений предварительным селектом?! Как к админу к нему претензий нет, но советы по предварительным селектов и merge в триггере - ни о чем!
Перед Антоном снимаю шляпу!
...
Рейтинг: 0 / 0
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #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
Сгенерить низкоуровневую ошибку на базе программно возможно?!
    #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
9 сообщений из 9, страница 1 из 1
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Сгенерить низкоуровневую ошибку на базе программно возможно?!
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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