# PL/SQL Programlama Temelleri

> PL/SQL blok yapısı, değişkenler, denetim akışı, koleksiyonlar, kayıtlar, cursor, exception, procedure, function ve package temellerini derleyen ders notları.

- Author: Muhammet Ali Köker
- Language: tr
- Canonical: https://alikoker.com.tr/plsql-programlama-temelleri
- Translation: https://alikoker.com.tr/en/plsql-programming-fundamentals
- Published: 2015-02-07T17:25:00+03:00
- Modified: 2026-07-24T20:50:00+03:00
- Verified: 2026-08-08T15:00:00+03:00
- Type: article

PL/SQL bölümü başlangıçta veri tabanı ders notlarının devamıydı. Yordamsal programlama ayrıntıları SQL'in ilişkisel sorgu modelinden farklı bir düşünme biçimi gerektirdiği için burada ayrı bir yazı olarak tuttum. Blok yapısı, scope, cursor, exception ve altprogram konularındaki özgün sıralamayı korudum.

## Ünite 1: PL/SQL'e Giriş

### PL/SQL ile veri tabanı programlama

PL/SQL, Oracle'ın SQL'e eklediği yordamsal programlama dilidir.

SQL bildirimseldir. PL/SQL ise SQL deyimlerini:

- değişkenler,
- koşullar,
- döngüler,
- hata yönetimi,
- yordamlar,
- fonksiyonlar,
- paketler

ile birleştirir.

PL/SQL'in temel kullanım alanı veri tabanına yakın iş mantığının tanımlanmasıdır.

### Blok türleri

PL/SQL'in temel çalışma birimi **blok**tur.

Bloklar:

- anonim blok,
- saklı yordam,
- saklı fonksiyon,
- paket,
- tetikleyici

gibi yapılarda kullanılabilir.

Dersin ana odağı anonim bloklar, yordamlar, fonksiyonlar ve paketlerdir.

### PL/SQL program yapısı

Temel blok:

```sql
DECLARE
    -- bildirimler
BEGIN
    -- çalıştırılabilir deyimler
EXCEPTION
    -- hata işleyicileri
END;
/
```

`DECLARE` ve `EXCEPTION` bölümleri duruma göre kullanılmayabilir. `BEGIN` ve `END` çalıştırılabilir bölümün temelidir.

### Blokların çalıştırılması

PL/SQL blokları Oracle istemci araçlarından çalıştırılabilir.

Ders notlarında SQL*Plus temel arayüz olarak ele alınır. Günümüzde SQL*Plus halen kullanılabilir; bunun yanında SQLcl, SQL Developer ve farklı istemci araçları da aynı veri tabanı motoruyla çalışabilir.

Önemli olan istemci aracı değil, SQL ve PL/SQL kodunun sunucuda geçerli sözdizimi ve çalışma modelidir.

### SQL ve PL/SQL dosyaları

SQL ve PL/SQL komutları dosyalarda saklanıp tekrar çalıştırılabilir.

Bu yaklaşım:

- tekrarlanabilirlik,
- sürüm kontrolü,
- gözden geçirme,
- dağıtım otomasyonu

açısından etkileşimli komut girişinden daha güvenlidir.

### Değişkenler ve sabitler

PL/SQL değişkenleri bildirim bölümünde tanımlanır.

```sql
DECLARE
    v_ad VARCHAR2(100);
    v_sayac NUMBER := 0;
BEGIN
    NULL;
END;
/
```

Sabit:

```sql
c_kdv CONSTANT NUMBER := 0.20;
```

### SQL deyimlerinin PL/SQL içinde kullanımı

PL/SQL içinde SQL doğrudan çalıştırılabilir.

Tek satır beklenen sorguda:

```sql
SELECT AD, UCRET
INTO v_ad, v_ucret
FROM PERSONEL
WHERE PERSONEL_NO = 100;
```

Kardinalite önemlidir. Sorgu sıfır veya birden fazla satır döndürürse istisna oluşabilir.

### DML kullanımı

```sql
UPDATE PERSONEL
SET UCRET = UCRET * 1.10
WHERE BOLUM_NO = 20;
```

PL/SQL bloğu içindeki DML mevcut transaction bağlamında çalışır.

### Transaction deyimleri

Gerektiğinde:

```sql
COMMIT;
ROLLBACK;
```

