Cursor Yaşam Döngüsü
Cursor (imleçleri) yönetmek için dört adım vardır. Aşağıdaki diyagram bir sql imlecin yaşam döngüsünü göstermektedir.Yaşam Döngüsü
Sırasıyla
- Tanımlamaları yap
- Cursor'ı aç
- Sonraki satıra geç
- Eğer ki sonraki satır yoksa Cursor'ı kapat şeklinde görsel yorumu yapabiliriz
Cursor'ın yaşam döngüsünü gördükten sonra SQL Server, Oracle, PostgreSQL ve MySQL için kullanımlarını inceleyelim.
Not: Tablomuzu çok sade bir şekilde tasarlayacağız, kurallar dahilinde değil de basit bir şekilde anlaşılabilir olmasına dikkat edeceğiz. Detaylar oldukça makale ve anlatım uzadığı için basit nitelikte tablo ile ilerleyeceğiz.
SQL Server Cursor Kullanımı
Öncelikle tablomuzu oluşturalım.SQL Server Tablo Oluşturalım
CREATE TABLE Urunler ( id INT PRIMARY KEY NOT NULL IDENTITY(1,1), urun_adi VARCHAR(100), alis_fiyati Decimal(10,2), satis_fiyati Decimal(10,2), kar_orani Decimal(10,2), kar_zarar_durumu VARCHAR(100) )
Tablomuz oluşturuldu, içerisine veriler ekleyelim. Çünkü Cursor ile verilerde satır satır dolaşıp çeşitli işlemler sonrası kar_orani ve kar_zarar_durumu kolonlarını güncelleyeceğiz.
SQL Server Tablo Verileri
INSERT INTO Urunler (urun_adi, alis_fiyati, satis_fiyati) VALUES ('Ütü Masası', 740, 810), ('Havlu', 285.60, 420.50), ('Çamaşır Makinesi', 8600, 10900), ('Buzdolabı', 12000, 12000), ('24 Ekran Monitör', 3000, 2000), ('Tişört', 175.80, 156.40), ('Yağmurluk', 499, 499), ('Spor Ayakkabı', 2800, 2690)
Tablomuzdaki verileri ekledik. Verilerle tablomuzun içeriğini görsel olarak paylaşalım.
Not: Görsel görüldüğü üzere kar_orani ve kar_zarar_durumu kolonları henüz değersiz (null) olarak gelmektedir. Cursor ile satır satır dolaştıktan sonra küçük bir yüzde hesaplaması ile kâr oranı belirlenip sonucunda ise kâr ve zarar durumu ilgili sütuna yazılacaktır.
SQL Server Tablo Verileri
SQL Server için Cursor (İmleç) örneğimizi hazırlayalım.
SQL Server Cursor Örnek
-- DECLARE ile tanımlamaları yapıyoruz. Veritabanından alacağımız değerleri karşıyalacağız, ardından hesaplama sonrası çıkan sonuçlar için değerleri de tanımlıyoruz. DECLARE @Id INT DECLARE @AlisFiyati DECIMAL(10,2) DECLARE @SatisFiyati DECIMAL(10,2) DECLARE @KarOrani DECIMAL(10,2) DECLARE @KarZararDurumu VARCHAR(100) DECLARE crsImlec CURSOR FOR -- Tablomuzdaki kayıtları çekiyoruz. Kolonların hepsini değil de işlem gerçekleştirmek istediklerimizi seçiyoruz. SELECT id, alis_fiyati, satis_fiyati, kar_orani, kar_zarar_durumu FROM Urunler -- Tanımlamış olduğumuz Cursor'ı açıyoruz OPEN crsImlec -- Sıradaki kayıt tanımladığımız imleç içine aktarılıp orada veri olarak tutulması sağlanıyor. -- Yani Select ile seçmiş olduğumuz tablo sütunları declare ile tanımladığımız değerlere aktarılıyor. FETCH NEXT FROM crsImlec INTO @Id, @AlisFiyati, @SatisFiyati, @KarOrani, @KarZararDurumu -- Sonraki kayıt var olana kadar döngü için alıyoruz. WHILE @@FETCH_STATUS = 0 BEGIN -- İlerlemiş olduğumuz her satırda alis_fiyati ile satis_fiyati kolonlarını karşılaştırıyoruz. -- Kâr-zarar belirlemek için koşulları yazalım. IF (@AlisFiyati < @SatisFiyati) BEGIN SET @KarOrani = (100 * (@SatisFiyati - @AlisFiyati) / @AlisFiyati) SET @KarZararDurumu = 'Bu satıştan kâr elde ettiniz' END ELSE IF (@AlisFiyati = @SatisFiyati) BEGIN SET @KarOrani = 0 SET @KarZararDurumu = 'Bu satıştan ne kâr ne de zarar elde ettiniz' END ELSE IF (@AlisFiyati > @SatisFiyati) BEGIN SET @KarOrani = NULL SET @KarZararDurumu = 'Bu satıştan zarar elde ettiniz' END -- Her satırda bulmuş olduğumuz @KarOrani ve @KarZararDurumu değerlerini tablodaki kolonları eşitliyoruz. UPDATE Urunler SET kar_orani = @KarOrani, kar_zarar_durumu = @KarZararDurumu WHERE id = @Id FETCH NEXT FROM crsImlec INTO @Id, @AlisFiyati, @SatisFiyati, @KarOrani, @KarZararDurumu END CLOSE crsImlec DEALLOCATE crsImlec
Cursor için hazırlamış olduğumuz sorguyu çalıştırdığımızda sonuç olarak kar_orani ve kar_zarar_durumu kolonlarının değerlerinin değiştiği görülmektedir.
SQL Server Cursor Sonrası Tablo Verileri
Benzer durumları Oracle veritabanı için yapalım.
Oracle Cursor Kullanımı
Öncelikle tablomuzu oluşturalım.Oracle Tablo Oluşturalım
CREATE TABLE URUNLER ( ID NUMBER(10) GENERATED BY DEFAULT AS IDENTITY, URUN_ADI VARCHAR2(100), ALIS_FIYATI NUMBER(10,2), SATIS_FIYATI NUMBER(10,2), KAR_ORANI NUMBER(10,2), KAR_ZARAR_DURUMU VARCHAR2(100), CONSTRAINT PK_URUNLER PRIMARY KEY(ID) )
Tablomuz oluşturuldu, içerisine veriler ekleyelim.
Oracle Tablo Verileri
INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Ütü Masası', 740, 810); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Havlu', 285.60, 420.50); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Çamaşır Makinesi', 8600, 10900); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Buzdolabı', 12000, 12000); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('24 Ekran Monitör', 3000, 2000); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Tişört', 175.80, 156.40); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Yağmurluk', 499, 499); INSERT INTO URUNLER (URUN_ADI, ALIS_FIYATI, SATIS_FIYATI) VALUES ('Spor Ayakkabı', 2800, 2690);
Tablomuzu oluşturduk ve içerisine verileri ekledik. KAR_ORANI ve KAR_ZARAR_DURUMU sütunları yine değersiz (null) şekilde gelmektedir.
Oracle Tablo Verileri
Oracle Cursor Örnek
SET SERVEROUTPUT ON; DECLARE UrunID NUMBER(10); AlisFiyati NUMBER(10,2); SatisFiyati NUMBER(10,2); KarOrani NUMBER(10,2); KarZararDurumu VARCHAR2(100); CURSOR crsImlec IS (SELECT ID, URUN_ADI, ALIS_FIYATI, SATIS_FIYATI FROM URUNLER); BEGIN FOR SATIR IN crsImlec LOOP UrunID := SATIR.ID; AlisFiyati := SATIR.ALIS_FIYATI; SatisFiyati := SATIR.SATIS_FIYATI; IF (AlisFiyati < SatisFiyati) THEN KarOrani := (100 * (SatisFiyati - AlisFiyati) / AlisFiyati); KarZararDurumu := 'Bu satıştan kâr elde ettiniz'; ELSIF (AlisFiyati = SatisFiyati) THEN KarOrani := 0; KarZararDurumu := 'Bu satıştan ne kâr ne de zarar elde ettiniz'; ELSIF (AlisFiyati > SatisFiyati) THEN KarOrani := NULL; KarZararDurumu := 'Bu satıştan zarar elde ettiniz'; END IF; UPDATE URUNLER SET KAR_ORANI = KarOrani, KAR_ZARAR_DURUMU = KarZararDurumu WHERE ID = UrunID; END LOOP; END;
Cursor için hazırlamış olduğumuz sorguyu çalıştırdığımızda benzer şekilde Oracle'da sonuç olarak KAR_ORANI ve KAR_ZARAR_DURUMU kolonlarının değerlerinin değiştiği görülmektedir.
Oracle Cursor Sonrası Tablo Verileri
PostgreSQL veritabanı için Cursor kullanımının örneklerini yapalım.
PostgreSQL Cursor Kullanımı
Öncelikle tablomuzu oluşturalım.PostgreSQL Tablo Oluşturalım
CREATE TABLE urunler ( id SERIAL PRIMARY KEY, urun_adi VARCHAR(100), alis_fiyati DECIMAL(10,2), satis_fiyati DECIMAL(10,2), kar_orani DECIMAL(10,2), kar_zarar_durumu VARCHAR(100) )
Tablomuz oluşturuldu, içerisine veriler ekleyelim.
PostgreSQL Tablo Verileri
INSERT INTO urunler (urun_adi, alis_fiyati, satis_fiyati) VALUES ('Ütü Masası', 740, 810), ('Havlu', 285.60, 420.50), ('Çamaşır Makinesi', 8600, 10900), ('Buzdolabı', 12000, 12000), ('24 Ekran Monitör', 3000, 2000), ('Tişört', 175.80, 156.40), ('Yağmurluk', 499, 499), ('Spor Ayakkabı', 2800, 2690)
Tablomuzu oluşturduk ve içerisine verileri ekledik. KAR_ORANI ve KAR_ZARAR_DURUMU sütunları yine değersiz (null) şekilde gelmektedir.
PostgreSQL Tablo Verileri
PostgreSQL Cursor Örnek
DO $$ DECLARE UrunID INT; AlisFiyati DECIMAL(10,2); SatisFiyati DECIMAL(10,2); KarOrani DECIMAL(10,2); KarZararDurumu VARCHAR(100); satir record; crsUrunler CURSOR FOR SELECT * FROM public.urunler; BEGIN OPEN crsUrunler; LOOP FETCH crsUrunler INTO satir; EXIT WHEN NOT FOUND; UrunID := satir.ID; AlisFiyati := satir.alis_fiyati; SatisFiyati := satir.satis_fiyati; IF (AlisFiyati < SatisFiyati) THEN KarOrani := (100 * (SatisFiyati - AlisFiyati) / AlisFiyati); KarZararDurumu := 'Bu satıştan kâr elde ettiniz'; ELSIF (AlisFiyati = SatisFiyati) THEN KarOrani := 0; KarZararDurumu := 'Bu satıştan ne kâr ne de zarar elde ettiniz'; ELSIF (AlisFiyati > SatisFiyati) THEN KarOrani := NULL; KarZararDurumu := 'Bu satıştan zarar elde ettiniz'; END IF; UPDATE urunler SET kar_orani = KarOrani, kar_zarar_durumu = KarZararDurumu WHERE id = UrunID; END LOOP; CLOSE crsUrunler; END; $$;
Cursor için hazırlamış olduğumuz sorguyu çalıştırdığımızda benzer şekilde PostgreSQL'de sonuç olarak kar_orani ve kar_zarar_durumu kolonlarının değerlerinin değiştiği görülmektedir.
PostgreSQL Cursor Sonrası Tablo Verileri
MySQL veritabanı için Cursor kullanımının örneklerini yapalım.
MySQL'de Cursor'ı Stored Procedure (Saklı Yordam) ve Function (Fonksiyon) içerisinde kullanabilmekteyiz.
MySQL Cursor Kullanımı
Öncelikle tablomuzu oluşturalım.MySQL Tablo Oluşturalım
CREATE TABLE urunler ( id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, urun_adi VARCHAR(100), alis_fiyati Decimal(10,2), satis_fiyati Decimal(10,2), kar_orani Decimal(10,2), kar_zarar_durumu VARCHAR(100) )
Tablomuz oluşturuldu, içerisine veriler ekleyelim.
MySQL Tablo Verileri
INSERT INTO urunler (urun_adi, alis_fiyati, satis_fiyati) VALUES ('Ütü Masası', 740, 810), ('Havlu', 285.60, 420.50), ('Çamaşır Makinesi', 8600, 10900), ('Buzdolabı', 12000, 12000), ('24 Ekran Monitör', 3000, 2000), ('Tişört', 175.80, 156.40), ('Yağmurluk', 499, 499), ('Spor Ayakkabı', 2800, 2690)
Tablomuzu oluşturduk ve içerisine verileri ekledik. kar_orani ve kar_zarar_durumu sütunları yine değersiz (null) şekilde gelmektedir.
MySQL Tablo Verileri
MySQL Cursor Örnek
CREATE PROCEDURE spKarZararCursor() BEGIN DECLARE crsTamamlandi INT DEFAULT 0; DECLARE UrunID INTEGER; DECLARE AlisFiyati Decimal(10,2); DECLARE SatisFiyati Decimal(10,2); DECLARE KarOrani Decimal(10,2); DECLARE KarZararDurumu VARCHAR(100); DECLARE crsCursor CURSOR FOR SELECT id, alis_fiyati, satis_fiyati FROM urunler; DECLARE CONTINUE HANDLER FOR NOT FOUND SET crsTamamlandi = 1; OPEN crsCursor; lpDongu: LOOP FETCH crsCursor INTO UrunID, AlisFiyati, SatisFiyati; IF (AlisFiyati < SatisFiyati) THEN SET KarOrani = (100 * (SatisFiyati - AlisFiyati) / AlisFiyati); SET KarZararDurumu = 'Bu satıştan kâr elde ettiniz'; ELSEIF (AlisFiyati = SatisFiyati) THEN SET KarOrani = 0; SET KarZararDurumu = 'Bu satıştan ne kâr ne de zarar elde ettiniz'; ELSEIF (AlisFiyati > SatisFiyati) THEN SET KarOrani = NULL; SET KarZararDurumu = 'Bu satıştan zarar elde ettiniz'; END IF; UPDATE urunler SET kar_orani = KarOrani, kar_zarar_durumu = KarZararDurumu WHERE id = UrunID; IF crsTamamlandi = 1 THEN LEAVE lpDongu; END IF; END LOOP; CLOSE crsCursor; END;
Prosedürü oluşturduk. Veritabanı içerisinde prosedürü görüntüleyelim.
Oluşturmuş Olduğumuz Stored Procedure
Prosedürü çalıştırınca urunler tablosu için hazırladığımız Cursor çalışacak ve ardından uygun koşullara göre kar_orani ve kar_zarar_durumu kolonlarını güncelleyecektir.
MySQL Cursor Prosedürünü Çağıralım
CALL spKarZararCursor();
Prosedürü çağırdıktan sonra urunler tablosundaki güncellenen kolonların ekran görüntüsünü paylaşalım.