oracle在同一个表

时间:2016-11-19 22:35:38

标签: oracle plsql triggers

要求是,

  1. 如果删除,则不能删除在USER_INFO表中创建的任何记录。捕获尝试从此表中删除记录,在AUDIT表中创建一个条目。
  2. 如果INSERTING,必填字段为ID,LOGIN_USER

    •在插入表格之前,请确认没有具有相同LOGIN_USER的现有记录且记录状态为True。

    •如果此验证失败,请返回错误代码和指示失败的消息。

    •将记录插入表格后,事件后触发器将触发更新以下字段:带序列的ID,创建的当前日期/时间和操作“记录创建”

  3. 如果更新,必填字段为ID,LOGIN_USER

    •在表格中更新记录时,会触发事件后触发器执行以下操作:

    o将记录插入到受影响的表中,复制字段的当前值。

    o使用以下值填充或覆盖以下字段:         活跃的错误         事件“审计数据维护”

    •事件前触发器将触发并阻止更新非活动记录。

    •状态为Active = False的记录可能无法更新。如果是,则必须创建新记录。

  4. 我编写了代码,它执行DELETE AND INSERT没有任何问题。

    问题在于UPDATE,当它遇到UPDATING块,其他块内的INSERTS;这里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;
    /
    

1 个答案:

答案 0 :(得分:0)

一种方法是在插入之前禁用触发器,然后再次启用它。 例如:

execute immediate 'alter trigger [trigger_name] disable'