Sunum yükleniyor. Lütfen bekleyiniz

Sunum yükleniyor. Lütfen bekleyiniz

Veri Tabanı Yönetim Sistemleri 2 Ders 6 PL/SQL Ek Bilgiler Yrd. Doç. Dr. Altan MESUT Trakya Üniversitesi Bilgisayar Mühendisliği Bölümü.

Benzer bir sunumlar


... konulu sunumlar: "Veri Tabanı Yönetim Sistemleri 2 Ders 6 PL/SQL Ek Bilgiler Yrd. Doç. Dr. Altan MESUT Trakya Üniversitesi Bilgisayar Mühendisliği Bölümü."— Sunum transkripti:

1 Veri Tabanı Yönetim Sistemleri 2 Ders 6 PL/SQL Ek Bilgiler Yrd. Doç. Dr. Altan MESUT Trakya Üniversitesi Bilgisayar Mühendisliği Bölümü

2 Veri Tipi Dönüşümleri Eğer veri tipi dönüşümü Oracle tarafından otomatik olarak yapılıyorsa örtük (implicit), kullanıcı tarafından bir fonksiyon ile yapılıyorsa açık (explicit) dönüşüm olarak nitelendirilir. Aşağıdaki örnekte biri karakter diğeri sayı türünde olan iki değişken toplama işlemine tabi tutulduğunda, karakter türünde olan Oracle tarafından otomatik olarak sayıya dönüştürülür ve ekranda 7000 görüntülenir. DECLARE v_salary NUMBER(6):=6000; v_sal_increase VARCHAR2(5):='1000'; BEGIN v_salary := v_salary + v_sal_increase; DBMS_OUTPUT.PUT_LINE(v_salary); END;

3 Örtük dönüşümün handikapları Bu tip dönüşümler yavaş olabilir. Örtük dönüşümler Oracle tarafından yapıldığı için, eğer Oracle dönüşüm kuralını değiştirirse kod bundan etkilenebilir. Dönüşüm kuralları, kullanılan ortama göre farklı olabilir. – Örneğin tarih biçimleri dil ve kurulum ayarlarına göre farklı olabilir. Dolayısıyla örtük dönüşüm farklı bir dildeki sunucuda çalışmayabilir. Database Programming with PL/SQL, Section 2, Lesson 5, Writing PL/SQL Executable Statements

4 Açık Dönüşümler Eğer dönüşüm işlemi TO_NUMBER, TO_CHAR, TO_DATE gibi bir fonksiyon kullanılarak yapılırsa hem daha hızlı hem de daha hatasız olur. – TO_CHAR(SYSDATE,'Month YYYY')Mart 2016 – TO_DATE('April-1999','Month-YYYY') 01/04/1999 DECLARE v_a VARCHAR2(10) := ' '; v_b VARCHAR2(10) := ' '; v_c PLS_INTEGER; BEGIN v_c := TO_NUMBER(v_a) + TO_NUMBER(v_b); DBMS_OUTPUT.PUT_LINE(v_c); END; Eğer Türkçe dil ayarlarında bir sistem kullanıyorsanız April yerine Nisan yazmalısınız. Aksi halde "not a valid month" hatası alırsınız.

5 İç İçe Bloklar Birçok programlama dilinde olduğu gibi PL/SQL’de de iç içe bloklar yaratılabilir. İç bloklar, dış blokta yaratılan değişkenleri ‘global değişken’ olarak kullanabilir. DECLARE v_outer_variable VARCHAR2(20):='GLOBAL VARIABLE'; BEGIN DECLARE v_inner_variable VARCHAR2(20):='LOCAL VARIABLE'; BEGIN DBMS_OUTPUT.PUT_LINE(v_inner_variable); DBMS_OUTPUT.PUT_LINE(v_outer_variable); END; DBMS_OUTPUT.PUT_LINE(v_outer_variable); END; Database Programming with PL/SQL, Section 2, Lesson 6, Nested Blocks and Variable Scope

