27 Haziran 2012 Çarşamba

Oracle PL SQL'de Dizi Kullanımı

Diğer programlama dillerinde olduğu gibi Oracle PL SQL altındada dizi kullanımı mümkündür.Bir önceki makalem'dede belirttiğim gibi bu diziler içerisinde döngüler vasıtasıyla dolaşmak mümkündür.Peki oracle'da dizi kullanımı bize en çok hangi noktalarda faydalı olur nerelerde kullanılır.Bunu basit bir örnekle açıklamak gerekirse.

Wep Programlama(Asp.Net olsun) yapıyorsunuz ve elinizde'ki bir excel'de bulunan verileri veritabanındaki tablonuza kaydetmek istiyorsunuz.Basit olması açısında Execl'imizin tek kolondan oluştuğunu düşünelim.Böyle bir durumda nasıl bir yol izleyebilirim diye düşündüğünüzde karşınıza 4 farklı yöntem çıkacaktır;

1. Yöntem Excel'deki her satırı alıp veritabanına tek tek INSERT edebilirsiniz.Bu yöntemde her bir satır için Veritabanına gitmeniz gerekecektir.

2. Yöntem Excel'de bulunan verilerin hepsini Excel'den okuyup.Bunların hepsini asp.net tarafında önceden belirlenen bir operatör vasıtasıyla birleştirirsiniz ve Database tarafında bu önceden belirlenen ayrac'a göre bu değeri parçalayıp bulduğunuz değerleri tablonuza Insert edersiniz.Bu yöntem biraz daha mantıklıdır Veritabanına bir kez bağlanırsınız ve işinizi halledersiniz Fakat daha komplex'dir.Bu yöntem bazı metedolojiler kullanıldığında bazen çok daha fazla komplex olabilmektedir.Bunu kolaylaştırmak için dizi kullanmak gayet rahatlatıcı bir çözüm olacaktır.Bu durumu biraz açıklamak gerekirse;

