2014-12-19 2 views
0

방아쇠 안에 사용자를 만들 수 있는지 궁금합니다. 내 코드가 구문 상 올바르다 고 생각 되더라도 오류가 발생합니다. 여기트리거 내에서 사용자를 만들 수 있습니까?

는 그래서이 작업을 수행 할 수 코드

CREATE OR REPLACE TRIGGER addUser 
BEFORE INSERT 
ON PLSQL_TEST_USERS 
FOR EACH ROW 
DECLARE 
    n VARCHAR2(20) := :new.name; 
    p VARCHAR2(20) := :new.password; 
BEGIN 
    dbms_output.put_line(n); 
    EXECUTE IMMEDIATE ('CREATE USER n IDENTIFIED BY p'); 
END; 
/

입니까?

는 여기에 내가 점점 오전 오류입니다 :

INSERT INTO PLSQL_TEST_USERS VALUES (1, 'rob', 'asdf')
Error report -
SQL Error: ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SYSTEM.ADDUSER", line 6
ORA-04088: error during execution of trigger 'SYSTEM.ADDUSER'
04092. 00000 - "cannot %s in a trigger"
*Cause: A trigger attempted to commit or rollback.
*Action: Rewrite the trigger so it does not commit or rollback.

답변

4

아니, 정확하게이 작업을 수행 할 수 없습니다.

트리거 내에서 커밋 할 수 없습니다 (일반적으로 아래 예외에 대해 설명합니다). CREATE USER과 같은 DDL은 DDL을 트리거에 넣을 수 없도록 두 개의 암시 적 커밋 (문 앞에 하나와 문 뒤에 하나)을 발행합니다.

자율 트랜잭션을 사용하도록 트리거를 선언하면 트리거 내부 커밋에 대한 규칙의 예외가 발생합니다. 그러나 이것은 몇 가지 이유로 문제를 올바르게 해결하지 못합니다. 먼저, 자율 트랜잭션은 이름에서 알 수 있듯이 자율적이므로 트리거하는 명령문이 롤백 되더라도 커밋됩니다. 즉, INSERT 문이 행을 성공적으로 삽입했지만 해당 변경 사항이 롤백되면 자치 트랜잭션이 커밋 된 상태로 유지되므로 사용자가 생성되지만 결국 plsql_test_users 테이블에 행이 없습니다. 쓰기 일관성을 위해 Oracle은 내부적으로 두 번 실행되는 명령문을 내부적으로 롤백하고 다시 실행할 수 있습니다.이 명령문은 사용자가 이미 존재하기 때문에 실패합니다. 자발적 트랜잭션은 실제로 기본 변경 작업이 성공했는지 여부에 관계없이 정보를 기록하려는 경우에만 사용해야합니다 (예 : 로그인 시도 또는 로그인 변경 시도로 로그인 또는 비밀번호 변경 실패로 인해 공격을 탐지 할 수 있습니다. 데이터의 상태).

dbms_job.submit 트리거를 호출하여 명령문이 커밋 된 후 곧 실행되는 백그라운드 작업을 제출하여 실제로 사용자를 생성 할 수 있습니다. 테이블에 추가되는 행과 생성되는 사용자 사이에 약간의 지연이 발생하지만 적어도 트랜잭션 적으로는 정확합니다 (생성하려는 사용자의 수와 백그라운드의 수와 같은 요소에 따라 지연이 커질 수 있습니다. 허용하는 작업). 아쉽게도 최신 dbms_scheduler 패키지 대신 이전 dbms_job 패키지를 사용해야합니다. 최신 패키지에 암시 적 커밋이 포함되어 있기 때문에 작업을 제출해야합니다.

백그라운드 작업 경로를 종료 한 경우 EXECUTE IMMEDIATE에 전달 된 명령문은 동적 SQL 문 실행시 해당 변수가 범위에 있지 않은 로컬 변수의 값을 참조 할 수 없습니다. 당신이

EXECUTE IMMEDIATE 'CREATE USER n IDENTIFIED BY p'; 

np 당신이 정의한 지역 변수를 참조하지 않는 쓸 때, 그들은 문자 그대로의 식별자입니다. 이렇게하면 단일 문자 암호 "p"로 사용자 "n"이 생성됩니다. 테이블의 사용자 이름과 암호를 사용하려는 경우 동적 SQL 문을 어셈블하는 동안이를 사용해야합니다. 뭔가 같은 것

EXECUTE IMMEDIATE 
    'CREATE USER ' || :new.name || 
    ' IDENTIFIED BY ' || :new.password; 

그리고이 모든 것이 왜 두 곳에서 정보를 저장하려고하는지 궁금해합니다. 오라클 사용자이기도 한 많은 사용자 이름 & 암호를 가진 테이블 plsql_test_users을 갖고 싶지는 않을 것 같습니다.오라클이 인증을 처리하기를 원하거나 애플리케이션이 인증을 처리하도록하려는 경우 각각이 인증을 처리한다고 생각하지 않아도됩니다 (예를 들어, 비밀번호가 변경되면 어떻게되는지). 응용 프로그램이 인증을 처리하려면 암호 (또는 암호화 된 암호)를 저장하지 마십시오. RAW 열에 소금으로 암호 해시를 저장합니다. 그런 다음 사용자가 로그인 할 때 암호를 제공하고 해시를 비교할 때 해시를 계산하고 확인합니다.

관련 문제