Cursor

Cursor

Cursor
Explicit Cursors
5 Önemli konudan biri.

cursor ı birden fazla satırın tutulduğu değişken olarak tanımlayabiliriz. cursor dan alınan satırı bir değişkene atılması lazım “for r_employee in c_employee” cursor daki “employee_id, first_name, last_name” değerleri r_employee atanıyor.

3. kayıt alınmak istendiğinde if sayac =3 şeklinde şart konulur. hr şemasındaki tabloların kayıt sayılarını bulan bir cursor nasıl yazılır ? yapılabiliyorsa ciddi bir adım mış .
veri tabanında kaç tablo var ?
drop table emp purge
create table emp as select * from employees;
pk fk yi almıyor nn alıyor
alter table emp modify (last_name null) ; –not null constraintini null girilebilir yapıyor.
update emp set last_name=null; last_name lerin hepsini null (boş gibi bişiy) yapıyor.

Örnek: bu genel istek
emp nin last_name leri boş employees de last_nameler var. employees de ki last_name leri emp ye kopyalayabilir misin ?
employee_id unique olduğu için bu id ile eşleştiriyoruz.

–10 milyon kayıt da değişiklik yapılıyorsa commiti loop un içine kopyalamak lazım. Aksi takdir tüm değişikliği undo da yapar undo şişer 4GB den 20-30 GB ye çıkar. VT durur o kadar yer yoksa. Herşeyden sonra commit koymak da biraz yavaş olur. Tablodaki kayıt satılarına göre hareket etmek lazım. Employees tablosu cursor a alınır. Çünkü birinin verisi lazım, emp ye isim tablosu ekleniyor .
alter table emp drop column isim ;
alter table emp add (isim varchar2 (100) );
isim bölümüne ad soyad şeklinde yazdırılacak.

2. cursor parametre alan cursordır. 1. nin department_id sini alıyor o department_id sine sahip üyeleri getiriyor.

truncate : rollback yapılamayanı, redo kullanmaz.
select count(*) from emp ;

bu direk çalışamıyor (DDL,create drop,alter truncate ) dynamic sql istiyor.

Bu çalışmaz ; tablo ve kolon adı parametrik yollanamaz, değer parametrik yollanabilir.
select first_name, last_name from emp where employee_id = 45 ; burada sadece 45 i parametrik yollayabilirsiniz.
execute immeidate ile heryeri parametrik yollayabiliriz.

bu şekilde de çalıştırılabilir aynı sonucu verir.

Veri tabanındaki tabloların kayıt sayılarını bulma
Nelere ihtiyaç var : tablo isimleri, ve kayıt sayılarına

Bu şekilde de bulunabilir.

analyze table emp compute statistics;
Tablonun istatistiklerini tutar. Dynamic viewler de tutulur normalde bu komut ile güncellenir. Bu bilgi ne kadar güncel olursa VT o kadar doğru karar verir.
Oracle tablonun kayıt sayısını güncel olarak görebilmesi için istatistik toplaması gerekir. Bunu ya dbs yapar ya da user. 10 g de her saat kendisi yapar. 9i hiç yapmıyordu . Kayıt bilgisini güncel olarak bilemediği için örneğin 100 kayıt var sanıyor bu yüzden full scan yapıyor halbuki güncelleme yapılmıştı ve 1 milyon kayıt girilmişti . Kayıt sayısını bilse index kullanacak 10 dakikada getireceğine 30 sn de getirecek.

Bütün tablolara iki şekilde analyze işlemi yaptırabiliriz

1-
analyze table emp compute statistics;
analyze table employees compute statistics;
analyze table dept compute statistics;

bu şekilde tüm tabloları bir script dosyasına koyup çalıştırabiliriz.
select ‘analyze table ‘ || table_name|| ‘ compute statistics;’ from user_tables;
İle bu test elde edilip delimited txt olarak kayıt edilip istenildiğinde çalıştırıldı.
İstatistiklerin güncel olduğunu anlamak için aşağıdaki sorgu kullanılabilir.

select table_name , num_rows from user_tables;
Test için de select count(*) kullanılır.

2-execute immediate ile (dynamic sql ile)

Otomatik olarak bağlı olunan şemanın istatistiklerini toplar

Bir cursor ile num_rows u başka bir cursor ile count(*) ile çekip karşılaştırma plsql i yan yana yazdırıp denenebilir.

WHILE

rpad ile düzgün gözükmesi sağlanır. 25 karakter sayısı sonrasında ‘ ‘ arasına boşluk * vb işaretler konulabilir.

for ile bu işi çok daha kolay yapılabilir. cursor lara c_ ile başlamak karışmaması için faydalıdır.
insert into ile , kaç kayıt girildiğini
dbms_output.put_line(SQL%COUNT) ile olmazsa
dbms_output.put_line(SQL%ROWCOUNT) ile yazdırabiliriz

UPDATEABLE CURSORS
insert upda sırasında readconsistency için kilitlenen satır (row) ilk update yapandadır kilit comitlemediği (yada rollbak) için kilit kalkmamıştır sonradan update yapmak isteyen kilitlenir.
1. commit ettiğinde 2. nin de update i gerçekleşir.
Deadlock : kilitlenmenin iki katıdır . kilitlenme ile aynı şey deildir.
a kullanıcısı, b kullanıcısının kilitli kaydını güncellemeye çalışıyor
b kullanıcısı da a kullanıcısının kilitli kaydını güncellemeye çalışırsa
ikisi de kilitlenir.Bu durumda oracle ilkini deadlock hatası vererek atar.
2. , 1. nin commit/rollback etmesini bekler.

Bu sql cümlesi ile bütün kayıtların kilidi bu komutu çalıştıran kullanıcıya geçer. commit leyerek kilit çözülür.

Bu şekilde sadece salary kolonu kilitlenir. Çalıştıracağınız cursor sırasında güncelleme yapılmasını istenmiyorsa kullanılır.

salary ve last_name kolonları bu cursor kapanana kadar kilitli kalır.

Üzerinde bulunduğum kaydın maaşını 5000 yap. Bu aşağıdaki gibi de yapılabilir.
Tercih edilen ;

parametre alan Cursorlar da (Including Cursor Parameters ) for kullanmak daha avantajlısıdır. Ne sonsuz döngüye girer, ne de açık cursor unutulur. Açık cursor performans açısından tehlikeli olabilir. Cursor ı açık bırakmak sistemden kullanmaya devam etmektir. 50 kişi çağırsa 50 tane cursor açık kalacak. bir süre ram yetmicektir.

Bu şekilde declare bölümünde cursor tanımlamaya gerek kalmıyor.
Nested blocks

Örneğin proc da hata verdi proc un içinde exception ile hata yakalanırsa diğerleri çalışmaya devam eder.