Hurriyet

29 Ocak 2014 Çarşamba

PL/SQL: Exception - Hata Yönetimi - PL/SQL Debuging - Handling PL/SQL Errors - PL/SQL Debuging

PL/SQL procedure'lari içerisindeki run-time hataları dizayn yanlışlıkları, donanım bozuklukları veya kodlama hataları gibi bir sürü nedenden dolayı ortaya çıkmaktadır. Bütün olabilecek hataları tahmin edemesek de, karşımızı çıkabileceklerini düşündüğümüz hataları işleyebiliriz.

Eğer programımızda hata kontrolü yoksa programın çalışması durur ve programın kontrolü işletim sistemine döner. Hata kontrolü varsa da program hatalara rağmen devam edebilir.

Exception Nedir?

 PL/SQL'de bir warning veya error durumunun ortaya çıkması "exception" olarak tanımlanır. Exception'lar ya kullanıcılar tarafından ya da sistem tarafından tanımlanırlar. Kullanıcı tarafından tanımlanan hatalar "raise" ifadesiyle başlatılırlar.

Çıkan hataları yönetmek için exception blokları yazarız. Exception ortaya çıktığında çalışma durup o bloğu kapsayan exception bloğuna gider.

Aşağıdaki örneğimizde standart bir hata bloğu tanımlamaktayız. Bu hata bloğunda tarih bilgisi çekilip tarih tablomuzun tek sütununa ekleriz. Eğer hata olursa da o ifadeyi kapsayan begin bloğundaki exception kısmına giderek oradaki hatalar arasından arama yapar. Örneğimizdeki hata diğer bütün hataları kapsadığı için eğer hata çıkarsa hemen o kısma girer ve rollback eder.

 DECLARE  
   a date;  
 BEGIN  
   select sysdate into a from dual;  
   insert into tarih values(a);  
   COMMIT;  
 EXCEPTION   
   WHEN OTHERS THEN  
    ROLLBACK;  
 END; 

Önceden Tanımlı PL/SQL Exception'ları:

Sistem tarafından tanımlı hatalar ne zaman PL/SQL de bir hata olursa, o zaman tetiklenirler. Oracle hatalarının hepsinin bir hata numarası vardır; ancak bu hatalar adlarıyla kontrol edilirler.

Genel olarak ortaya çıkacak hataları "OTHERS" ifadesiyle kapsayabiliriz. Hatalar ortaya çıktığında SQLCODE ve SQLERRM fonksiyonları işimize yarayabilir. SQLCODE fonksiyonu SQL hata numarasını verirken, SQLERRM ise SQL hata mesajını vermektedir.

Ayrıca diğer adı olmayan hataları işlemek için  "pragma exception init" ifadesini kullanabiliriz. Aşağıdaki hatalar hata koduna tanımlı isim  verilmiş olan hatalardır.

ExceptionOracle Hata KoduSQLCODE Değeri

ACCESS_INTO_NULL

ORA-06530

-6530

CASE_NOT_FOUND

ORA-06592

-6592

COLLECTION_IS_NULL

ORA-06531

-6531

CURSOR_ALREADY_OPEN

ORA-06511

-6511

DUP_VAL_ON_INDEX

ORA-00001

-1

INVALID_CURSOR

ORA-01001

-1001

INVALID_NUMBER

ORA-01722

-1722

LOGIN_DENIED

ORA-01017

-1017

NO_DATA_FOUND

ORA-01403

+100

NOT_LOGGED_ON

ORA-01012

-1012

PROGRAM_ERROR

ORA-06501

-6501

ROWTYPE_MISMATCH

ORA-06504

-6504

SELF_IS_NULL

ORA-30625

-30625

STORAGE_ERROR

ORA-06500

-6500

SUBSCRIPT_BEYOND_COUNT

ORA-06533

-6533

SUBSCRIPT_OUTSIDE_LIMIT

ORA-06532

-6532

SYS_INVALID_ROWID

ORA-01410

-1410

TIMEOUT_ON_RESOURCE

ORA-00051

-51

TOO_MANY_ROWS

ORA-01422

-1422

VALUE_ERROR

ORA-06502

-6502

ZERO_DIVIDE

ORA-01476

-1476

Özetle yukarıdaki tanımlı hatalarımız olabileceğini öngörüyorsak "exception when ..... then" boşluğuna o tanımlı hata ismini vererek o hatayı işleyebiliriz.