6 Değişken Kapsama Alanı Eğer aynı değişken ismi hem lokal hem de global olarak kullanıldı ise iç blok lokal olanı kullanır. Nasıl ki C++’ta :: kullanımı ile global olana erişmek mümkün ise, PL/SQL’de de global olana erişmek istenirse dış blok için bir etiket tanımı yapılabilir:

7 MERGE Kaynak ve hedef tablolarda eşleşen değerler varsa hedef tablodaki değerleri güncelleyen, yoksa hedef tabloya yeni değer olarak ekleyen DML komutudur. MERGE INTO art a USING items i ON (a.id = i.item_id) WHEN MATCHED THEN UPDATE SET a.artist = i.artist, a.description = i.description WHEN NOT MATCHED THEN INSERT VALUES(i.item_id, i.title, i.artist, i.description); Database Programming with PL/SQL, Section 3, Lesson 1, Review of SQL DML

8 TYPE Nesne Yönelik Programlama dillerinde kullanılan nesnelere benzer PL/SQL yapısı CREATE TYPE … AS OBJECT ile oluşturulur: CREATE TYPE address_typ AS OBJECT ( street VARCHAR2(30), city VARCHAR2(20), postal_code VARCHAR2(6) ); Bir nesne tanımı içinde başka bir nesne kullanılabilir: CREATE TYPE employee_typ AS OBJECT ( employee_id NUMBER(6), first_name VARCHAR2(20), last_name VARCHAR2(25),.. address address_typ ); CREATE TABLE employees OF employee_typ; şeklinde tablo oluşturulabilir.

9 Diziler VARRAY türünde TYPE ile oluşturulur DECLARE type namesarray IS VARRAY(5) OF VARCHAR2(10); type grades IS VARRAY(5) OF INTEGER; names namesarray; marks grades; total integer; BEGIN names := namesarray('Ali', 'Pınar', 'Ayhan', 'Veli'); marks := grades(98, 97, 78, 87); total := names.count; dbms_output.put_line('Total '|| total || ' Students'); FOR i in 1.. total LOOP dbms_output.put_line('Student: ' || names(i) || ' Marks: ' || marks(i)); END LOOP; END; CREATE TYPE Phone_List_Type AS VARRAY(5) OF VARCHAR2(25) VideoRental.sql scriptinde TYPE içinde FUNCTION kullanımını da inceleyiniz. VideoRental.sql scriptinde yer alan bu satırı 4. derste vermiştik

10 Cursor'lar: Implicit & Explicit Önceki derslerde bahsedilen Cursor hakkında biraz daha ayrıntılı bilgi vermek gerekirse, cursor aslında sorgu sonucunun saklandığı alana bir isim verilmesi veya bu alanı gösteren bir pointer gibi düşünülebilir. Database Programming with PL/SQL, Section 5, Lesson 1'e göre iki tip Cursor'un tanımı şu şekildedir: – Implicit Cursor: Tüm DML işlemleri için ve tek satır döndüren sorgular için ORACLE tarafından otomatik olarak tanımlanır. – Explicit Cursor: Programcı tarafından çok satır döndüren sorguların saklanması için tanımlanır. Bazı kaynaklara göre çok satır döndüren bir sorgu eğer FOR döngüsü tanımında cursor olarak tanımlanmadan (isim verilmeden) kullanıldıysa, bu da bir Implicit Cursor kullanımıdır.

11 Implicit Cursor FOR döngüsü: Önceki dersimizde FOR döngüsünü adım sayısı bilinen bir işlem için FOR num IN LOOP şeklinde kullanmıştık. Buradaki kullanım For Each döngüsüne benzer şekilde kayıt sayısını bilmemize gerek kalmadan tüm kayıtlar için çalışır. BEGIN FOR kayit IN ( SELECT * FROM Personel WHERE "BÖLÜM" = 10 ORDER BY Soyad) LOOP DBMS_OUTPUT.put_line ( kayit.Ad || ' ' || Kayit.Soyad); END LOOP; END;