kullanılabilir.

Ancak yeniden kullanılabilir yordamların kendi başına `COMMIT` yapıp yapmaması mimari bir karardır. Transaction sınırı çoğu uygulamada üst katmanın sorumluluğunda tutulur.

### Bağlı değişkenler

Bind variable, SQL metni ile değerleri ayırır.

Kavramsal olarak:

```text
SQL yapısı + parametre değerleri
```

şeklinde düşünülmelidir.

Bağlı değişkenler:

- SQL enjeksiyonu riskini azaltmada,
- sorgu ayrıştırma maliyetini düşürmede,
- plan paylaşımında

önemli olabilir.

### Bildirimler bölümü

`DECLARE` bölümünde:

- değişken,
- sabit,
- tür,
- cursor,
- yerel yordam,
- exception

tanımlanabilir.

### Varsayılan değerler

```sql
v_sayac NUMBER := 0;
```

veya uygun bağlamda `DEFAULT` kullanılabilir.

### NULL denetimi

PL/SQL'de de SQL'in üç değerli mantığına dikkat edilmelidir.

```sql
IF v_deger IS NULL THEN
    ...
END IF;
```

### %TYPE

`%TYPE`, değişken tipini tablo sütunundan türetir.

```sql
v_ucret PERSONEL.UCRET%TYPE;
```

Sütun tipi değiştiğinde kodun veri tipi tanımıyla uyumunu korumayı kolaylaştırır.

### %ROWTYPE

Bir tablonun veya cursor sonucunun tüm satır yapısını kayıt tipi olarak kullanır.

```sql
v_personel PERSONEL%ROWTYPE;
```

Alanlara:

```sql
v_personel.AD
v_personel.UCRET
```

biçiminde erişilebilir.

### Veri türleri

PL/SQL:

- sayısal,
- karakter,
- tarih-zaman,
- Boolean,
- record,
- collection

gibi türler sağlar.

SQL veri tipleriyle PL/SQL veri tipleri büyük ölçüde bütünleşmiştir ancak her tür SQL sütun tipi olarak kullanılamaz.

### İfadeler ve işleçler

PL/SQL:

- aritmetik,
- karşılaştırma,
- mantıksal

işleçleri destekler.

Koşullarda `NULL` semantiği dikkate alınmalıdır.

### Açıklama satırları

Tek satır:

```sql
-- açıklama
```

Çok satır:

```sql
/*
  açıklama
*/
```

Üretim kodunda yorumlar kodun kendisinden çıkarılamayan amacı veya özel gerekçeyi açıklamalıdır.

## Ünite 2: Program Denetimi

### IF deyimi

```sql
IF v_ucret > 50000 THEN
    ...
END IF;
```

Alternatif:

```sql
IF kosul THEN
    ...
ELSIF baska_kosul THEN
    ...
ELSE
    ...
END IF;
```

### Koşul gerçekleşmiyorsa

`ELSE`, diğer koşulların hiçbirinin gerçekleşmediği yolu tanımlar.

### İç içe IF

Bir `IF` bloğu başka bir `IF` bloğu içerebilir.

Derin iç içe yapı okunabilirliği azaltır. Mantıksal koşullar mümkün olduğunca sade tutulmalıdır.

### Temel LOOP

```sql
LOOP
    ...
END LOOP;
```

Çıkış koşulu yoksa sonsuz döngü oluşur.

### Koşulsuz çıkış

```sql
EXIT;
```

döngüyü sonlandırır.

### Koşullu çıkış

```sql
EXIT WHEN v_sayac >= 10;
```

### WHILE döngüsü

```sql
WHILE v_sayac < 10 LOOP
    v_sayac := v_sayac + 1;
END LOOP;
```

Koşul her iterasyon öncesinde değerlendirilir.

### FOR döngüsü

```sql
FOR i IN 1..10 LOOP
    ...
END LOOP;
```

Belirli aralıkta yineleme için uygundur.

### Döngü etiketleri

İç içe döngülerde belirli döngüyü isimlendirmek ve gerektiğinde açıkça hedeflemek için etiketler kullanılabilir.

### GOTO

PL/SQL `GOTO` deyimini destekler.

