ORACLE PL/SQL OBJECT TYPE 6 SELECT * FROM TABLE(

Söz ve ibareler, dinleyenler topluluğu için azık mesabesindedir.

Senin o azıktan nasibin ancak yediğin kadarıdır –İbni Arabi

 

Merhaba Arkadaşlar
object oriented programming oracle makalemize devam ediyoruz. (Bu işi sevdim, Yazıp duruyorum)
Bu makalemizde, bir object type oluşturacağız, bu object type”ı referans alan bir type list oluşturacağız.
Bir function ile bu listeyi doldurup geri donmesini saglayacagiz.
Bunun bize ne avantajı olacak peki:
cevap: bu function”ı tablo gibi kullanıp, select sorguları icerisine alabilecegiz;
bu sayede tablo veya view gibi dinamik bir kullanım saglayacak.
Sözü fazla uzatmadan; bunların nasıl yapılacağını anlatalım.
Önce type”ımızı create ediyoruz.

--
--
create or replace type t_key_value as object 
(
  key         varchar2(1000),
  value       varchar2(4000),
  type        varchar2(100),
  constructor function t_key_value(key varchar2, value varchar2) return self as result
);
/
--
--

type”ın body kısmını create ediyoruz. ve default constructor tanımlayıp,
cumartesi ve pazar günlerini tatil diye işaretlemesini saglayacagiz.

--
--
create or replace type body t_key_value is
  constructor function t_key_value(key varchar2, value varchar2) return self as result is
  begin
  
    if key in (6, 7) then
      self.type := 'Tatil';
    else
      self.type := 'İş Günü';
    end if;
    
    self.key   := key;
    self.value := value;
    return;
  end;
end;
/
--
--

Type”ımızı referans alan object type list tanımlamasını da yapalım.

--
--
create or replace type t_key_value_list as table of t_key_value;
/
--
--

evet artık isi yapacak function”ı da olusturalım.
kodun icine comment yazarak her satırı acıklamaya özen gösteriyorum.

--
--
create or replace function getKeyValueList return t_key_value_list is
  v_kv      t_Key_Value; -- oncelikle type degiskenimizi tanımlıyor
  v_kv_list t_key_value_list := t_key_value_list(); -- key value type'ının listesini olusturmustuk onu tanımlıyoruz
  v_day     varchar2(10) := null; -- gunlerin isimlerini tutabilmek icin ayrı bir degisken tanımladık case fonksiyonu ile buna deger atayacağız
begin
  -- WRITE TYPE
  -------------------------------------------------
  -- Yedi kez donecek bir for döngüsü oluşturuyoruz
  --dbms_output.put_line('------ Deger Atama  ------');
  for r in 1 .. 7 loop
    ------------------------
    -- gelen degere gore gunun ismi ilgili degiskene atilacak
    case r -- r for dongusundeki donus degerini alır o yüzden ayrıca bir degisken tanımlamaya gerek yok
      when 1 then
        v_day := 'PAZARTESI';
      when 2 then
        v_day := 'SALI';
      when 3 then
        v_day := 'CARSAMBA';
      when 4 then
        v_day := 'PERSEMBE';
      when 5 then
        v_day := 'CUMA';
      when 6 then
        v_day := 'CUMARTESI';
      when 7 then
        v_day := 'PAZAR';
      else
        v_day := null; -- olmaz ama her zaman siz kodunuzu yazarken ELSE'yi düşünün ve yazın...
    end case;
    ------------------------
  
    -- oncelikle type degiskenimi dolduruyoruz....  
    /*
    v_kv.key   := r;
    v_kv.value := v_day;
    */
    -- constrotur devreye girsin diye new kewwordunu kullandim... 
    -- yukarıdak remark'ladıgım gibi kullansak ve declare kısmında initialize etseydik bu asamada constructor devreye girmezdi. 
    -- ilk ne zaman initialize edildiyse, constructor o zaman devreye girer.
    v_kv := new t_Key_Value(r, v_day);
    ------------------------
    -- object type listimizi extend edip, içine type basacağız. 
    v_kv_list.extend;
    v_kv_list(v_kv_list.count) := v_kv; -- index vererek type'ı refere ediyoruz.
    ------------------------

  end loop;

  -- buraya kadar type'ı doldurduk ve type list'imize bu type'ları ekledik.
  -- bundan sonra artık; olusturdugumuz type list'i function'dan geri donecegiz
  return v_kv_list;


end getKeyValueList;
/
--
--

 

tanımlamalarımız tamam. Artık bunları kullanalım. Buyurun size bir kaç tane örnek. Bundan sonrasını sizin haya gücüne bırakıyorum. istediğiniz gibi kullanın…

Capture

--
-- diğer bir kullanım 

select * from table(getKeyValueList) a where a.type='İş Günü';

select * from table(getKeyValueList) a where a.type='Tatil';
--
--

 

Selam ve Dua ile…

@Cevheri

 

 

ORACLE PL/SQL – OBJECT TYPE – 5 USING INSERT INTO

Hırsı bırak, kendini boş yere harcama.
Şu toprak altında çırak da bir, usta da –Mevlana

Merhaba Object Oriented Oracle yazımıza devam ediyoruz.

Bu yazımızda, object type’ları tabloya veya tablonun column’larına referans verme ve buralara, kayıt ekleme ile ilgili çok güzel örnekler yapacağız. Program yazarken oluşturduğunuz ve kullandığımız tipleri, hiç bir tip dönüşümüne sokmadan, olduğu gibi veritabanına kaydedip, okumaya başlayınca, Objelerle çalışmanın lezzetini tadacaksınız.

Öncelikle personType ve personInventory diye iki tane obje oluşturuyorum. birinde personel bilgileri, diğerinde, personel envanter bilgileri. Personel ve Envanter içeriği(özelliği) çok sık değişmeyeceği için, tüm ihtiyaç olacak alanlar oluşturup, bunları column tipi olarak vereceğiz.

Tip ve tablomuzu oluşturalım.

Person Bilgileri Object Type:

-- person icin uygun object type oluşturulur..
create or replace type personType as object
(
  firstname varchar2(100),
  lastname  varchar2(100),
  mail      varchar2(100),
  phone     varchar2(20)
)
;
/

Person Envanter Bilgisi Object Type:

-- personel envanteri icin uygun type oluşturulur.
create or replace type personInventory as object
(
  inventoryname varchar2(100),
  inventorytype varchar2(20)
);
/

Şimdi de bu type’ları referans alan tablomuzu oluşturalım:

-- person icin tabloyu object type'larımızla create ediyoruz
-- direk o tipleri insert edeceğiz.
create table personTab (
person       personType,
invontory    personInventory
);

Eveet yukarda gördüğünüz gibi; tablomuzun iki kolonu var; ama içlerinde onlarca, yüzlerce özellik olabilir. Peki güzel, iyi be kardeşim bunu biz nasıl kullanacağız, hadi, insert ve select deneyelim.(sanki okuyanlar hiç select-insert bilmiyor ya…)

insert into personTab values (
personType('Ali','Sormaz','ali@sormaz.com','02122122112'),
personInventory('Bilgisayar', 'TEKNIK')
);

insert into personTab values (
personType('Veli','Yormaz','veli@yormaz.com','3122122112'),
personInventory('Paspas', 'TEMIZLIK')
);

commit;

Evet dediğiniz gibi insertin hiç farkı yok, aslında şuna benzer : insert into table_name select * from filanca_table;

son bombamızı patlatıp, select sorgumuzu da yazıyoruz…………

Capture

Sorgu sonucuna dikkat ettiyseniz, bir kişinin adını çekmek istiyorsak = personTab.Person.Firstname şeklinde bir tree yapısı kuracağız. bu tree yapısı istediğiniz kadar içeri gidebilir.

Object Type’ların tablolarla ilişkisini inceleyemeye çalıştık; bu konuda makalelerimiz devam edecek. Dilimiz döndüğünce, parmaklarımız yazdığınca bu konuları anlatmaya çalışacağız.

Selam ve Dua ile…

 

ORACLE PL/SQL – OBJECT TYPE – 4 USING INHERITANCE

Misafirsin Bu Hanede Ey Gönül,
Umduğunla Değil , Bulduğunla Gül..
Hane Sahibi Ne Derse O Olur,
Ne Kimseye Sitem Eyle , Ne de Üzül –Mevlana

Merhaba Dostlar

Object – Oriented Oracle konumuzun dördüncü makalesindeyiz. Bu makalede sizlere, OOP programlamanın olmazsa olması inheritance (kalıtım, miras alma) özelliğinin plsql de nasıl kullanılacağını anlatacağım. Buraya kadar anlattığımız makaleler daha basic konulardı, artık object type’ın enterprise özelliklerini incelemeye başlıyoruz.  Burada OOP nin inheritance özelliğini açıklamaya kalkmayacağım. bunu bildiğinizi varsayıyorum. (Buradan inceleyebilirsiniz)

Bu yazımda, mesaj yapısı kurdum. bir BaseMessage type’ım var. Bu type bir mesaj’da olmazsa olmaz özellikleri(en base) barındıracak; ancak bundan, hata mesajı ve başarılı mesaj gibi iki tane daha type türeteceğiz. Base type’ta print diye bir metod var, doldurulan mesaj içeriklerini ekrana yazdıran metod. bu metodu, hem başarılı mesaj, hemde hata mesajlarına tek tek yazmıyoruz. Base type’ta yapmamız yeterli.

Miras alma UNDER keywordü ile yapılmaktadır. aşağıda örneğimizde görülecektir.

Şimdi objelerimi create edelim sırasıyla

Önce Base Type’ı create edelim. İçinde iki tane constructor var.  Bu constructor’ların amacı, bu objeleri, istersek parametre vererek, istersekte, parametre vermeden çağrılabilmesini sağlamaktır.

SuccessMessage();

SuccessMessage(mesajkodu, mesajicerigi);

Not: create ederken force keywordunu kullandım. bunun amacı, bu objeyi referans alan başka objeler varsa, replace etmeye kalktığınızda uyarı verir. yani en alttaki oğul kaydı droplanmadan, üstteki obje değiştirilemez(spec tarafı). body kısmında böyle bir kısıt yok.

create or replace type BaseMessageType force as object
(
  Code    varchar2(20),
  Message varchar2(4000),
  constructor function BaseMessageType return self as result,
  constructor function BaseMessageType(p_code varchar2, p_message varchar2) return self as result,
  member procedure print
)
not final -- Miras alınabilecek bir type oluşturmuş olduk
/

create or replace type body BaseMessageType is

  -- ilk deger ataması default degerler ile yapılıyor.
  constructor function BaseMessageType return self as result is
  begin
    self.Code    := '00000';
    self.Message := 'NULL';
    return;
  end;

  -- parametre olarak gelenler code ve message kısmına atanıyor
  constructor function BaseMessageType(p_code varchar2, p_message varchar2) return self as result is
  begin
    self.Code    := p_code;
    self.Message := p_message;
    return;
  end;
  member procedure print is
  begin
    dbms_output.put_line('Mesaj Kodu  :' || self.Code);
    dbms_output.put_line('Mesaj Icerik:' || self.Message);
  end;
end;
/

Başarılı Message Type’ı oluşturalım. code , message ve print özelliklerini base’den alacak şekilde tasarlıyoruz.

create or replace type SuccessMessage under BaseMessageType
(
  -- normalde mesaj tipini de  base type'ta tanımlayabilirdik; ama burda da bir property olsun istedim.
  MessageType varchar2(20),
  constructor function SuccessMessage return self as result,
  constructor function SuccessMessage(p_code varchar2, p_message varchar2) return self as result
)
/

create or replace type body SuccessMessage is

  constructor function SuccessMessage return self as result is
  begin
    self.MessageType    := 'SUCCESS';
    self.Code           := '00001';
    self.Message       	:= 'SUCCESSFUL';
    return;
  end;

  constructor function SuccessMessage(p_code varchar2, p_message varchar2) return self as result is
  begin
    self.MessageType    := 'SUCCESS';
    self.Code           := p_code;
    self.Message        := p_message;
    return;
  end;

end;
/

Aynı mantıkla Hata Mesajı Type’ımızıda oluşturalım

create or replace type ErrorMessage under BaseMessageType
(
  -- normalde mesaj tipini de  base type'ta tanımlayabilirdik; ama burda da bir property olsun istedim.
  MessageType varchar2(20),
  constructor function ErrorMessage return self as result,
  constructor function ErrorMessage(p_code varchar2, p_message varchar2) return self as result
)
/
create or replace type body ErrorMessage is

  constructor function ErrorMessage return self as result is
  begin
    self.MessageType    := 'ERROR';
    self.Code           := '00003';
    self.Message        := 'GENERAL ERROR';
    return;
  end;

  constructor function ErrorMessage(p_code varchar2, p_message varchar2) return self as result is
  begin
    self.MessageType    := 'ERROR';
    self.Code           := p_code;
    self.Message        := p_message;
    return;
  end;

end;
/

BaseMessageType oluşturduk,

SuccessMessage ve ErrorMessage bundan türedi. ve üst objenin tüm özelliklerini kullanabilecek hale geldi.

şimdi örnek kodumuzu yazalım. yani bunları çalıştıralım. ve bakalım nasıl bir output ortaya çıkacak.

Not : print kullanımına dikkat edelim.

Tabi iserror diye bir değişken tanımladım. amaç program içinde hata oluştuğunda bunu setleyeceğim ve buna göre uygun message’ı çağıracağım.

-- Created on 20.05.2015 by cevheri 
declare
  error   ErrorMessage;
  succes  SuccessMessage;
  iserror boolean := true;
begin

  -- Hayal gucumuzu kullanarak;
  -- burada zilyon tane(baya bi çok demek) 
  -- iş yapan kod calıştığını düşünüyoruz
  -- hata oluşmassa burası çalışacak
  if iserror then
  
    -------------------------------------------------------------------------
    dbms_output.put_line('----------------------------');
    dbms_output.put_line('Hata yok default başarılı mesajı dönsün');
  
    -- type'ımızda constructor olduğu için
    -- default değerleri kullacağız
    succes := SuccessMessage;
    succes.print;
  
    dbms_output.put_line('----------------------------');
    dbms_output.put_line('Hata yok, Kullanıcıya Afferin desin');
  
    -- type'ımızda constructor olduğu için
    -- parametre almasını sağlayacağız
    succes := SuccessMessage('00001', 'Afferin Güzel Çalıştırdın');
    succes.print;
    -------------------------------------------------------------------------
  end if;

  iserror := false; -- artık hata yok 🙂 düzeldi
  if (not iserror) then
    
    -------------------------------------------------------------------------
    -- Yine Hayal gucumuzu kullanarak;
    -- burada zilyon tane(baya bi çok demek) 
    -- iş yapan kod calıştığını ve hata meydana geldiginde de 
    -- bu satırın çalışacağını düşünüyoruz.
    
    dbms_output.put_line('----------------------------');
    dbms_output.put_line('Hata oluştuğunu anlayalım yeter');
    error := ErrorMessage;
    error.print;
  
    dbms_output.put_line('-------------------------------------');
    dbms_output.put_line('Hatanın sebebini biliyoruz. Yakaladık');
    error := ErrorMessage('00002', 'Tabloya kayıt eklenirken Hata olustu.');
    error.print;
    -------------------------------------------------------------------------
  end if;

end;
/

Şimdi de çıktısına bir göz atalım mı
——————————————————————-

mesaj, dışardan parametre vermeden çağrıldığında
Hata yok default başarılı mesajı dönsün
Mesaj Kodu :00001
Mesaj Icerik:SUCCESSFUL
——————————————————————-

mesaj ve code, dışardan parametre verilerek çağrılırsa
Hata yok, Kullanıcıya Afferin desin
Mesaj Kodu :00001
Mesaj Icerik:Afferin Güzel Çalıştırdın
——————————————————————-

mesaj, dışardan parametre vermeden çağrıldığında
Hata oluştuğunu anlayalım yeter
Mesaj Kodu :00003
Mesaj Icerik:GENERAL ERROR
——————————————————————-
mesaj ve code, dışardan parametre verilerek çağrılırsa
Hatanın sebebini biliyoruz. Yakaladık
Mesaj Kodu :00002
Mesaj Icerik:Tabloya kayıt eklenirken Hata olustu.
——————————————————————-

Bu örnek daha spesific yapılabilir. Yağ-Salça-Soğan bizden, siz isterseniz içine patates, patlıcan vb… ne katarsanız katın.

Ben en basit şekliyle, sade ve anlaşılır olmasına özen gösteriyorum. sizden yapmanızı istediğim ilk örnek, şudur: success mesaj ve error message type’larının içindeki constructor’larının içinde kod yazmayın. base’e gidip, message’ın nerden geldiğini anlayın ve tüm kodlamayı ordan yapın. (ödev de verirmişiz ya…)

Selam ve Dua ile…

ORACLE PL/SQL – OBJECT TYPE – 3 USING PL/SQL OBJECT TYPE “CONSTRUCTOR”

Her canlının ölümü tadacağını,
ama sadece bazılarının hayatı tadacağını öğrendim. — Mevlana

 

Merhaba

Bir önceki yazımızda, object type ve object type list örneğini inceledik.(Buradan inceleyebilirsiniz)

Artı Bu yazımızda, biraz daha işi profesyonelleştirelim ve  aynı örneği kullanarak, object type’lar içine constructor tanımlaması yapalım mı. Bu yapıyı oracle PL/SQL dilinde ilk duyanlar, hadi yaaa derler genelde. Çünkü bir veritabanından, object oriented çalışma mantığı pek beklemezler. ama ilk object type yazımızda da bunu anlatmaya çalışmıştım(Buradan inceleyebilirsiniz) . ilk iki yazı standart bir tip tanımlaması ve array mantığında, o tipten liste oluşturma şeklinde oldu. artık bu object type’lar içinde çok güzel programlar yazağız.

Muhabbeti uzatmıyor ve sizi kodla baş başa bırakıyorum.

hadi artık objemizi create edelim

create or replace type t_key_value as object 
(
  key         varchar2(1000),
  value       varchar2(4000),
  type        varchar2(100),
  constructor function t_key_value(key varchar2, value varchar2) return self as result
);
/

create or replace type body t_key_value is
  constructor function t_key_value(key varchar2, value varchar2) return self as result is
  begin
  
    if key in (6, 7) then
      self.type := 'Tatil';
    else
      self.type := 'Calismak Lazim';
    end if;
    
    self.key   := key;
    self.value := value;
    return;
  end;
end;
/

create or replace type t_key_value_list as table of t_key_value;
/

 

Bu kod şunu yapıyor: günleri ve günün numarasını tutup, bunu listelemeye yarıyor. günlerin yüklemesi yapılırken,” tatil mi, çalışma zamanı mı olduğuna karar veriyor.”

Kodu satır satır anlatmaya çalıştm.

Kolay gele.

-- Created on 14.05.2015 by Cevheri 
declare
  v_kv      t_Key_Value; -- oncelikle type degiskenimizi tanımlıyor ve initialize ediyorduk artık yapmıyoruz :)))
  v_kv_list t_key_value_list := t_key_value_list(); -- key value type'ının listesini olusturmustuk onu tanımlıyoruz
  v_day     varchar2(10) := null; -- gunlerin isimlerini tutabilmek icin ayrı bir degisken tanımladık case fonksiyonu ile buna deger atayacağız
