---
title: 'Yerleşik İşlevler'
source: 'https://academia.sh/tr/kurslar/sql-temelleri/yerlesik-islevler'
course: 'SQL Temelleri'
language: tr
updated: '2026-08-17T18:09:02+00:00'
license: 'CC BY-SA 4.0'
---

# Yerleşik İşlevler

Satır başına çalışan dizgi, sayı ve tarih işlevleri; karakter ile bayt uzunluğu ayrımı, tam sayı bölmesi ve tarih işlevlerinin standarda en uzak alan olması.

Önceki ders boş değeri dönüştüren üç yapıyı kullandı: `COALESCE`, `NULLIF` ve `CASE`.
Üçü de tek bir satırın değerlerini alıp tek bir değer üreten **skaler işlevlerdir**
(scalar function) — sonuç kümesinin satır sayısını değiştirmezler, yalnız sütun değerlerini
dönüştürürler.

Bu ders aynı ailenin geri kalanını kurar: metin, sayı ve tarih üzerinde çalışan yerleşik
işlevler. Ailenin öğretici tarafı yalnız ne yaptıkları değil, adlandırmalarının ne kadar
değişken olduğudur. Yerleşik işlevler, standart SQL ile motor lehçesinin en görünür
biçimde ayrıldığı alandır.

Aşağıdaki blok şemayı ve örnek veriyi kurar; dersin bütün sorguları bu blokta oluşturulan
`kutuphane.db` dosyası üzerinde çalışır.

```sh
rm -f kutuphane.db
sqlite3 kutuphane.db <<'SQL'
CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, sehir TEXT NOT NULL);
CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL,
                    basim_yili INTEGER, sube_id INTEGER REFERENCES sube(sube_id));
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL,
                  eposta TEXT, kayit_tarihi TEXT NOT NULL);
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL REFERENCES kitap(kitap_id),
                    uye_id INTEGER NOT NULL REFERENCES uye(uye_id), alis_tarihi TEXT NOT NULL,
                    iade_tarihi TEXT);
INSERT INTO sube VALUES (1,'Merkez','Ankara'),(2,'Bahçelievler','Ankara'),
  (3,'Kadıköy','İstanbul'),(4,'Konak','İzmir');
INSERT INTO kitap VALUES (1,'Körlük','José Saramago',1995,1),(2,'Tutunamayanlar','Oğuz Atay',1972,1),
  (3,'Kum Kitabı','Jorge Luis Borges',1975,2),(4,'Yaban','Yakup Kadri',1932,2),
  (5,'Sessiz Ev','Orhan Pamuk',1983,3),(6,'Anayurt Oteli','Yusuf Atılgan',NULL,3),
  (7,'Tehlikeli Oyunlar','Oğuz Atay',1973,NULL);
INSERT INTO uye VALUES (1,'Ayşe','Demir','ayse@ornek.test','2023-02-14'),
  (2,'Mehmet','Kaya','mehmet@ornek.test','2023-05-30'),(3,'Zeynep','Arslan',NULL,'2024-01-09'),
  (4,'Emre','Yıldız','emre@ornek.test','2024-03-22'),(5,'Selin','Aydın',NULL,'2024-11-05'),
  (6,'Burak','Şahin','burak@ornek.test','2025-01-18');
INSERT INTO odunc VALUES (1,1,1,'2025-01-10','2025-01-24'),(2,2,1,'2025-02-02','2025-02-20'),
  (3,1,2,'2025-02-11',NULL),(4,3,3,'2025-03-01','2025-03-15'),(5,4,3,'2025-03-18','2025-04-02'),
  (6,1,4,'2025-04-05','2025-04-19'),(7,5,4,'2025-04-21',NULL),(8,2,5,'2025-05-02','2025-05-30'),
  (9,7,1,'2025-05-14','2025-05-28'),(10,3,5,'2025-06-03',NULL),(11,6,2,'2025-06-11','2025-06-25'),
  (12,4,4,'2025-06-20','2025-07-04');
SQL
```

## Uzunluk: Karakter mi, Bayt mı

Metnin uzunluğunu veren işlev, ölçtüğü şey konusunda net olmalıdır. Bilgisayarlar Nasıl
Çalışır kursunda kurulan ayrım burada doğrudan görünür: bir karakter birden çok bayt
kaplayabilir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT LENGTH('Körlük') AS karakter, LENGTH(CAST('Körlük' AS BLOB)) AS bayt;
SQL
```

```
karakter  bayt
--------  ----
6         8   
```

Altı karakterlik sözcük sekiz bayt tutuyor: `ö` ve `ü` harflerinin her biri iki bayt.
Uzunluk işlevinin karakter mi bayt mı saydığı **motora göre değişir**; bazı motorlarda ayrı
adlarla iki işlev bulunur, bazılarında tipin metin mi ikili veri mi olduğuna bakılır.
Alan sınırı denetiminde bu ayrım doğrudan hataya dönüşür — karakterle ölçüp baytla saklayan
bir denetim, Türkçe metinde beklenenden erken taşar.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik, LENGTH(baslik) AS uzunluk FROM kitap ORDER BY uzunluk DESC, baslik;
SQL
```

