2017-12-22 13 views
0

Oracle Forms 10g를 사용하여 양식을 작성하여 사용자를 db에 추가하는 GUI를 작성합니다.pl/sql에서 예외 처리

코드 : 모든 입력이 textboxes이 (어떤 작품) 작성하는 경우

declare 
    firstname VARCHAR(15); 
    lastname VARCHAR(15); 
    usernameee VARCHAR(15); 
    emailll VARCHAR(15); 
    pass1 VARCHAR(15); 
    pass2 VARCHAR(15); 
    v varchar2(200); 
begin 
    firstname := :HOMEADMIN1.TXTFIRSTNAME; 
    lastname := :HOMEADMIN1.TXTLASTNAME; 
    usernameee := :HOMEADMIN1.TXTUSERNAME; 
    emailll := :HOMEADMIN1.TXTEMAIL; 
    pass1 := :HOMEADMIN1.TXTPASSWORD; 
    pass2 := :HOMEADMIN1.TXTPASSWORD2; 

    if firstname is null or lastname is null or usernameee is null or 
     emailll is null or pass1 is null or pass2 is null then 
     message('Please fill all fields'); 
    else 
     select Firstname into v from Person where Username = usernameee; 
     if sql%found then 
      message('This username is already taken'); 
     else 
      select Firstname into v from Person where Email = emailll; 
      if sql%found then 
       message('This email is already taken'); 
      else 
       insert into Person values (PersonSeq.nextval,firstname,lastname,usernameee,pass1,emailll,0,1); 
       commit; 
      end if; 
     end if; 
    end if; 
end; 

이 코드 검사가, 다음은 확인해야합니다 다음은 내가 Add User 버튼에 when-button-pressed 트리거에 사용되는 코드입니다 입력 된 usernameemail이 이미 사용 된 경우 코드는 잘 컴파일되지만, email 또는 username을 입력하면 NO_DATA_FOUND exception을 처리해야 함을 나타내는 error 01403이 표시됩니다. 여기 내 코드에서 어떻게 할 수 있습니까? 내가 처리해야하는 2 가지 조건 (질의)을 가지고 있고 어떻게해야할지 모르기 때문에 나는 붙어있다. 어떤 도움을 주시면 감사하겠습니다.

답변

0

관심있는 라인은 "이름"을 가져 오는 SELECT 문입니다 (다른 조건 - 사용자 이름에 한 번, 이메일로 한 번).

한 가지 방법은 MAX 같은 집계 함수를 사용하는 것입니다 :

select max(Firstname) into v from Person where Username = usernameee; 

가 그렇게를, 그것은 NO-DATA는-발견 제기하지 않습니다.

그러나 이는 단지 멋진 해결 방법입니다. 올바른 접근법은 예외를 적절하게 처리하는 것입니다. @Littlefoot는 각 검증을 분할 할 수 제공하는 솔루션에 대한 대안으로

else 
    -- First, check whether USERNAME is taken: 
    begin 
    select firstname into v from person where username = usernameee; 

    -- You don't need IF SQL%FOUND because - if SELECT returned a value, you'll 
    -- get here anyway 
    message('This username is already taken'); 
    raise form_trigger_failure; --> this is Forms, isn't it? 

    exception 
    -- SELECT returned nothing and raised an exception 
    when no_data_found then 
     -- do nothing; proceed to EMAIL validation 
     null; 
    end; 

    -- Username is available (because previous RAISE didn't fire 
    begin 
    select firstname into v from person where email = emailll; 

    message('This email is already taken'); 
    raise form_trigger_failure; 

    exception 
    when no_data_found then 
     null; 
    end; 

    insert into person values (...); 
    commit; 
end if; 
+0

글쎄, "예외"로 "정상적인"동작 (행이없는 것으로 기본 설정)을 처리하는 것은 맛의 문제입니다. 따라서 나는 첫번째 해결책을 선호 할 것이다. –

+0

첫 번째 솔루션을 사용하려면 select 문 바로 뒤에있는 조건을 사용해야합니까? – RoyNasr

+0

MAX를 사용하면 초기 메시지에 게시 한 코드가 "있는 그대로"그대로 유지되며 변경 사항이 없습니다. MAX는 SELECT 문에만 추가됩니다. – Littlefoot

0

: 그렇게하기 위해서는 같은 자신의 BEGIN - 예외-END 블록으로 그 SELECT 문을 둘러싸해야합니다 그것은 자신의 별도 절차입니다. 메인 프로세스는 로직이 거의 없습니다. 요구 사항을 검증하고 요구 사항 예외를 삽입하거나 처리하십시오. 따라서 :

declare 
    -- internal exceptions 
    not_all_fields_entered exception; 
    user_name_already_taken exception; 
    email_already_taken  exception; 

    -- variables 
    firstname VARCHAR(15); 
    lastname VARCHAR(15); 
    usernameee VARCHAR(15); 
    emailll VARCHAR(15); 
    pass1 VARCHAR(15); 
    pass2 VARCHAR(15); 

    -- validaion routines 
    procedure validate_fields_entered 
    is 
    begin 
     if firstname is null or lastname is null or usernameee is null 
     or emailll is null or pass1 is null or pass2 is null 
     then 
      raise not_all_fields_entered; 
     end if; 
    end validate_fields_entered; 

    procedure validate_user_name_not_taken 
    is 
     user_name_count integer; 
    begin 
     select count(*) 
      into user_name_count 
      from Person 
      where Username = usernameee 
      and rownum < 2; 
     if user_name_count = 1 
     then 
      raise user_name_already_taken; 
     end if; 
    end validate_user_name_not_taken; 

    procedure validate_email_not_taken 
    is 
     email_use_count integer; 
    begin 
     select count(*) 
      into email_use_count 
      from Person 
      where Email = emailll 
      and rownum < 2; 
     if email_use_count = 1 
     then 
      raise email_already_taken; 
     end if; 
    end validate_user_name_not_taken;  

begin 
    firstname := :HOMEADMIN1.TXTFIRSTNAME; 
    lastname := :HOMEADMIN1.TXTLASTNAME; 
    usernameee := :HOMEADMIN1.TXTUSERNAME; 
    emailll := :HOMEADMIN1.TXTEMAIL; 
    pass1 := :HOMEADMIN1.TXTPASSWORD; 
    pass2 := :HOMEADMIN1.TXTPASSWORD2; 

    -- do validations 
    validate_fields_entered; 
    validate_user_name_not_taken; 
    validate_email_not_taken; 

    -- all good insert the row 
    insert into Person values (PersonSeq.nextval,firstname,lastname,usernameee,pass1,emailll,0,1); 

exception 
    when not_all_fields_entered then 
     message('Please fill all fields'); 
    when user_name_already_taken then 
     message('This username is already taken'); 
    when email_already_taken then 
      message('This email is already taken'); 
    when others then 
     log_error (....) ; 
     raise ; 
end; 

여기에 지정되지 않았지만 유지 관리를 생각합니다. 요구 사항이 다음과 같이 변경되는 경우 필요한 사항 : 1. 이메일의 형식이 올바른지 확인하지 않으면 올바른 것입니다. 2. 암호가 같고 복잡성 규칙을 충족하는지 확인하십시오.