PL/SQL Hatalarını Tanımlamak:

PL/SQL'de kendi hatalarımızı tanımlayabiliriz. Yukarıdaki hatalar dışında karşımıza çıkabilecek olanları kendimiz tanımlayarak bunların işlenmesini sağlayabiliriz. Bu hatalar değişken tanımlama kısmında tanımlanırlar. Örnek olarak aşağıdaki tanımı verebiliriz.

Declare
  hata exception;

PL/SQL Hatalarını Bir SQL Hata Numarasıyla Eşleştirmek: 

Hataların bir isimle eşleştirilmesi için "pragma exception_init(exception_ismi,-Oracle_hata_numarası;" şeklinde bir ifade kullanmalıyız.

 Declare  
  hata exception;  
  pragma exception_init(hata,-60);  
 Begin  
  --"hata"'ya neden olabilecek işlemler  
 Exception  
  When hata then  
  Rollback;  
 End;  

Yukarıdaki örnekte ORA-00060 olan deadlock hatası gerçekleştiğinde bu hatayı bize "hata" olarak bir uyarı diye gösterecektir.

Programda Kendi PL/SQL Hatalarımızı Yaratmak:

RAISE_APPLICATION_ERROR procedure'ı ile kendi ORA- hatalarımızı yaratabiliriz. Bu şekilde bir hata olmasa bile, bizim iş akışımıza uygun olmayan bir durum yakaladığımızda programı durdurup uygulamaya mesaj gönderebiliriz. Burada hata numarası olarak verebileceğimiz sayı -20000 ile -20999 arasında olabilir. Hata mesajı da 2048 bytes uzunluğunda olabilir.

 Declare  
    
 Begin  
  --"hata"'ya neden olabilecek işlemler  
 raise_application_error(-20001,'Dikkat!!');
 End;  

Yukarıdaki durumda program çalıştığında uyarı amaçlı bir ifade çalıştırmaktayız. İşlemlerimiz bir ORA hatasına neden olmasa da, kendimiz programımızı bu şekilde durdurabiliriz.

RAISE İfadesiyle Exception Üretmek:

Yukarıdaki başlığımızda nasıl exception üretebileceğimizi gördük. Bu exception işlemek istediğimizde "raise" ifadesini kullanabiliriz.  Bunun için ilk önce kendi hatamızı tanımlamamız gerekir.

DECLARE  
  stok_hatası exception;  
  stok number(5);  
 BEGIN  
   select sayı into stok from depo;  
   IF stok< 100 THEN  
    RAISE stok_hatası;  
   END IF;  
 EXCEPTION  
   WHEN stok_hatası THEN  
    raise_application_error(-20001,"Stok kalmamış durumdadır");  
 END;  

Örneğimizde ilk önce stok_hatası şeklinde hatamızı tanımlamaktayız. Sonra uygun zaman geldiği zaman eğer şartlar sağlanıyorsa stok_hatası şeklinde hatamız tetiklenir. Bu hata tetiklendiği zaman programın ne yapması gerektiğini exception bloğunda tanımlarız. Örneğimizde bunu raise_application_error procedure'u ile işlemekteyiz. Bu şekilde kısaca eğer hatayla karşılaşırsak bize "Stok kalmamıştır" şeklinde uyarı verecektir.

Bu şekilde kendi yarattığımız hatayı işlemiş oluruz.

Loop İçerisine Exception Tanımlamak:

Loop içerisine Exception tanımlama örneğimiz için aşağıdaki synoynm compile etme örneğimize bakabiliriz. Bu örnekte görebileceğimiz gibi exception tanımlayabilmemiz için, exception'ın ait olduğu bir begin end bloğu olmalıdır. Loop içerisinde begin.. end bloğu koyarak içeride yaşanabilecek herhangi bir hatanın farkında olabiliriz.

 declare  
 cursor a is select owner,object_name from dba_objects where object_type='SYNONYM' and status='INVALID' and owner!='PUBLIC';  
 z varchar2(100);  
 begin  
 for x in a  
 loop  
   
 begin  
 z:= 'alter synonym '|| x.owner || '.'|| x.object_name || ' compile;';  
 execute immediate z;  
 exception when others  
 then   
 dbms_output.put_line(SQLERRM || ' ' ||SQLCODE || ' ' || x.object_name);  
 end;  
 end loop;  
   
   
 end;  
 / 





Hiç yorum yok:

Yorum Gönder