```
baslik             uzunluk
-----------------  -------
Tehlikeli Oyunlar  17     
Tutunamayanlar     14     
Anayurt Oteli      13     
Kum Kitabı         10     
Sessiz Ev          9      
Körlük             6      
Yaban              5      
```

## Kesme, Arama, Değiştirme

Metnin bir parçasını almak için parça alma işlevi kullanılır. Standart yazım ile yaygın
yazım burada ayrılır.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT SUBSTRING('2024-01-09' FROM 1 FOR 4) AS yil;
SQL
```

```
Parse error near line 3: near "FROM": syntax error
  SELECT SUBSTRING('2024-01-09' FROM 1 FOR 4) AS yil;
                  error here ---^
```

Standarttaki `SUBSTRING(… FROM … FOR …)` yazımı bu motorda tanınmıyor. Motorun kabul
ettiği yazım, argümanları virgülle ayıran biçimdir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT ad, SUBSTR(kayit_tarihi,1,4) AS kayit_yili FROM uye ORDER BY uye_id;
SQL
```

```
ad      kayit_yili
------  ----------
Ayşe    2023      
Mehmet  2023      
Zeynep  2024      
Emre    2024      
Selin   2024      
Burak   2025      
```

Bir alt dizginin konumunu bulan işlevin adı da **motora göre değişir**. Standarttaki
`POSITION(… IN …)` yazımı yerine bu motorda ayrı adlı bir işlev bulunuyor.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT eposta, INSTR(eposta,'@') AS konum FROM uye WHERE eposta IS NOT NULL ORDER BY uye_id;
SQL
```

```
eposta             konum
-----------------  -----
ayse@ornek.test    5    
mehmet@ornek.test  7    
emre@ornek.test    5    
burak@ornek.test   6    
```

Konum `1`'den başlıyor. SQL'de dizgi konumları bir tabanlıdır; Programlama Temelleri
kursundaki sıfır tabanlı dizin alışkanlığı burada geçerli değildir ve bir kaydırma hatasının
sık kaynağıdır.

Değiştirme ve kırpma işlevleri daha az değişkendir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik, REPLACE(baslik,'Kitabı','Kitap') AS degistirilmis FROM kitap
WHERE baslik LIKE '%Kitab%';
SELECT '[' || TRIM('   Körlük   ') || ']' AS kirpilmis;
SQL
```

```
baslik      degistirilmis
----------  -------------
Kum Kitabı  Kum Kitap    
kirpilmis
---------
[Körlük] 
```

Kırpma işlevi öntanımlı olarak iki uçtaki boşlukları alır; hangi karakterlerin
kırpılacağını belirten ve yalnız bir uçtan kırpan biçimleri de vardır.

## Sayı İşlevleri ve Bölme

Sayısal işlevlerin çoğu tek biçimlidir, ama bölme davranışı ayrık durur.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT ABS(-7) AS mutlak, ROUND(2.555, 2) AS yuvarlak,
       17 % 5 AS kalan, 17 / 5 AS bolum, 17.0 / 5 AS ondalik;
SQL
```

```
mutlak  yuvarlak  kalan  bolum  ondalik
------  --------  -----  -----  -------
7       2.56      2      3      3.4    
```

`17 / 5` işlemi `3` verdi, `17.0 / 5` işlemi `3.4`. Bölmenin tam sayı mı ondalık mı
olduğunu belirleyen şey, işlenenlerin tipidir. Bu davranış **motora göre değişir**: bazı
motorlar iki tam sayının bölümünü de ondalık üretir. Taşınabilir yazım, bölmeden önce en az
bir işleneni ondalık tipe çevirmektir.

Kalan işleci de iki yazımla bulunabilir ve yazımlar aynı tipi üretmeyebilir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT 17 % 5 AS islecle, MOD(17,5) AS islevle;
SQL
```

```
islecle  islevle
-------  -------
2        2.0    
```

Aynı sayı, biri tam sayı diğeri ondalık olarak döndü. Sonuç bir karşılaştırmaya ya da
gruplamaya girecekse bu fark önemlidir.