12 Explicit Cursor FOR döngüsü: DECLARE CURSOR c1 IS SELECT * FROM Personel WHERE "BÖLÜM" = 10 ORDER BY Soyad; BEGIN FOR kayit IN c1 LOOP DBMS_OUTPUT.put_line ( kayit.Ad || ' ' || Kayit.Soyad); END LOOP; END;

13 FETCH kullanımı Cursor'lar ile çalışırken FOR döngüsü kullanmak yerine FETCH ile kayıtlar tek tek çekilebilir. Fakat bunun için önce Cursor'u Open ile açmak gerekir. Cursor sorgusunda elde edilen tüm alanlar için değişkenler tanımlamak ta gerekir. Sona geldiğimizi anlayıp döngüden çıkmak için %NOTFOUND özelliğini kullanabiliriz. DECLARE CURSOR c1 IS SELECT Ad, Soyad FROM Personel WHERE "BÖLÜM" = 10 ORDER BY Soyad; Ad Personel.Ad%TYPE; Soyad Personel.Soyad%TYPE; BEGIN OPEN c1; LOOP FETCH c1 INTO Ad, Soyad; EXIT WHEN c1%NOTFOUND; DBMS_OUTPUT.put_line ( Ad || ' ' || Soyad); END LOOP; END;

14 Cursor Özellikleri (Attributes) AttributeDescription %FOUNDEğer bir INSERT, UPDATE veya DELETE ifadesi bir yada daha çok satırı etkilediyse veya bir SELECT INTO ifadesi bir yada daha çok satır döndürdüyse TRUE döndürür. %NOTFOUND%FOUND'un mantıksal tersidir. DML işleminde herhangi bir satır etkilenmediyse veya sorguda döndürülmediyse TRUE döndürür. %ISOPENCursor açık ise TRUE döndürür. Implicit Cursor'larda hep FALSE döndürür (çünkü Oracle ilgili SQL ifadesini yürüttükten sonra otomatik olarak Cursor'u kapatır). %ROWCOUNTINSERT, UPDATE veya DELETE ifadelerinden etkilenen, veya SELECT INTO ifadesinden dönen satır sayısını döndürür. Geçen hafta Hata İşleme ile ilgili örnekte «IF SQL%NOTFOUND THEN …» ifadesini görmüştük. Eğer Explicit değil de Implicit Cursor kullanılacak ise değişken ismi yerine SQL yazılır.

15 Execute Immediate ile Dinamik Sorgular Sorgunun yazıldığı ve derlendiği anda sorgunun parse edilmesi için gerekli bilgilerin tamamı yoksa, bu bilgilerin bir kısmı çalışma anında (runtime) elde ediliyorsa bu tip sorgulara dinamik sorgular denir. ORACLE'da EXECUTE IMMEDIATE ifadesi ile sorgunun dinamik olarak çalıştırılması mümkündür. Dinamik SQL hakkında detaylı bilgi için: Database Programming with PL/SQL, Section 12, Lesson 1, Using Dynamic SQL

16 EXECUTE IMMEDIATE Örneği: Parametre olarak aldığı tablo adı, kolon adı ve kriter bilgilerine göre sorgu oluşturup sonucu döndüren fonksiyon CREATE OR REPLACE FUNCTION single_number_value ( table_in IN VARCHAR2, column_in IN VARCHAR2, where_in IN VARCHAR2) RETURN NUMBER IS l_return NUMBER; BEGIN EXECUTE IMMEDIATE 'SELECT ' || column_in || ' FROM ' || table_in || ' WHERE ' || where_in INTO l_return; RETURN l_return; END; BEGIN DBMS_OUTPUT.put_line ( single_number_value ( 'employees', 'salary', 'employee_id=138')); END;

17 CREATE FUNCTION del_rows(p_table_name VARCHAR2) RETURN NUMBER IS BEGIN EXECUTE IMMEDIATE 'DELETE FROM '||p_table_name; RETURN SQL%ROWCOUNT; END; DECLARE v_count NUMBER; BEGIN v_count := del_rows('EMPLOYEE_NAMES'); DBMS_OUTPUT.PUT_LINE(v_count|| ' rows deleted.'); END; EXECUTE IMMEDIATE Örneği: Parametre olarak ismini aldığı tablodaki tüm kayıtları silen ve sildiği kayıt sayısını döndüren fonksiyon

18 Prosedürden Geri Değer Döndürme Prosedürlerde parametrenin ismi ile veri tipi arasında seçimlik olarak parametre modu verilebilir. Verilebilecek 3 mod vardır (mod yazılmaz ise varsayılan olarak IN kabul edilir): – IN: Değeri prosedür içinde değiştirilemeyen girdi parametresi – OUT: Çağırana geri değer döndürebilen parametre – IN OUT: Girdi olarak aldığı değeri prosedür içinde değiştirip geri döndürebilen parametre Database Programming with PL/SQL, Section 8, Lesson 3, Passing Parameters

19 OUT parametresi ile değer döndürme CREATE PROCEDURE Ad_Soyad_Getir ( p_PNo IN Personel.PNo%TYPE, p_Ad OUT Personel.Ad%TYPE, p_Soyad OUT Personel.Soyad%TYPE) IS BEGIN SELECT Ad, Soyad INTO p_Ad, p_Soyad FROM Personel WHERE PNo = p_PNo; END; Ad_Soyad_Getir(178, a_Ad, a_Soyad); DBMS_OUTPUT.PUT_LINE(a_Ad || ' ' || a_Soyad);

20 IN OUT parametresi ile değer döndürme

21 Parametrelerin referans ile aktarımı: NOCOPY Veri yapıları dersinde gördüğünüz gibi bazen bir prosedürü çağırırken alacağı parametreyi değer ile değil referans ile veririz (call by value/reference). Her ne kadar değer ile çağırmak daha güvenli olsa da, parametrenin taşıyacağı değer çok büyük ise referans ile çağırmak bize hız kazandırır. PL/SQL’de IN türü parametreler varsayılan olarak referans ile çağırılırken OUT ve IN OUT parametreleri ise değer ile çağrılır. Eğer OUT veya IN OUT sonrasında NOCOPY yazılırsa onların da referans ile çağrılması mümkündür: TYPE t_emp IS TABLE OF employees%ROWTYPE; PROCEDURE emp_proc (p_small_arg IN NUMBER, p_big_arg OUT NOCOPY t_emp); Database Programming with PL/SQL, Section 12, Lesson 2, Improving PL/SQL Performance

22 Fonksiyon Tabanlı İndeksler SELECT * FROM Etkinlikler WHERE TO_CHAR(Tarih, 'month') = 'nisan'; Etkinlikler tablosundaki tarih alanı üzerinde index var olsa bile yukarıdaki sorguda TO_CHAR fonksiyonu kullanıldığı için bu indeks işe yaramaz. Aşağıdaki gibi fonksiyon tabanlı bir indeksin yaratılmış olması gereklidir: CREATE INDEX etkinlik_tar_ind ON Etkinlikler (TO_CHAR(Tarih, 'month')); Kendi oluşturduğumuz fonksiyonlar da eğer deterministik olarak tanımlanırlar ise indeks yaratmada kullanılabilir. Bunun için fonksiyon tanımında «RETURN NUMBER DETERMINISTIC IS» gibi bir ifade kullanmalıyız. – Bir bölümdeki personelin toplam maaşını döndüren bir fonksiyon, maaş değerleri değiştikçe farklı değer üreteceği için (non-deterministik), bu tip fonksiyonlar indeks için kullanılmaz.


"Veri Tabanı Yönetim Sistemleri 2 Ders 6 PL/SQL Ek Bilgiler Yrd. Doç. Dr. Altan MESUT Trakya Üniversitesi Bilgisayar Mühendisliği Bölümü." indir ppt

Benzer bir sunumlar


Google Reklamları