2014-04-10 3 views
0

데이터베이스에 대한 간단한 기능이 무엇인지 연구 중입니다.Oracle DBMS INSERT 프로 시저가 작동하지 않습니다.

사용자가 내 애플리케이션에 등록 할 때 필드 password_changed이 0으로 초기화되면 user trigger 아래의 메소드를 실행하여 새 사용자에게 비밀번호를 업데이트해야한다는 메시지를 보내려합니다.

CREATE OR REPLACE TRIGGER trg_users 
BEFORE INSERT OR UPDATE ON users FOR EACH ROW 
BEGIN 
    -- Get the new user id 
    IF :NEW.user_id IS NULL THEN 
     SELECT seq_user_id.nextval 
     INTO :NEW.user_id 
     FROM sys.dual; 
    END IF; 

    -- Alert a user that they need to change their password 
    IF :NEW.pass_changed IS NULL THEN 
     :NEW.pass_changed := 0; 
     send_alert(:NEW.user_id, 'Thank-you for registering, please change your password for security reasons!'); 
    END IF; 
END; 

이 첫 번째 트리거가 단순히 암호가 0로 설정을 처음 상태 다음 내 순서에 의해 채워 가져옵니다 :NEW.user_id을 복용, 내 send_alert() 함수를 호출합니다.

send_alert() 절차 :이 코드를 실행하면

-- Sends an alert to the user noting that they haven't changed their password 
CREATE OR REPLACE PROCEDURE send_alert( 
    this_user users.user_id%TYPE, 
    this_message STRING 
) 
AS 
BEGIN 
    INSERT INTO messages 
    VALUES('', this_user, getSystemId(), 'ALERT', this_message, '', ''); 
END send_alert; 

, 나는 오류가 integrity constraint (PRCSE.INBOX_MESSAGE_TO_FK) violated - parent key not found 나는 이것이 무엇을 의미하는지 이해 - 나는 그 필드를 대체 할 경우 부모 키의 값이, this_user을 통해 채워야하지만 프로 시저가 완료 한 기존 값과 이전 사용자의 경우 INSERTS.

어떤 이유로 든 :NEW.user_id이 전달되지 않는다고 생각할 수 있지만 프로 시저를 호출하기 전에 값을 초기화합니다.

편집 10/04/14 그리니치 표준시 13시 48분가 : - 감사를, 알렉스 혼란을 지우려면, getSystem가()는 마스터 관리자 ID

-- Gets the ID of the SYSTEM user via its unique email 
CREATE OR REPLACE FUNCTION getSystemId 
    RETURN NUMBER 
IS 
    system_user users.user_id%TYPE; 
    pragma autonomous_transaction; 
BEGIN 
    SELECT user_id 
    INTO system_user 
    FROM users 
    WHERE user_email = '[email protected]' 
    AND user_permissions = 'ADMIN'; 
RETURN system_user; 
COMMIT; 
END getSystemId; 

어떤 도움을 주시면 감사하겠습니다을 반환합니다. 당신이 BEFORE 트리거 값을 삽입하려고하기 때문에

+3

어떻게 'AFTER INSERT' 트리거는? –

+0

사실상 해결책이었던 @OracleUser - 오라클 DB를 처음 접했기 때문에 지금이 특정 시나리오가 어떻게 해결되었는지 알게되어 기쁘다 - 감사합니다! :) – Alex

답변

2

이것은 (부모 행이 삽입됩니다 예를 들어, 전) :

SQL> create table t(x int primary key); 


SQL> create table t_c(x int references t(x)); 


SQL> create or replace trigger tr_i 
    2 before insert on t 
    3 for each row 
    4 begin 
    5 insert into t_c(x) values(:new.x); 
    6 end; 
    7/

SQL> insert into t values(1); 
insert into t values(1) 
      * 
error in line 1: 
ORA-02291: integrity constraint (SCOTT.SYS_C00330529) voilated - parent key not found 
ORA-06512: in "SCOTT.TR_I", line 2 
ORA-04088: error in trigger execution 'SCOTT.TR_I' 


SQL> create or replace trigger tr_i 
    2 after insert on t 
    3 for each row 
    4 begin 
    5 insert into t_c(x) values(:new.x); 
    6 end; 
    7/

SQL> insert into t values(1); 

1 row inserted. 

SQL> select * from t; 

    X                   
------                   
    1                   

SQL> select * from t_c; 

    X                   
------                   
    1  
+0

Ahh 내가 너무 바보라고 느낀다 - 나는 그것이 분명히하기 위해, 이전 트리거가 INSERT를하기 전에 모든 값을 준비한다는 점을 발견하지 못했다고 믿을 수 없다. 그래서 : NEW.user_id가 증가했다. 테이블에 아직 존재하지 않으므로 키가 위반 되었습니까? 도움을 주셔서 감사합니다. btw :) – Alex

+1

예, BTW에서는 DEFERRED 제약 조건을 사용할 수있는 이런 종류의 논리가 정말로 필요한 경우 - 예외적 인 경우가 아니지만 커밋 할 때까지 기다릴 때까지 기다릴 것입니다. 그러나 성능 저하와 같은 단점이 있습니다. –

+0

흥미 롭다. 나는 그것에 대해 읽을지도 모른다. 다시 도움을 주셔서 감사합니다. – Alex

관련 문제