Yuvarlamada da dikkat edilecek bir nokta var: ondalık sayılar ikilik gösterimde tam
karşılanamaz — Bilgisayarlar Nasıl Çalışır kursundaki kayan noktalı sayı dersinin sonucu
burada da geçerlidir. Parasal hesaplarda yuvarlama işlevine değil, ondalık tipe güvenilir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik, basim_yili, basim_yili % 10 AS son_hane FROM kitap
WHERE basim_yili IS NOT NULL ORDER BY kitap_id;
SQL
```

```
baslik             basim_yili  son_hane
-----------------  ----------  --------
Körlük             1995        5       
Tutunamayanlar     1972        2       
Kum Kitabı         1975        5       
Yaban              1932        2       
Sessiz Ev          1983        3       
Tehlikeli Oyunlar  1973        3       
```

## Tarih İşlevleri

Tarih, standardın en zayıf uygulandığı alandır. Standartta tarihten parça çıkarmak için bir
yükleme benzeri yazım, tarihe süre eklemek için ise bir aralık tipi tanımlıdır. İkisi de
her motorda bulunmaz.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT EXTRACT(YEAR FROM alis_tarihi) AS yil FROM odunc;
SQL
```

```
Parse error near line 3: near "FROM": syntax error
  SELECT EXTRACT(YEAR FROM alis_tarihi) AS yil FROM odunc;
                      ^--- error here
```

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT alis_tarihi + INTERVAL '14' DAY AS son_gun FROM odunc;
SQL
```

```
Parse error near line 3: near "DAY": syntax error
  SELECT alis_tarihi + INTERVAL '14' DAY AS son_gun FROM odunc;
                       error here ---^
```

İki standart yazım da bu motorda çalışmadı. Motorun sunduğu karşılıklar başka adlar taşıyor.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT odunc_id, alis_tarihi,
       strftime('%Y', alis_tarihi) AS yil,
       date(alis_tarihi,'+14 days')  AS son_gun
FROM odunc WHERE odunc_id <= 4 ORDER BY odunc_id;
SQL
```

```
odunc_id  alis_tarihi  yil   son_gun   
--------  -----------  ----  ----------
1         2025-01-10   2025  2025-01-24
2         2025-02-02   2025  2025-02-16
3         2025-02-11   2025  2025-02-25
4         2025-03-01   2025  2025-03-15
```

İki tarih arasındaki farkı gün cinsinden almak da motora özgü bir yazım gerektirir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT odunc_id, alis_tarihi, iade_tarihi,
       CAST(julianday(iade_tarihi) - julianday(alis_tarihi) AS INTEGER) AS gun
FROM odunc WHERE iade_tarihi IS NOT NULL AND odunc_id <= 5 ORDER BY odunc_id;
SQL
```

```
odunc_id  alis_tarihi  iade_tarihi  gun
--------  -----------  -----------  ---
1         2025-01-10   2025-01-24   14 
2         2025-02-02   2025-02-20   18 
4         2025-03-01   2025-03-15   14 
5         2025-03-18   2025-04-02   15 
```

Üçüncü ödünç kaydı listede yok: iade tarihi boş olduğu için fark hesaplanamaz ve koşul
onu eledi. Boş değer kuralı burada da işliyor.

Tarih işlevlerinin motora bağlılığı pratik bir sonuç doğurur: tarih hesabı sorgunun içine
gömüldüğünde sorgu taşınamaz hale gelir. Taşınabilirlik gerekiyorsa tarih aritmetiği ya
uygulama katmanına alınır ya da motora özgü kısmı tek bir yerde toplanır. Ayrıca tarih
sütununun saat dilimi taşıyıp taşımadığı da **motora ve tipe göre değişir**; saat dilimsiz
bir sütunda yapılan gün hesabı, saat dilimi sınırında bir gün kayabilir.

## Özet

- Skaler işlevler satır başına çalışır ve sonuç kümesinin satır sayısını değiştirmez.
- Uzunluk işlevinin karakter mi bayt mı saydığı motora bağlıdır; ASCII dışı metinde ikisi
  ayrışır.
- Dizgi konumları bir tabanlıdır; parça alma ve konum bulma işlevlerinin standart yazımı
  her motorda bulunmaz.
- Bölmenin tam sayı mı ondalık mı olacağını işlenenlerin tipi belirler ve bu davranış
  motora göre değişir.
- Tarih işlevleri standarttan en çok ayrılan alandır; parça çıkarma ve süre ekleme
  yazımları motordan motora değişir.
- Tarih hesabında boş değer kuralı sürer: bir ucu boş olan fark hesaplanamaz.

## Sonraki Adım

Buraya kadar bütün sorgular tek bir tablodan okudu. Oysa normalleştirilmiş bir şemada
anlamlı sorular tek tabloya sığmaz: "hangi üye hangi kitabı ödünç aldı" sorusunun yanıtı üç
tabloya dağılmıştır, çünkü ödünç tablosunda yalnız kimlikler var. Sonraki konu tabloları
birleştiren yan tümceyi kurar ve ilk dersi eşleşen satırların kesişimini — iç birleştirmeyi
— ele alır.