begin

  -- WRITE TYPE
  -------------------------------------------------
  -- Yedi kez donecek bir for döngüsü oluşturuyoruz
  dbms_output.put_line('------ Deger Atama  ------');
  for r in 1 .. 7 loop
    ------------------------
    -- gelen degere gore gunun ismi ilgili degiskene atilacak
    case r -- r for dongusundeki donus degerini alır o yüzden ayrıca bir degisken tanımlamaya gerek yok
      when 1 then
        v_day := 'PAZARTESI';
      when 2 then
        v_day := 'SALI';
      when 3 then
        v_day := 'CARSAMBA';
      when 4 then
        v_day := 'PERSEMBE';
      when 5 then
        v_day := 'CUMA';
      when 6 then
        v_day := 'CUMARTESI';
      when 7 then
        v_day := 'PAZAR';
      else
        v_day := null; -- olmaz ama her zaman siz kodunuzu yazarken ELSE'yi düşünün ve yazın...
    end case;
  
    ------------------------
    -- !!!! ÖNEMLİ !!!!!!!!
    -- işte olay burada kopuyor. ilk değer ataması yapılırken, constructor da çalışmasını yapıyor.
    v_kv := new t_Key_Value(r, v_day);
    ------------------------
  
    -- object type listimizi extend edip, içine type basacağız. 
    v_kv_list.extend;
    v_kv_list(v_kv_list.count) := v_kv; -- index vererek type'ı refere ediyoruz.
    ------------------------
  
    dbms_output.put_line('Atanan Key         :' || v_kv.key);
    dbms_output.put_line('Atanan Value       :' || v_kv.value);
    dbms_output.put_line('constructor type   :' || v_kv.type);
    dbms_output.put_line('****');
  end loop;

  dbms_output.put_line('-----------------------------');
  -- END WRITE-------------------------------------

  --**************************************************************

  -- READ TYPE-------------------------------------

  v_kv := null;
  dbms_output.put_line('-------  Deger Okuma   ------');
  -- hadi artık, doldurulan listelerin içindeki değerleri okuyalım
  for r in 1 .. v_kv_list.COUNT loop
  
    v_kv := v_kv_list(r); --- yine index vererek okuyoruz....
  
    dbms_output.put_line('Okunan Key         :' || v_kv.key);
    dbms_output.put_line('Okunan Value       :' || v_kv.value);
    dbms_output.put_line('constructor type   :' || v_kv.type);
    dbms_output.put_line('****');
  end loop;

  dbms_output.put_line('----------------------------');
  -- END READ-------------------------------------