Ancak modern yapılandırılmış programlama yaklaşımında `IF`, `CASE`, döngüler ve altprogramlar çoğu durumda daha okunabilir akış sağlar. `GOTO` yalnız zorunlu ve açık gerekçesi olan durumlarda düşünülmelidir.

## Ünite 3: PL/SQL Koleksiyonları ve Kayıtları

### PL/SQL tabloları

Eski Oracle terminolojisindeki **PL/SQL table** kavramı güncel terminolojide ağırlıklı olarak **associative array** başlığı altında değerlendirilir.

Bir koleksiyon çok sayıda aynı tür değeri tek değişken altında tutar.

Kavramsal yapı:

```text
anahtar -> değer
```

### Koleksiyon tanımlama

Örnek:

```sql
DECLARE
    TYPE t_adlar IS TABLE OF VARCHAR2(100)
        INDEX BY PLS_INTEGER;

    v_adlar t_adlar;
BEGIN
    v_adlar(1) := 'Ali';
    v_adlar(2) := 'Ayse';
END;
/
```

### Koleksiyonların kullanımı

Elemanlar indeks üzerinden okunur ve değiştirilir.

Koleksiyonlar PL/SQL tarafında geçici veri kümelerini yönetmek için kullanışlıdır.

### Koleksiyon öznitelikleri

Yaygın collection method'ları arasında:

- `COUNT`,
- `FIRST`,
- `LAST`,
- `DELETE`,
- `EXISTS`,
- `NEXT`,
- `PRIOR`

bulunur.

### Eleman sayısı

```sql
v_adlar.COUNT
```

mevcut eleman sayısını verir.

### İlk ve son eleman

```sql
v_adlar.FIRST
v_adlar.LAST
```

mevcut indeks sınırlarını verir.

Seyrek koleksiyonlarda `1..COUNT` varsayımı her zaman doğru değildir.

### Eleman silme

```sql
v_adlar.DELETE(2);
```

belirli elemanı kaldırabilir.

### Kullanıcı tanımlı kayıtlar

PL/SQL record, farklı türde alanları tek mantıksal nesne altında toplar.

```sql
TYPE t_personel IS RECORD (
    personel_no NUMBER,
    ad VARCHAR2(100),
    ucret NUMBER
);
```

### Kayıt değişkeni

```sql
v_personel t_personel;
```

Alan erişimi:

```sql
v_personel.ad
```

### %ROWTYPE

Tablo satırını manuel olarak tekrar tanımlamak yerine:

```sql
v_personel PERSONEL%ROWTYPE;
```

kullanılabilir.

Bu yaklaşım veri tabanı şemasıyla tip uyumunu artırır.

## Ünite 4: İmleçler

### İmleç kavramı

Cursor, SQL deyiminin sonuç kümesi üzerinde satır satır işlem yapmaya yarayan PL/SQL mekanizmasıdır.

SQL mümkün olduğunca küme tabanlı kullanılmalıdır. Cursor, satır bazlı iş mantığı gerçekten gerektiğinde kullanılmalıdır.

### Örtük imleç

Oracle, DML ve tek satırlı SQL işlemleri için örtük cursor yönetimini otomatik yapar.

Örtük cursor ile ilgili durum bilgileri:

```text
SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT
SQL%ISOPEN
```

gibi özniteliklerle okunabilir.

### Belirtilmiş imleç

Birden fazla satır üzerinde kontrollü dolaşmak için explicit cursor tanımlanabilir.

```sql
CURSOR c_personel IS
SELECT PERSONEL_NO, AD, UCRET
FROM PERSONEL
WHERE BOLUM_NO = 20;
```

### Cursor çalışma sırası

Klasik explicit cursor yaşam döngüsü:

1. declare,
2. open,
3. fetch,
4. close.

### Cursor açma

```sql
OPEN c_personel;
```

Sorgu yürütme bağlamını hazırlar.

### Veri alma

```sql
FETCH c_personel
INTO v_personel_no, v_ad, v_ucret;
```

Her `FETCH` bir sonraki satırı alır.

### Cursor kapatma

```sql
CLOSE c_personel;
```

Kaynakları serbest bırakır.

### Cursor öznitelikleri

Explicit cursor için:

```text
c_personel%FOUND
c_personel%NOTFOUND
c_personel%ROWCOUNT
c_personel%ISOPEN
```

kullanılabilir.

### Cursor tabanlı kayıtlar