Örnek datamız : (Murat Imre#Merhaba Dunya#Oracle diziler#vb) formatında olsun burada ayraç olarak '#' karakterini kullandık.

Bunun için öncelikle sisteminizde bir dizi tipi tanımlamanız gerekmektedir.Bunu merkezi ve daha farklı amaçlarda kullanılmak üzere bir Package içerisinde tanımlayıp kullanabilirsiniz veya doğrudan Oracle içerisinde Type tanımlayabilirsiniz ve Sisteminizde bu tip durumlarda kullanılmak üzere SPLIT işlemi yapan bir fonksiyon yazmanız gerekmektedir.Bu fonksiyon 2 tip parametre alabilir.

1. parametre parçalanacak olan hamveriyi saklayacak.

2. parametre ise hangi opereatöre göre parçalama işlemi yapılacak bu değeri saklayacak.

Asıl prosedürümüze gelecek olursak burada ilk olarak Split işlemi yapan fonksiyonumuzdan dönen veriyi saklamak üzere bir tane Dizi tipide yerel değişken tanımlamalıyız ve prosedürümüzün begin tagının altında bu fonksiyona gerekli parametreleri geçip dönen değeri bu değişkenimizi atamalıyız.
Artık Excel'deki verilerimiz Oracle tarafında bir dizide saklanmakta tek bir işimiz kaldı bu dizinin değerlerini tablomuza INSERT etmek.

NOT : Bu fonksiyon ve bu yöntem büyük ve komplex sistemlerde işinizi son derece kolayaştıracaktır.

3.Yöntem Direk Asp.Net tarafından prosedürümüze Dizi Tipinde parametre geçmek Yukarda bahsettiğim diğer 2 yöntemden çok daha mantıklı ve çok daha az maliyetli bir yöntemdir.

4.Yöntem ise yine verileri Asp.Net tarafında birleştirmek fakat bu sefer Excel kolonundaki verinin tipine göre özel bir formatta birleştirmek (Örnek: Veri string türünde ise veriyi '' işaretleri arasında yazmalısınız Sayısal bir değerse direk birleştirebilirsiniz) ve birleştirme operatörü olarak ',' (virgül kullanmalısınız) verileri birleştirme işlemi bittikten sonra bu değeri parametre olarak prosedürümüze geçmeliyiz ve prosedür tarafındada Dinamik bir sorgu yazarak gelen değeri direk olarak bu dinamik sorgumuza dahil edebiliriz.Fakat bu gerçekten çok ama çok dikkat edilmesi gereken bir konudur çünkü Dinamik SQL'ünüze parametre olarak gelen veriyi direk olarak dahil ederseniz kullanıcılar sistemimizde pekde istenmeyen sonuçlar oluşmasına sebep olabilirler.Daha doğrusu "SQL Injection" saldırılarına maruz kalabilirsiniz.Sql Injection saldırılarından korunmayıda başka bir makalemde sizlerle paylaşacağım.

Makalamizin devamı için Common Adında bir package oluştup bu package içerisindede bir dizi tipi oluşturalım.Dizi tipimizi package'mizin SPEC alanında oluşturuyoryuz

Common Package

--PACKAGE SPECK KISMI
CREATE OR REPLACE PACKAGE MIMRE.COMMON
AS

TYPE STRINGARRAY IS TABLE OF VARCHAR2(500) INDEX BY BINARY_INTEGER; --Dizi tanımlaması yapılıyor


    --PACKAGE İÇERİSİNDE YER ALABİLECEK FONKSİYON VE PROSEDÜR TANIMLAMALARI

END COMMON;
/

--PACKAGE BODY KISMI
CREATE OR REPLACE PACKAGE BODY  MIMRE.COMMON
AS

    --PACKAGE İÇERİSİNDE YER ALABİLECEK FONKSİYON VE PROSEDÜR İÇERİKLERİ

END COMMON;


Evet artık sistemlerimizde kullanılmak üzere VARCHAR2 tipinde bir dizimiz bulunmakta.Şimdide sistemimizde kullanılmak üzere Dizi tipinde değer dönen bir SPLIT fonksiyonu yazalım.Artık bütün projelerimizde kullabileceğimiz bize kullanım kolaylığı sağlayan bir SPLIT fonksiyonumuz var.Bu fonskiyon sayesinde çok kolay ve anlaşılabilir kodlar yazabileceğiz.

Örneğin : MyExcel(2) dediğimiz zaman Dizimizin dolayısıyla Excelin 2. elemanına ulaşabileceğiz.


--PACKAGE SPECK KISMI
CREATE OR REPLACE PACKAGE MIMRE.COMMON
AS

    TYPE STRINGARRAY IS TABLE OF VARCHAR2(500) INDEX BY BINARY_INTEGER; --Dizi tanımlaması yapılıyor

    --PACKAGE İÇERİSİNDE YER ALABİLECEK FONKSİYON VE PROSEDÜR TANIMLAMALARI

     FUNCTION F_SPLIT
     (
        pValue VARCHAR2,
        pSeperator VARCHAR2
    )
    RETURN COMMON.STRINGARRAY;

END COMMON;
/

--PACKAGE BODY KISMI
CREATE OR REPLACE PACKAGE BODY  MIMRE.COMMON
AS

    --PACKAGE İÇERİSİNDE YER ALABİLECEK FONKSİYON VE PROSEDÜR İÇERİKLERİ
   
     FUNCTION F_SPLIT
     (
        pValue VARCHAR2,
        pSeperator VARCHAR2
    )
    RETURN COMMON.STRINGARRAY

        IS    
            rIndex       NUMBER :=0;
            sepIndex     NUMBER :=0;
            lastStrValue  VARCHAR2(1500) := pValue; --Parçalanacak Değerin Parçalanma Sonrası Değerinin Saklandığı Değişken
            returnArray COMMON.STRINGARRAY;

        BEGIN
            -- pSeperator ile belirtilen parçalama opertörünün(Ayraç) geçtiği ilk konumu bul
            sepIndex := INSTR (lastStrValue , pSeperator , 1 , 1 );

            --Parçalama işlemi bitene kadar devam edecek bir döngüye giriliyor
            --Parçalama işlemi ne hamveride ayraç kalmayana kadar devam et
            WHILE ( sepIndex != 0) LOOP
            BEGIN
                  --Bir sonraki adım için döngü değişkeninin değerinin bir artır 
                  rIndex := rIndex + 1;

                  --Ayracın ilk bulunduğu yeri tespit et ve buraya kadar olan veriyi dönüş dizisine ata
                  returnArray(rIndex) := SUBSTR( lastStrValue , 1 , sepIndex - 1 );

                  --Diziye alınan değeri parçalanma işlemine devam edilecek olan ham veriden çıkar
                  lastStrValue := SUBSTR( lastStrValue , sepIndex + 1 , LENGTH(lastStrValue) );

                  --Yukarda atama işlemi yapıldıktan sonra bir sonraki değer için ayracın yerini tespit et 
                  sepIndex := INSTR( lastStrValue , pSeperator , 1 , 1 );

                  -- Eğer parçalanma işlemi bitmişse yani ham veri içerisinde artık ayraç kalmamışsa ham veride kalan son değeride diziye yerleştir ve
                  --Döngüden çıkılması için bir sonraki adıma geç 
                  IF sepIndex = 0 THEN
                     returnArray( rIndex + 1 ) := lastStrValue;
                  END IF;
            END;
            END LOOP;

            --Eğer ham veride hiç ayraç yok ise bu değeri direk olarak diziye yerleştir
            IF rIndex = 0 THEN
                returnArray(1) := pValue;
            END IF;

            --Return array 
            RETURN returnArray;
        END F_SPLIT;

END COMMON;

Common paketindeki SPLIT fonksiyonu aşağıdaki gibi bir kullanım ile çağırıp.Dizimizin içerisindeki elemanların değerlerini görüntüleyebiliriz.    

DECLARE

    MyExcell MIMRE.COMMON.STRINGARRAY;
   
    --ASP.NET tarafından geleceğini düşündüğümüz veri 
    vExcelData VARCHAR2(250) := 'Murat Imre#Merhaba Dunya#Oracle diziler#Bilgisayar Muhendisligi#Havalar cok sicak';
   
BEGIN

    MyExcell := MIMRE.COMMON.F_SPLIT(vExcelData,'#');  --Artık Dizimize değerler dolduruldu

    DBMS_OUTPUT.PUT_LINE('Exceldeki ilk satırımız : ' || MyExcell(MyExcell.FIRST));
    DBMS_OUTPUT.PUT_LINE('Exceldeki ikinci satırımız : ' || MyExcell(2));
    DBMS_OUTPUT.PUT_LINE('Exceldeki son satırımız : ' || MyExcell(MyExcell.LAST));

END;

Ekran çıktımız aşağıdaki gibi olacaktır.


Bir sonraki makalem'de Asp.Net ile Bir Excel dosyasının içeriğini açıp verileri Asp.Net tarafında '#' operatörü ile birleştirdikten sonra bu değerleri bir Stored Procedure vasıtasıyla Tablomuza INSERT eden bir proje yapalım hem bu konuyu iyice pekiştirmiş oluruz.


Hiç yorum yok:

Yorum Gönder