end;

 

 

Kodun bendeki çıktısı şu şekilde, bir de siz deneyin bakalım doğru çalışıyor mu …….

------ Deger Atama  ------
Atanan Key         :1
Atanan Value       :PAZARTESI
constructor type   :Calismak Lazim
****
Atanan Key         :2
Atanan Value       :SALI
constructor type   :Calismak Lazim
****
Atanan Key         :3
Atanan Value       :CARSAMBA
constructor type   :Calismak Lazim
****
Atanan Key         :4
Atanan Value       :PERSEMBE
constructor type   :Calismak Lazim
****
Atanan Key         :5
Atanan Value       :CUMA
constructor type   :Calismak Lazim
****
Atanan Key         :6
Atanan Value       :CUMARTESI
constructor type   :Tatil
****
Atanan Key         :7
Atanan Value       :PAZAR
constructor type   :Tatil
****
-----------------------------
-------  Deger Okuma   ------
Okunan Key         :1
Okunan Value       :PAZARTESI
constructor type   :Calismak Lazim
****
Okunan Key         :2
Okunan Value       :SALI
constructor type   :Calismak Lazim
****
Okunan Key         :3
Okunan Value       :CARSAMBA
constructor type   :Calismak Lazim
****
Okunan Key         :4
Okunan Value       :PERSEMBE
constructor type   :Calismak Lazim
****
Okunan Key         :5
Okunan Value       :CUMA
constructor type   :Calismak Lazim
****
Okunan Key         :6
Okunan Value       :CUMARTESI
constructor type   :Tatil
****
Okunan Key         :7
Okunan Value       :PAZAR
constructor type   :Tatil
****
----------------------------

 

 