Cursor satır yapısı `%ROWTYPE` ile alınabilir.

```sql
v_kayit c_personel%ROWTYPE;
```

### Cursor FOR döngüsü

PL/SQL cursor açma, fetch ve kapatma işlemlerini otomatik yönetebilir.

```sql
FOR r IN (
    SELECT PERSONEL_NO, AD
    FROM PERSONEL
    WHERE BOLUM_NO = 20
) LOOP
    ...
END LOOP;
```

Basit cursor dolaşımlarında açık `OPEN/FETCH/CLOSE` kullanımından daha güvenlidir.

### Parametreli cursor

```sql
CURSOR c_personel(p_bolum_no NUMBER) IS
SELECT PERSONEL_NO, AD
FROM PERSONEL
WHERE BOLUM_NO = p_bolum_no;
```

Aynı sorgu farklı parametrelerle tekrar kullanılabilir.

## Ünite 5: Kural Dışı Durumların Denetlenmesi

### Exception yönetimi

PL/SQL çalışma zamanı hatalarını **exception** mekanizmasıyla yönetir.

Bir hata oluştuğunda normal akış durur ve uygun `EXCEPTION` işleyicisine geçilir.

```sql
BEGIN
    ...
EXCEPTION
    WHEN ... THEN
        ...
END;
/
```

Hata yönetimi güvenilir veri tabanı programlamasının temelidir.

### Önceden tanımlı hatalar

Oracle bazı hata durumlarını isimlendirilmiş exception olarak sunar.

Örneğin:

- `NO_DATA_FOUND`,
- `TOO_MANY_ROWS`,
- `ZERO_DIVIDE`,
- `DUP_VAL_ON_INDEX`.

```sql
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        ...
```

### Önceden tanımlı olmayan sunucu hataları

Belirli Oracle hata kodları kullanıcı tarafından isimlendirilmiş exception ile ilişkilendirilebilir.

Bu amaçla `PRAGMA EXCEPTION_INIT` kullanılabilir.

### Hata kodları

PL/SQL hata bağlamında:

```sql
SQLCODE
SQLERRM
```

ile hata kodu ve hata metni elde edilebilir.

Bu bilgiler loglama ve hata dönüşümünde kullanılabilir.

### Kullanıcı tanımlı exception

```sql
DECLARE
    e_gecersiz_ucret EXCEPTION;
BEGIN
    IF v_ucret < 0 THEN
        RAISE e_gecersiz_ucret;
    END IF;
EXCEPTION
    WHEN e_gecersiz_ucret THEN
        ...
END;
/
```

İşletme kuralları anlamlı exception'lara dönüştürülebilir.

### Hata yönetiminde transaction

Exception yakalanması transaction'ın otomatik olarak istenen şekilde sonuçlandırıldığı anlamına gelmez.

Hata durumunda:

- hangi değişikliklerin geri alınacağı,
- transaction'ın kim tarafından sonlandırılacağı,
- hatanın üst katmana aktarılıp aktarılmayacağı

tasarımın parçasıdır.

## Ünite 6: Altprogramlar

### Altprogram kavramı

PL/SQL'de yeniden kullanılabilir isimlendirilmiş kod bloklarına altprogram denir.

İki temel tür:

- procedure,
- function.

Altprogramlar:

- tekrar eden kodu azaltır,
- iş mantığını merkezileştirir,
- yetkilendirme sınırı oluşturabilir,
- uygulama ile veri tabanı arasında kararlı arayüz sağlayabilir.

### Ortak yapı

Bir altprogram:

- ad,
- parametreler,
- bildirimler,
- çalıştırılabilir bölüm,
- exception bölümü

içerebilir.

### Yordamlar

Procedure bir işi yerine getirir.

```sql
CREATE OR REPLACE PROCEDURE UCRET_GUNCELLE (
    p_personel_no IN NUMBER,
    p_yeni_ucret IN NUMBER
) AS
BEGIN
    UPDATE PERSONEL
    SET UCRET = p_yeni_ucret
    WHERE PERSONEL_NO = p_personel_no;
END;
/
```

### Anonim blok içindeki yordamlar

Bir procedure yalnız bulunduğu blok içinde kullanılmak üzere yerel tanımlanabilir.

Bu yöntem yardımcı işlemleri bölmek için kullanılabilir.

