Как создать триггер before или after, который может перехватывать DUP_VAL_ON_INDEX в Oracle PL / SQL

#oracle #plsql #oracle11g

#Oracle #plsql #oracle11g

Вопрос:

У меня есть такая таблица

 KD_C KD_PLA KD_T     GABUNG   BERAKHIR    GAJI_PL     BUYOUT
---- ------ ---- ---------- ---------- ---------- ----------
C001 MA001  T006       2003       2014      50000    5200000
C002 SC001  T006       2012       2016      65000   20280000
C003 TW001  T006       2005       2018      90000   46800000
C004 TV001  T006       2008       2017      60000   24960000
C005 PC001  T001       2003       2016      80000   24960000
C006 AC001  T001       1996       2014      90000    9360000
C007 DB001  T001       2010       2016      65000   20280000
C008 EH001  T001       2011       2018      85000   44200000
C009 JC001  T002       1996       2014      60000    6240000
C010 SG001  T002       1998       2016      87000   27144000
C011 LS001  T002       2010       2018      81000   42120000
C012 PR001  T002       2004       2016      60000   18720000
C013 JH001  T003       2005       2018      72000   37440000
C014 GC001  T003       2003       2015      65000   13520000
C015 ED001  T003       2010       2018     100000   52000000
C016 GB001  T003       2010       2016      80000   24960000
C017 DG001  T004       2011       2018      73000   37960000
C018 RG001  T004       1992       2014      90000    9360000
C019 PJ001  T004       2011       2018      80000   41600000
C020 RP001  T004       2012       2017      92000   38272000
C021 GB002  T005       2006       2018     102000   53040000
C022 EA001  T005       2011       2015      70000   14560000
C023 HL001  T005       2012       2018      65000   33800000
C024 KW001  T005       2009       2017      67000   27872000
C025 MA001  T005       2017       2022      50000   26000000
C028 MA001  T001       2016       2018      15000    3120000
C029 MA001  T001       2016       2018      15000    3120000
C030 MA001  T001       2016       2018      15000    3120000
 

А затем я попытался создать триггер для обновления вместо вставки в таблицу при дублировании первичного ключа. Первичный ключ — это первый столбец ‘KD_CONTRACT’.

 CREATE OR REPLACE TRIGGER INSERT_TABEL_CONTRACT
BEFORE INSERT ON CONTRACT
FOR EACH ROW
DECLARE
    KODE VARCHAR2(20);
    TEMPCARIKODE NUMBER;
BEGIN
    SELECT LPAD(TO_NUMBER(NVL(SUBSTR(MAX(KD_CONTRACT),2),0)) 1,3,'0') INTO KODE
    FROM CONTRACT;

    SELECT COUNT(KD_CONTRACT) INTO TEMPCARIKODE
    FROM CONTRACT
    WHERE KD_CONTRACT = :NEW.KD_CONTRACT;

    IF(TEMPCARIKODE = 0) THEN       
        :NEW.KD_CONTRACT := 'C'||KODE;
        :NEW.GABUNG := TO_NUMBER(TO_CHAR(SYSDATE,'YYYY'));
        :NEW.BERAKHIR := :NEW.GABUNG   :NEW.BERAKHIR;
        :NEW.BUYOUT := (:NEW.GAJI_PL * 52) * (:NEW.Berakhir-:NEW.Gabung) * 2;
    END IF; 
EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE('ERROR at Line 1:');
        DBMS_OUTPUT.PUT_LINE('ORA-20003: Data sudah ada, data akan diupdate!');
END;
/
show err;
 

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

он не показывает ошибки… Итак, триггер успешно создан. затем я попытался вставить дублированный первичный ключ. INSERT INTO CONTRACT VALUES('C001','MA001','T001',2013,2,15000,2500000);

результат

 INSERT INTO CONTRACT VALUES('C001','MA001','T001',2013,2,15000,2500000)
*
ERROR at line 1:
ORA-00001: unique constraint (TUGAS.PK_CONTRACT) violated
 

Он вызвал ORA-00001, но он никогда не касался DUP_VAL_ON_INDEX и ничего не показывал или настраиваемое сообщение.
У кого-нибудь есть идея? Когда он даже не касается DUP_VAL_ON_INDEX, как я могу вставить запрос на обновление в случае when…
Спасибо…
* в любом случае, мой oracle — XE или express edition.

Комментарии:

1. Код триггера не будет выдавать a dup_val_on_index , поэтому ваш обработчик исключений никогда не будет вызван. Проверка на нарушение ограничений полностью отделена от триггера. Если вы хотите перехватить ошибку, любой код, содержащий insert оператор, должен иметь обработчик исключений.

2. что вы хотите получить? На первый взгляд вы пытаетесь вставить значения с помощью inique KD_CONTRACT . Если я прав, более подходящим является использование последовательности.

3. @MichaelPiankov Ах, это ответ на мой вопрос.. Тогда я должен найти другой способ. Спасибо!

4. @BenyaminLimanto: если вопрос теперь бесполезен, пожалуйста, удалите его

Ответ №1:

EXCEPTION Блок из вашего триггера никогда не будет выполнен, поскольку ваш триггер не содержит никаких INSERT UPDATE операторов or. Вместо этого вы должны рассмотреть INSTEAD OF триггер.

Комментарии:

1. Хорошо. Могу ли я использовать вместо работы также с BEFORE On?