Selam ve Dua ile

Oracle PL/SQL – Object Type -1 USING PL/SQL OBJECT TYPES

… Gönül buğday tanesine benziyor,
bizse değirmene.
Değirmen nereden bilecek
bu dönüşün sebebi ne?
— Mevlana

Merhaba

Uzun süredir yazmayı planladığım oracle’daki object type kullanımı konusuna başlamış bulunuyorum. (Çok sık kullandığım ve sevdiğim bir alandır) Konu o kadar geniş ve bir kaç makaleye sığdırılamayacak kadar büyük ki nerden başlayacağınıza, konuları nasıl böleceğinize, makaleyi nerede sonlandıracağınıza karar vermek zor olabiliyor. En son sıfırdan, başlangıç seviyesinden anlatmaya karar verdim.

İlk makalemizde çok kısa bir şekilde, object type create(bu zaten standart, her makalenin olmazsa olmazı), initialize, example şeklinde olacak. aynı objeyi birkaç örnek kullanımıyla birlikte vereceğim.

—————————————————————

İhtiyaç Fazlası

öncelikle object type’lar pl/sql de nesne yönelimli kod yazabilme olanağı sunar. (Gerçek hayattaki objeleri veritabanında oluşturup, bunları birbirinden türetip, kullanabilme gibi, daha birçok konu.  Bunu ilerleyen makalelerimizde detaylı olarak anlatacağız.) Java, c# dillerinde çalışmış arkadaşlar bu özelliği çok severler genelde. Bu makelemizde, object type nasıl oluşturulur ve nasıl kullanılır, onu anlatacağız.

