2016-11-19 3 views
0

требования являетсяоракул Перед триггером на операции DML на одной таблице

  1. IF УДАЛЕНИЯ, любая запись создана в USER_INFO таблице не может быть удалена. Попытка удалить запись из этой таблицы будет захвачена, создайте запись в таблице AUDIT.
  2. IF вставляя, обязательные поля ID, LOGIN_USER

    • Перед установкой в ​​таблицу, проверить есть не существующая запись с тем же LOGIN_USER и статус записи в True.

    • Если это подтверждение не выполнено, введите код ошибки и сообщение об ошибке.

    • Когда запись вставлена ​​в таблицу, триггер после события будет срабатывать обновления следующих полей: ID с последовательностью, созданием текущей даты/время и действия «создание записи»

  3. ЕСЛИ ОБНОВЛЕНИЕ, Обязательные для заполнения поля ID, LOGIN_USER

    • при обновлении записи в таблице, триггер после события будет срабатывать выполнение следующих действий:

    O Вставить запись в текущих значений осуществляется таблица копирования полей.

    о следующих полей заполняются или переопределен со следующими значениями: Активного Ложными События «Аудит для обслуживания данных»

    • Триггера до события будет срабатывать и предотвратить неактивную запись от обновления.

    • Запись со статусом Active = False не может быть обновлена. Если это так, необходимо создать новую запись.

Я написал код, и он выполняет DELETE AND INSERT без каких-либо проблем.

Проблема с UPDATE, когда она попадает в блок UPDATING, INSERTS внутри блоков else; здесь запрос INSERT рекурсивно запускается блоком INSERTING. Это не должно выполняться, когда я хотел запустить только блок UPDATING.

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

CREATE OR REPLACE TRIGGER BEFORE_DML     
BEFORE DELETE OR INSERT OR UPDATE OF ID,LOGIN_USER ON USER_INFO 
REFERENCING NEW AS NEW OLD AS OLD    
FOR EACH ROW 

DECLARE 
    PRAGMA AUTONOMOUS_TRANSACTION;       
    V_USER   VARCHAR2 (30);   
    V_NODE   VARCHAR2 (50);   
    V_CNT   NUMBER := 0;  
    V_ACTIVE  VARCHAR2 (10);  

BEGIN   
    SELECT SYS_CONTEXT ('USERENV', 'IP_ADDRESS')   
    INTO V_NODE  
    FROM DUAL;  

    IF DELETING THEN  
     INSERT   
     INTO AUDIT (IDS,  
        ACTION,   
        IP_ADDRESS,   
        LOGIN,   
        CREATED   
        )   
      VALUES(AUDIT_SEQ.NEXTVAL,   
        'Deletion',   
        V_NODE,  
        SYS.LOGIN_USER,   
        SYSDATE  
        );   
     COMMIT;  
     RAISE_APPLICATION_ERROR (-20002, 'USER_INFO table data can not be deleted');  
    END IF; --Close IF for DELETING  

    IF INSERTING THEN    

     SELECT COUNT (1)   
     INTO V_CNT   
     FROM USER_INFO  
     WHERE LOGIN_USER = :NEW.LOGIN_USER   
     AND STATUS='TRUE';   

      IF (V_CNT >=1) THEN  
       RAISE_APPLICATION_ERROR (-20002, 'DATABASE LOGIN USER ALREADY EXISTS', TRUE);  
      END IF;  
       :NEW.ID  := DBLOGIN_SEQ.NEXTVAL;    
       :NEW.CREATED := SYSDATE;   
       :NEW.ACTION  := 'Record Creation' ;     
    END IF; --CLOSE IF FOR INSERTING   

    IF UPDATING THEN  

     IF :OLD.STATUS = 'INACTIVE'   
     THEN  
      RAISE_APPLICATION_ERROR (-20002, 'INACTIVE RECORDS CAN NOT BE UPDATED'); 
     ELSE IF :OLD.STATUS = 'FALSE' THEN  
       INSERT INTO USER_INFO(ID,  
            STATUS,   
            LOGIN_USER,   
            CREATED,   
            ACTION   
            )   
          VALUES(DBLOGIN_SEQ.NEXTVAL,  
            'INVALID',    
            :OLD.LOGIN_USER,    
            SYSDATE,   
            'FALSE RECORD UPDATED '   
            );   
       COMMIT;   
     ELSE  
      INSERT INTO USER_INFO(ID,   
            STATUS,   
            LOGIN_USER,    
            CREATED,    
            ACTION   
           )  
          VALUES(DBLOGIN_SEQ.NEXTVAL,    
            'FALSE',   
            :OLD.LOGIN_USER, --NEW.LOGIN_USER   
            SYSDATE,  
            'Audit for data maintenance'  
            ); 
      COMMIT;  
     END IF;            
    END IF;  
    END IF; --CLOSE IF FOR UPDATING    

END BEFORE_DML; 
/
+0

Это домашнее задание или вы пытаетесь решить проблему реального мира? Вы могли бы сделать что-то взломанное, если у вас есть пакет с общедоступной глобальной переменной 'in_before_dml_trigger', которую вы установили в своем блоке' update' и проверите в верхней части вашего триггера. Это решило бы ближайшую проблему, но это была королевская боль с точки зрения обслуживания и поддержки. Вы делаете что-то в триггере, который будет работать только в однопользовательской системе - уникальный индекс фактически обеспечит наличие только одной строки для 'login_user' в многопользовательской системе. –

+0

Спасибо. Этот подход правильный? – Hima

ответ

0

Один из способов - отключить триггер перед вашими вставками, а затем снова включить его. Пример:

execute immediate 'alter trigger [trigger_name] disable' 
+0

Я уверен, что вы не можете запустить DDL внутри триггера. –

+0

уверен, что вы можете .. с динамическим sql –

+0

Речь идет не о синтаксисе, а о том, что делает DDL.DDL неявно делает фиксацию, которая не разрешена в триггере. –

Смежные вопросы