2017-12-22 11 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トリガに使用されるコードであります入力されたusernameおよびemailがすでに使用されているかどうかを確認します。コードはうまくコンパイルされますが、emailまたはusernameと入力するとerror 01403が表示され、NO_DATA_FOUND exceptionを処理する必要があることが示されます。 私のコードでこれをどうやって行うことができますか?私は2つの条件(クエリ)が処理される必要があり、どのようにわからないのでスタックされています。どんな助けもありがとう。

答えて

0

あなたが興味を持っているのは、 "Firstname"(さまざまな条件 - ユーザ名とメールで1回)を取得するSELECT文です。

一つのアプローチは、MAXとして、集約関数を使用することです:

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

、それはNO-DATA-FOUNDは発生しません。

ただし、これはちょうどいいえの回避策です。正しいアプローチは、例外を適切に処理することです。 @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-EXCEPTION-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.パスワードが同じで、複雑さの規則を満たしていることを検証します。