End ihtiyaç Fazlası

—————————————————————

 

Şimdi object type’ımızı create edelim

create or replace type t_key_value as object 
(
key    varchar2(1000),
value  varchar2(4000)
)
/

Key ve value property’si olan bir nesne oluşturmuş olduk. Buna değerler set edip, ihtiyacımız olduğunda nasıl kullanırız, bunu iki örnekle anlatacağım

————————————————————–

ilk Örneğimiz Şu şekilde olacak

-- Created on 14.05.2015 by Cevheri 
declare
  -- 1.Yöntem
  -- Null yüklemesi yapılarak, initialize etmiş oluyoruz. 
  -- bunun birden fazla yöntemi var
  -- constructor verilerek te yapılabilir. ilerde onunda örneğiniz yaparız. 
  -- ama en basit haliyle anlattığımız için bu şekilde devam edelim
  v_kv t_Key_Value := t_Key_Value(null, null);
begin
  v_kv.key   := '01';
  v_kv.value := 'Adana';
  
  dbms_output.put_line('Key   :'||v_kv.key);
  dbms_output.put_line('Value :'||v_kv.value);
end;
/

 

————————————————————–

İkinci örneğimiz(çeşitli kullanma yöntemleri hangisini severseniz)

-- Created on 14.05.2015 by Cevheri 
declare
  -- 2.Yöntem
  -- Null yüklemesi yapılarak, initialize etmiş oluyoruz. 
  -- bunun birden fazla yöntemi var
  -- constructor verilerek te yapılabilir. ilerde onunda örneğiniz yaparız. 
  -- ama en basit haliyle anlattığımız için bu şekilde devam edelim
  v_kv t_Key_Value;
begin
  v_kv := t_key_value( '01', 'Adana');
  
  dbms_output.put_line('Key   :'||v_kv.key);
  dbms_output.put_line('Value :'||v_kv.value);
end;
/

iki örneğin çıktısı da aynı olacak:

Key     :01
Value :Adana

———————–

 

Type’lar bu şekilde oluşturulur ve benim kullandığım iki yöntemi de göstermek istedim.

Sonraki makalelerimizde, bu type’ları, List<> şeklinde kullanımı, constructor tanımı, under, final keywordleri, type içine business iş katmanını nasıl yedireceğiz,  function, procedure nasıl yazılır(bunu öğrendikten sonra plsql package yazmayacağınıza eminim…) bunları da dilimiz döndüğünce anlatmaya çalışacağız.