### Saklı yordamlar

Şema düzeyinde oluşturulan procedure veri tabanında derlenmiş nesne olarak saklanır.

Birden fazla uygulama aynı yordamı çağırabilir.

### Yordamların çalıştırılması

PL/SQL içinden:

```sql
BEGIN
    UCRET_GUNCELLE(100, 75000);
END;
/
```

çağrılabilir.

İstemci aracı ve sürücüye göre callable statement mekanizmaları da kullanılabilir.

### IN, OUT ve IN OUT parametreleri

`IN` yalnız giriş değeridir.

`OUT` yordamın dışarı değer vermesini sağlar.

`IN OUT` hem giriş hem çıkış amacıyla kullanılabilir.

API tasarımında parametre yönü açık tutulmalıdır.

### Fonksiyonlar

Function bir değer döndürür.

```sql
CREATE OR REPLACE FUNCTION YILLIK_UCRET (
    p_aylik_ucret IN NUMBER
) RETURN NUMBER AS
BEGIN
    RETURN p_aylik_ucret * 12;
END;
/
```

### Saklı fonksiyonlar

Şema düzeyindeki fonksiyonlar veri tabanı nesnesidir.

Uygun koşullarda SQL ifadeleri içinde de kullanılabilir.

Fonksiyonun yan etkileri ve SQL'den çağrılma kuralları Oracle semantiğine göre değerlendirilmelidir.

### Paketler

Package, ilişkili PL/SQL öğelerini tek şema nesnesi altında gruplar.

Bir paket:

- tipler,
- sabitler,
- değişkenler,
- cursor'lar,
- exception'lar,
- procedure'ler,
- function'lar

içerebilir.

### Paket belirtimi

**Package specification** dışarıdan görülebilen arayüzdür.

```sql
CREATE OR REPLACE PACKAGE PERSONEL_API AS
    PROCEDURE UCRET_GUNCELLE(
        p_personel_no IN NUMBER,
        p_yeni_ucret IN NUMBER
    );

    FUNCTION YILLIK_UCRET(
        p_aylik_ucret IN NUMBER
    ) RETURN NUMBER;
END PERSONEL_API;
/
```

### Paket gövdesi

**Package body**, arayüzde belirtilen altprogramların gerçekleştirimini içerir.

```sql
CREATE OR REPLACE PACKAGE BODY PERSONEL_API AS

    PROCEDURE UCRET_GUNCELLE(
        p_personel_no IN NUMBER,
        p_yeni_ucret IN NUMBER
    ) AS
    BEGIN
        UPDATE PERSONEL
        SET UCRET = p_yeni_ucret
        WHERE PERSONEL_NO = p_personel_no;
    END;

    FUNCTION YILLIK_UCRET(
        p_aylik_ucret IN NUMBER
    ) RETURN NUMBER AS
    BEGIN
        RETURN p_aylik_ucret * 12;
    END;

END PERSONEL_API;
/
```

Specification ile body ayrımı, arayüz ile gerçekleştirim ayrımını sağlar.

### Paketlerin kullanımı

Paket üyesi:

```sql
PERSONEL_API.UCRET_GUNCELLE(...)
```

biçiminde çağrılabilir.

Paketler özellikle ortak veri tabanı işlevlerini tek ad alanında toplamak için uygundur.

### Paketlerin tasarım değeri

İyi tasarlanmış paket:

- iç gerçekleştirim ayrıntılarını gizler,
- uygulamaya dar bir API sunar,
- tekrar kullanım sağlar,
- erişim yetkisinin paket düzeyinde verilmesine olanak tanır,
- ilgili fonksiyonları mantıksal olarak bir araya getirir.

Veri tabanı programlama katmanı büyüdükçe bağımsız yordamlar yerine tutarlı paket sınırları oluşturmak bakım maliyetini azaltabilir.

## Bu Çalışmaya Atıf

Köker, M. A. (2015). PL/SQL Programlama Temelleri. alikoker.com.tr. https://alikoker.com.tr/plsql-programlama-temelleri

- BibTeX: https://alikoker.com.tr/plsql-programlama-temelleri.bib
- RIS: https://alikoker.com.tr/plsql-programlama-temelleri.ris
- CSL-JSON: https://alikoker.com.tr/plsql-programlama-temelleri.csl.json