(Referans : http://docs.oracle.com/cd/B12037_01/appdev.101/b10807/10_objs.htm)

 

Kolay Gelsin

Selam ve Dua ile…

@Cevheri

 

 

DBMS_APPLICATION_INFO – 2 (MODULE , ACTION)

Hiç görmediğim bir sevinçle; kapına geldim.
“Kim o” de yeter ki;
Sen kim olmamı istiyorsan o olmaya geldim –Mevlana

Merhaba

Daha önce dbms_application_info.client_info metodundan hatırlanacağı gibi, oracle session bilgilerini read ve set edebiliyorduk.

(Öncelikle bu yazıyı okumanızda fayda var DBMS_APPLICATION_INFO – 1   (CLIENT_INFO))

Oracle Client_Info haricinde session’ı setleyebileceğimiz iki alan daha veriyor; bunlarda Module_Name ve Action_Name bilgileridir. Bu iki değer için, Module Action bilgisinin parent’i diyebiliriz.

Örnek ile anlatalım,

Oracle ile çalışan bir Program yazdınız. İsmi: OracleIleCalisanProgramSoft. Programınız; oracle’a her connect olduğunuda “Module” alanını programınızın ismiyle setlersiniz. o sabit kalır. Sonra her farklı işlem yapmaya kalktığında da, action kısmını setlersiniz.

Örnek :

Sisteme Giriş Yaparken (loglama vs.. yaptığınızı varsayalım ve uzun sürdüğünü düşünelim.)

Module: OracleIleCalisanProgramSoft

Action  : Login

 

Muhasebe işlemleri yapmaya başladı

Module: OracleIleCalisanProgramSoft

Action  : Muhasebe

 

Raporlama almaya başladı (Topluca Fatura Hazırlıyor vs..)

Module: OracleIleCalisanProgramSoft

Action: Raporlama

 

Bu Sayede, hali hazırda program işlemlerine devam ederken bunu takip edebilecek, tablolara bir kaydın hangi aşamada atıldığını tutmak isterseniz de yine yazılmış bu action bilgisini read ederek kulllanabileceksiniz.

———————————————————————

Artık kod yazmaya devam edebilir (En sevdiğim tarafı)

Bunların nasıl yapılacağını yazalım.

-------
-------
declare
  -- ilk module atamalarımı yapıyorum.
  v_module        varchar2(4000) := 'ORACLE_ILE_CALISAN_HERHANGI_BIR_PROGRAM.EXE';
  v_active_module varchar2(4000) := null;

  -- ilk action atamalarımı yapıyorum.
  -- Bunu programın ilerleyen zamanlarında da değiştirebilir ve tekrar set_action yapabilirim.
  v_action        varchar2(4000) := 'PROGRAMIN_BIR_PARCASI';
  v_active_action varchar2(4000) := null;
begin
  -- Sessiondaki, module ve action bilgilerini okuyalım...
  dbms_application_info.read_module(module_name => v_active_module, action_name => v_active_action);

  -- Module bilgisi daha önce hiç atanmamışsa, atamasını yapıyoruz.
  if (v_active_module is null) then
    dbms_application_info.set_module(v_module, v_action);
    dbms_output.put_line('Sessiona Yeni atanan Module Bilgisi : ' || v_module);
  else
    -- varsa olan bilgiyi kullanabiliriz
    dbms_output.put_line('Sessiondaki Aktif Module Bilgisi : ' || v_active_module);
  end if;

  --Action bilgisi o an için atanmamışsa veya atamasını istediğimiz bilgiden farklıya
  if (v_active_action is null or v_active_action != 'BENIM_ISTEDIGIN_ACTION_BILGISI_DEGILSE') then
    dbms_application_info.set_action(action_name => v_action);
    dbms_output.put_line('Sessiona Yeni atanan Action Bilgisi : ' || v_action);
  else
    --Varsa ve benim istediğim bilgiyse direk okuyabiliriz....
    dbms_output.put_line('Sessiondaki Aktif Module Bilgisi : ' || v_active_action);
  end if;
end;
/
----------

dbms_application_info.set_module,

dbms_application_info.set_action,

dbms_application_info.read_module metodlarını inceledik.

Kolay gelsin dileklerimle…

 

Selam ve Dua İle…

 

DBMS_APPLICATION_INFO – 1 (CLIENT_INFO)

Ayağın kırıldı diye üzülme.
Allah sana belki kanat verecek.

Kuyu dibinde kaldın diye kırılma,
belki oradan bile bir kapı açılır.

Yusuf kuyudan sultan oldu –Mevlana

Merhaba

Bugünkü yazımız, PL/SQL Developer’ların sıklıkla kullandığı

DBMS_APPLICATION_INFO.READ_CLIENT_INFO  ve DBMS_APPLICATION_INFO.SET_CLIENT_INFO procedurleriyle alakalı olacaktır.

Öncelikle Client_Info nedir ondan bahsedelim.

select v.CLIENT_INFO, v.* from v$session v

Oracle, sistemdeki aktif sessionların bilgisini yukardaki bir view aracılığıyla bize sunmaktadır. sisteminizdeki aktif sessionların listesini bu sorgu ile görebilirsiniz. Her yeni session açıldığında, bu sessiona ait bir yığın bilgi de tutulur. sessionid leri, çalıştırdığı sqller, aktif-pasif durumu, bağlandığı bilgisiyarın bilgileri vb….

Bize de bu bilgilerden bazılarını yazma ve sonrasında okuma imkanı vermiştir. Yani siz oracle’da yeni bir session açtığınızda; oracle’ın bu topladığı veriler haricinde (sınırlı sayıda) session bilgisini kendiniz yönetebilirsiniz.

(Normalde bu işler için GLOBAL TEMPORARY TABLE kullanmak daha doğrudur; ama hazır elimizde olan alanı yönetmek daha kolay olduğu için bu alanlarıda kullanmakta da fayda var. GLOBAL TEMPORARY TABLE hakkında da bir yazı yazmak nasip olursa, orada bu konuyu daha detaylı anlatırım. )

Şimdi set ve read metodlarının örnek kullanımını inceleyelim.

--
declare
  -- atamasını yapacağımız user bilgisini set ediyoruz
  v_client_info        varchar2(4000) := 'TEST_USER'; 

  -- daha önce ataması yapılan user bilgisi varsa bu değişkene atayacağız
  v_active_client_info varchar2(4000) := null; 
begin
  
  -- read metodu ile client info bilgisini değişkene atıyoruz
  dbms_application_info.read_client_info(client_info => v_active_client_info);
  
  -- eğer daha önce atama yapılmamışsa, atama yapacağız; varsa direk yazdıracağız
  if (v_active_client_info is null) then
    dbms_application_info.set_client_info(client_info => v_client_info);
    dbms_output.put_line('Sessiona atanan User Bilgisi : '||v_client_info);
  else
    dbms_output.put_line('Sessiondaki Aktif User : '||v_active_client_info);
  end if;
end;
--

kod ilk çalıştığında çıktı şu şekilde := Sessiona atanan User Bilgisi : TEST_USER

eğer aynı sessionda tekrar çalıştırırsak :=  Sessiondaki Aktif User : TEST_USER

 

Bunu ister database’in logon_triggger’ında isterseniz; yazdığınız arayüzün open session metodunda yazın ve session açık olduğu sürece, istediğiniz yerden bu bilgilere ulaşın.

HAZIR BİR GLOBAL DEĞİŞKEN

Kolay Gelsin Dileklerimle

 

Selam ve Dua ile…

 

ORACLE PARTITIONING – 2 (PARTITION BY RANGE)

Kim demiş, gül yaşar dikenin himayesinde.
Dikenin itibarı, ancak gül sayesinde –Mevlana

Merhaba

Partitioning üzerine yazılarımıza devam ediyoruz.

Bu yazımızda da oluşturduğumuz tabloyu yıl yıl partition yapıp, sadece o yıla ait bir veriyi görüntülemek istediğimizde de partition name üzerinden nasıl sorgulayacağımızı göreceğiz. Bu sayede; daha önce yaşanan performans problemlerinin de ciddi anlamda önüne geçmiş olacağız.

Tablomuzu create edelim.

Burada dikkat edilmesi gereken husus range olarak verdiğiniz column, (burada yıl verdik); Bu değere eşit ya da büyük veriler bir sonraki tanımlı partiton’ a gider.

CREATE TABLE tmp_cevheri_action
(
   action_id    NUMBER,
   action_year  NUMBER,
   action_month NUMBER,
   action_date  DATE,
   action       VARCHAR2 (250)
)
PARTITION BY RANGE
   (action_year)
   (
      PARTITION actionyear_001 VALUES LESS THAN ('2010'),
      PARTITION actionyear_002 VALUES LESS THAN ('2011'),
      PARTITION actionyear_003 VALUES LESS THAN ('2012'),
      PARTITION actionyear_004 VALUES LESS THAN ('2013'),
      PARTITION actionyear_005 VALUES LESS THAN ('2014'),
      PARTITION actionyear_006 VALUES LESS THAN ('2015'),
      PARTITION actionyear_007 VALUES LESS THAN ('2016')
   );

————————————————————————————————————————–

nologging olarak alterleyeceğim. biraz sonra içine yüklü bir data atacağım…

alter table tmp_cevheri_action nologging;

————————————————————————————————————————–

deneme bir history tablosunun kayitlarini “append” ile alıyorum…

insert /*+ append */ into tmp_cevheri_action 
select 
rownum action_id, 
to_number(to_char(t.islem_tarihi, 'YYYY')) as action_year, 
to_number(to_char(t.islem_tarihi, 'MM')) action_month, 
t.islem_tarihi as action_date,
'İşlem Bilgisi' as action
from history_table t;

commit;

—————————————————————————————————————————-

partitionların durumlarını inceleyelim.

select t.partition_name, t.partition_position
  from DBA_tab_partitions t 
 where t.table_name = 'TMP_CEVHERI_ACTION';

PARTITION_NAME                 PARTITION_POSITION
------------------------------ ------------------
ACTIONYEAR_001                                  1
ACTIONYEAR_002                                  2
ACTIONYEAR_003                                  3
ACTIONYEAR_004                                  4
ACTIONYEAR_005                                  5
ACTIONYEAR_006                                  6
ACTIONYEAR_007                                  7
7 rows selected

—————————————————————————————————————————-

Kayıt durumlarına bakalım.

SQL> select COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_001)
  2  UNION ALL
  3  select  COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_002)
  4  UNION ALL
  5  select  COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_003)
  6  UNION ALL
  7  select  COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_004)
  8  UNION ALL
  9  select  COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_005)
 10  UNION ALL
 11  select  COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_006)
 12  UNION ALL
 13  select  COUNT(*) from TMP_CEVHERI_ACTION partition(ACTIONYEAR_007)
 14  ;
 
  COUNT(*)
----------
         0
    133162
    189577
    605844
   7811142
   1624013
     16301
7 rows selected

 

Sistem oturdu, bundan sonraki gelen kayıtlarda ilgili partitiona gidecek.. süper oldu. Ancaaak; bu bize nasıl bir performans sağlayacak….

……..

Bize sadece 2014 yılının verileri lazım.

işte çayımızın demlendiği an

işte sorgu

SQL> select * from tmp_cevheri_action 
            partition(ACTIONYEAR_006) t 
      where t.action_date between '01.01.2014' and '31.12.2014';

 ACTION_ID ACTION_YEAR ACTION_MONTH ACTION_DATE ACTION
---------- ----------- ------------ ----------- -------------
   8739726        2014            1 11.01.2014  İşlem Bilgisi
   8739727        2014            1 11.01.2014  İşlem Bilgisi
   8739728        2014            1 11.01.2014  İşlem Bilgisi
   8739729        2014            1 11.01.2014  İşlem Bilgisi
   8739730        2014            1 11.01.2014  İşlem Bilgisi
   8739731        2014            1 11.01.2014  İşlem Bilgisi
   8739732        2014            1 11.01.2014  İşlem Bilgisi
   8739733        2014            1 11.01.2014  İşlem Bilgisi
   8739734        2014            1 11.01.2014  İşlem Bilgisi
   .......
   ......
   .....
   ....
   ...
   ..
   .

—————————————————————————————————————————-

Sorguya başka tarih girelim.

SQL> select * from tmp_cevheri_action partition(ACTIONYEAR_006) t
  2  where t.action_date between '01.01.2015' and '31.12.2015' ;
no rows

 

Eğer sorguya partition ismini vermeden çalıştırırsak, normal tabloymuş gibi cevap verecek; burda da devreye indexlemeyi de partitoning yapmak girecektir.
Hepinize kolay gelsin…

Selam ve Dua ile…

COMMIT WRITE NOWAIT PARAMETRESI

 

MerhabaArkadaşlar.

Loglama yapıları üzerinde biraz araştırma yaparken karşılaştığım ve çok hoşuma giden bir yapıdan bahsedeceğim.

“COMMIT WRITE”
Oracle 10g2xxx ve üzerinde
Bir o kadar kolaylık sağlayan bu komut aynı zamanda bir o kadar da tehlikelidir. Direkt redologlara müdehale ediyorsunuz ki… Bunun tehlikesini tahmin ediyorsunuzdur umarım. etmiyorsanız canlı ortamlarda kullanmamanızı tavsiye ederim.

COMMIT WRITE BATCH NOWAIT; -- Can kurtaran 🙂

Batch comutu ekleyerek, verilen data Redelog dosyalarına yazılmadan öce buffer’a alınarak tampon belleğe almış oluyoruz ve transaction hızını artırmış oluyoruz.

Ama asıl bahsetmek istediğim iş Nowait : Database in işlem sırasını atlatıyoruz diyebiliriz. bir işe öncelik tanıyoruz.(Torpil geçiyoruz)Commitle verilen datanın diske yazılmasını beklemeden, yerine yeni bir iş alır. Data bütünlüğü düşünülmeyecek işler için uygun olabilir. Kayıp olasıdır….

Örnek: Sisteminize giriş yapan kullanıcıların logunu tutmak istiyorsunuz. Aynı anda yüzlerce, binlerce kullanıcı sisteme giriyor ve çok yoğun bir sisteminiz var. Veya veritabanında yaptığınız insert, update, delete işlemlerinde bir hata alınınca bunları loglamak istiyorsunuz.
Bunların veri bütünlüğüne ihtiyacı yoktur. Yani bir log kaydı yazılamama ihtimalinde sizi çok büyük sorumluluklar beklememektedir. bunlar sizin işlerinizi kolaylaştırmak için yaptığınız çalışamalardır. Burada NOWAIT komutunu kullanmak akıllıcadır.
Ama bir ödeme yapan sisteminizi düşünelim. bu kaydın veri bütünlüğü şarttır. arkasında ciddi sorumluluklar vardır. İşte burada WAIT metodu devreye giriyor. yani bu commit diske kaydedilmeden, yeni bir işlem kesinlikle almayacaktır.

 

Olayı daha iyi anlamak adına Daha önce yapılmış bir testi de paylaşmak istiyorum.

   DECLARE
      SD DATE;
    BEGIN
     FOR I IN 1..150000 LOOP
      UPDATE EMP SET counter = counter + 1 WHERE EMPno=7499;
      commit;
     END LOOP;
    END;
    /

PL/SQL procedure successfully completed.

Elapsed: 00:00:15.02

--------------------------------------------------------

    DECLARE
      SD DATE;
    BEGIN
     FOR I IN 1..150000 LOOP
      UPDATE EMP SET counter = counter + 1 WHERE EMPno=7499;
      commit write batch nowait;
     END LOOP;
    END;
    /

 successfully completed.

Elapsed: 00:00:14.09
---------------------------------------------------------------  
   DECLARE
      SD DATE;
    BEGIN
     FOR I IN 1..150000 LOOP
      UPDATE EMP SET counter = counter + 1 WHERE EMPno=7499;
      commit write immediate wait;
     END LOOP;
    END;
    /

PL/SQL procedure successfully completed.

Elapsed: 00:02:20.06

 

Sehirler Arası Mesafe Tablosu

Merhaba

Bugün bir arkadaşımın ödevi için hazırladığım Şehirler arası mesafe tablosunu burda paylaşmak istedim.  İhtiyaç duyan olursa tekrar uğraşmasın

 

create scripti

create table ILMESAFESI
(
  id     NUMBER,
  ilid1  NUMBER,
  ilid2  NUMBER,
  mesafe NUMBER
);

 

örnek insert scripti

insert into ILMESAFESI (id, ilid1, ilid2, mesafe)
values (1, 2, 1, 330);

 

sql scriptinin tamamını dosya olarak ekliyorum. ilmesafesi